diff options
430 files changed, 7413 insertions, 6986 deletions
diff --git a/Android.bp b/Android.bp index ffb4d3a6ff73..2318f7bbf73a 100644 --- a/Android.bp +++ b/Android.bp @@ -734,6 +734,7 @@ filegroup { "core/java/android/annotation/RequiresPermission.java", "core/java/android/annotation/SystemApi.java", "core/java/android/annotation/TestApi.java", + "core/java/com/android/internal/annotations/GuardedBy.java", ], } // Build ext.jar diff --git a/StubLibraries.bp b/StubLibraries.bp index 6927f4449054..0f805655b33d 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -340,7 +340,7 @@ java_library_static { } java_library_static { - name: "framework_module_app_stubs_current", + name: "android_module_app_stubs_current", srcs: [ ":module-app-api-stubs-docs", ], @@ -355,7 +355,7 @@ java_library_static { } java_library_static { - name: "framework_module_lib_stubs_current", + name: "android_module_lib_stubs_current", srcs: [ ":module-lib-api-stubs-docs", ], diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index ed5626a1acbc..69f4748548a7 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -77,7 +77,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -85,6 +84,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.server.AppStateTracker; import com.android.server.DeviceIdleInternal; @@ -1171,9 +1171,9 @@ public class JobSchedulerService extends com.android.server.SystemService jobStatus.enqueueWorkLocked(work); } - StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED, uId, null, jobStatus.getBatteryName(), - StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED, + FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__SCHEDULED, JobProtoEnums.STOP_REASON_CANCELLED, jobStatus.getStandbyBucket(), jobStatus.getJobId()); @@ -2567,7 +2567,8 @@ public class JobSchedulerService extends com.android.server.SystemService BatteryStatsInternal mBatteryStatsInternal = LocalServices.getService (BatteryStatsInternal.class); mBatteryStatsInternal.noteJobsDeferred(uid, counter.numDeferred(), sinceLast); - StatsLog.write_non_chained(StatsLog.DEFERRED_JOB_STATS_REPORTED, uid, null, + FrameworkStatsLog.write_non_chained( + FrameworkStatsLog.DEFERRED_JOB_STATS_REPORTED, uid, null, counter.numDeferred(), sinceLast); } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index dbdce70dda03..f706260edec2 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -32,10 +32,10 @@ import android.text.format.DateFormat; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.job.GrantedUriPermissions; import com.android.server.job.JobSchedulerInternal; @@ -1059,10 +1059,12 @@ public final class JobStatus { mReadyDynamicSatisfied = mDynamicConstraints == (satisfiedConstraints & mDynamicConstraints); if (STATS_LOG_ENABLED && (STATSD_CONSTRAINTS_TO_LOG & constraint) != 0) { - StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED, + FrameworkStatsLog.write_non_chained( + FrameworkStatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED, sourceUid, null, getBatteryName(), getProtoConstraint(constraint), - state ? StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__SATISFIED - : StatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED); + state ? FrameworkStatsLog.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__SATISFIED + : FrameworkStatsLog + .SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED); } return true; } diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp index 09ca1d257460..1f9f18cd051a 100644 --- a/apex/statsd/Android.bp +++ b/apex/statsd/Android.bp @@ -19,8 +19,9 @@ apex { } apex_defaults { - // libc.so and libcutils.so are included in the apex - // native_shared_libs: ["libc", "libcutils"], + native_shared_libs: [ + "libstats_jni", + ], // binaries: ["vold"], java_libs: [ "framework-statsd", @@ -44,3 +45,33 @@ android_app_certificate { // com.android.os.statsd.pk8 (the private key) certificate: "com.android.os.statsd", } + + +// JNI library for StatsLog.write +cc_library_shared { + name: "libstats_jni", + srcs: ["jni/**/*.cpp"], + shared_libs: [ + "libnativehelper", // Has stable abi - should not be copied into apex. + "liblog", // Has a stable abi - should not be copied into apex. + ], + static_libs: [ + //TODO: make shared - need libstatssocket to also live in the apex. + "libstatssocket", + "libcutils", // TODO: remove - needed by libstatssocket + ], + //TODO: is libc++_static correct? + stl: "libc++_static", + cflags: [ + "-Wall", + "-Werror", + "-Wextra", + "-Wno-unused-parameter", + ], + apex_available: [ + "com.android.os.statsd", + "test_com.android.os.statsd", + //TODO (b/148620413): remove platform. + "//apex_available:platform", + ], +}
\ No newline at end of file diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp index f66f0340edab..231c91026bb6 100644 --- a/apex/statsd/framework/Android.bp +++ b/apex/statsd/framework/Android.bp @@ -34,9 +34,8 @@ java_library { ], libs: [ "framework-annotations-lib", - // TODO(b/146230220): Use framework-system-stubs instead. - //"android_system_stubs_current", - //"framework_module_lib_stubs_current", + // TODO(b/146230220): Use android_module_lib_stubs_current instead. + //"android_module_lib_stubs_current", "framework-all", ], hostdex: true, // for hiddenapi check diff --git a/core/jni/android_util_StatsLog.cpp b/apex/statsd/jni/android_util_StatsLog.cpp index 9225fc2839d0..9d410eb1f836 100644 --- a/core/jni/android_util_StatsLog.cpp +++ b/apex/statsd/jni/android_util_StatsLog.cpp @@ -17,12 +17,9 @@ #define LOG_NAMESPACE "StatsLog.tag." #define LOG_TAG "StatsLog_println" -#include <assert.h> - #include "jni.h" +#include <log/log.h> #include <nativehelper/JNIHelp.h> -#include "utils/misc.h" -#include "core_jni_helpers.h" #include "stats_buffer_writer.h" namespace android { @@ -57,7 +54,27 @@ static const JNINativeMethod gMethods[] = { int register_android_util_StatsLog(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/util/StatsLog", gMethods, NELEM(gMethods)); + return jniRegisterNativeMethods(env, "android/util/StatsLog", gMethods, NELEM(gMethods)); } - }; // namespace android + +/* + * JNI Initialization + */ +jint JNI_OnLoad(JavaVM* jvm, void* reserved) { + JNIEnv* e; + int status; + + ALOGV("statsd : loading JNI\n"); + // Check JNI version + if (jvm->GetEnv((void**)&e, JNI_VERSION_1_4)) { + ALOGE("JNI version mismatch error"); + return JNI_ERR; + } + status = android::register_android_util_StatsLog(e); + if (status < 0) { + ALOGE("jni statsd registration failure, status: %d", status); + return JNI_ERR; + } + return JNI_VERSION_1_4; +} diff --git a/api/current.txt b/api/current.txt index 32fb1e7e8bfd..562d47e792ca 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9990,7 +9990,7 @@ package android.content { method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display); method @NonNull public android.content.Context createFeatureContext(@Nullable String); method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException; - method @NonNull public android.content.Context createWindowContext(int); + method @NonNull public android.content.Context createWindowContext(int, @Nullable android.os.Bundle); method public abstract String[] databaseList(); method public abstract boolean deleteDatabase(String); method public abstract boolean deleteFile(String); @@ -31129,11 +31129,6 @@ package android.net.wifi { field @Deprecated public static final String[] strings; } - @Deprecated public static class WifiConfiguration.SuiteBCipher { - field @Deprecated public static final int ECDHE_ECDSA = 0; // 0x0 - field @Deprecated public static final int ECDHE_RSA = 1; // 0x1 - } - public class WifiEnterpriseConfig implements android.os.Parcelable { ctor public WifiEnterpriseConfig(); ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig); @@ -31616,6 +31611,7 @@ package android.net.wifi.hotspot2 { method public android.net.wifi.hotspot2.pps.Credential getCredential(); method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp(); method public long getSubscriptionExpirationTimeInMillis(); + method @NonNull public String getUniqueId() throws java.lang.IllegalStateException; method public boolean isOsuProvisioned(); method public void setCredential(android.net.wifi.hotspot2.pps.Credential); method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp); @@ -36944,7 +36940,7 @@ package android.os { ctor public VibrationAttributes.Builder(); ctor public VibrationAttributes.Builder(@Nullable android.os.VibrationAttributes); method @NonNull public android.os.VibrationAttributes build(); - method @NonNull public android.os.VibrationAttributes.Builder replaceFlags(int); + method @NonNull public android.os.VibrationAttributes.Builder setFlags(int, int); method @NonNull public android.os.VibrationAttributes.Builder setUsage(int); } @@ -47070,8 +47066,8 @@ package android.telephony { } public class MmsManager { - method public void downloadMultimediaMessage(int, @NonNull String, @NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent); - method public void sendMultimediaMessage(int, @NonNull android.net.Uri, @Nullable String, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent); + method public void downloadMultimediaMessage(int, @NonNull String, @NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long); + method public void sendMultimediaMessage(int, @NonNull android.net.Uri, @Nullable String, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long); } @Deprecated public class NeighboringCellInfo implements android.os.Parcelable { @@ -51776,7 +51772,7 @@ package android.view { method public int getFlags(); method public android.view.Display.HdrCapabilities getHdrCapabilities(); method @Deprecated public int getHeight(); - method public void getMetrics(android.util.DisplayMetrics); + method @Deprecated public void getMetrics(android.util.DisplayMetrics); method public android.view.Display.Mode getMode(); method public String getName(); method @Deprecated public int getOrientation(); @@ -51785,10 +51781,10 @@ package android.view { method public long getPresentationDeadlineNanos(); method public void getRealMetrics(android.util.DisplayMetrics); method public void getRealSize(android.graphics.Point); - method public void getRectSize(android.graphics.Rect); + method @Deprecated public void getRectSize(android.graphics.Rect); method public float getRefreshRate(); method public int getRotation(); - method public void getSize(android.graphics.Point); + method @Deprecated public void getSize(android.graphics.Point); method public int getState(); method public android.view.Display.Mode[] getSupportedModes(); method @Deprecated public float[] getSupportedRefreshRates(); diff --git a/api/system-current.txt b/api/system-current.txt index 0596b3d41eba..d7a591dfa508 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1604,7 +1604,7 @@ package android.bluetooth { } public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile { - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); + method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); } public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile { @@ -4484,11 +4484,11 @@ package android.media.session { } public static interface MediaSessionManager.OnMediaKeyEventDispatchedListener { - method public default void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token); + method public void onMediaKeyEventDispatched(@NonNull android.view.KeyEvent, @NonNull String, @Nullable android.media.session.MediaSession.Token); } public static interface MediaSessionManager.OnMediaKeyEventSessionChangedListener { - method public default void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token); + method public void onMediaKeyEventSessionChanged(@NonNull String, @Nullable android.media.session.MediaSession.Token); } public static interface MediaSessionManager.OnMediaKeyListener { @@ -6233,7 +6233,7 @@ package android.net { } public abstract class NetworkAgent { - ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); + ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkScore, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); method @Nullable public android.net.Network getNetwork(); method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); method public void onAutomaticReconnectDisabled(); @@ -6248,7 +6248,7 @@ package android.net { method @NonNull public android.net.Network register(); method public void sendLinkProperties(@NonNull android.net.LinkProperties); method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); - method public void sendNetworkScore(int); + method public void sendNetworkScore(@NonNull android.net.NetworkScore); method public void sendSocketKeepaliveEvent(int, int); method public void setConnected(); method @Deprecated public void setLegacyExtraInfo(@Nullable String); @@ -6351,6 +6351,55 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); } + public final class NetworkScore implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.NetworkScore.Metrics getEndToEndMetrics(); + method @NonNull public android.net.NetworkScore.Metrics getLinkLayerMetrics(); + method public int getRange(); + method @IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH, to=android.net.NetworkScore.MAX_SIGNAL_STRENGTH) public int getSignalStrength(); + method public boolean hasPolicy(int); + method public boolean isExiting(); + method @NonNull public android.net.NetworkScore withExiting(boolean); + method @NonNull public android.net.NetworkScore withSignalStrength(@IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH) int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkScore> CREATOR; + field public static final int MAX_SIGNAL_STRENGTH = 1000; // 0x3e8 + field public static final int MIN_SIGNAL_STRENGTH = 0; // 0x0 + field public static final int POLICY_DEFAULT_SUBSCRIPTION = 8; // 0x8 + field public static final int POLICY_IGNORE_ON_WIFI = 4; // 0x4 + field public static final int POLICY_LOCKDOWN_VPN = 1; // 0x1 + field public static final int POLICY_VPN = 2; // 0x2 + field public static final int RANGE_CLOSE = 1; // 0x1 + field public static final int RANGE_LONG = 4; // 0x4 + field public static final int RANGE_MEDIUM = 3; // 0x3 + field public static final int RANGE_SHORT = 2; // 0x2 + field public static final int RANGE_UNKNOWN = 0; // 0x0 + field public static final int UNKNOWN_SIGNAL_STRENGTH = -1; // 0xffffffff + } + + public static class NetworkScore.Builder { + ctor public NetworkScore.Builder(); + method @NonNull public android.net.NetworkScore.Builder addPolicy(int); + method @NonNull public android.net.NetworkScore build(); + method @NonNull public android.net.NetworkScore.Builder clearPolicy(int); + method @NonNull public android.net.NetworkScore.Builder setEndToEndMetrics(@NonNull android.net.NetworkScore.Metrics); + method @NonNull public android.net.NetworkScore.Builder setExiting(boolean); + method @NonNull public android.net.NetworkScore.Builder setLegacyScore(int); + method @NonNull public android.net.NetworkScore.Builder setLinkLayerMetrics(@NonNull android.net.NetworkScore.Metrics); + method @NonNull public android.net.NetworkScore.Builder setRange(int); + method @NonNull public android.net.NetworkScore.Builder setSignalStrength(@IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH, to=android.net.NetworkScore.MAX_SIGNAL_STRENGTH) int); + } + + public static class NetworkScore.Metrics { + ctor public NetworkScore.Metrics(@IntRange(from=android.net.NetworkScore.Metrics.LATENCY_UNKNOWN) int, @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) int, @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) int); + field public static final int BANDWIDTH_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.net.NetworkScore.Metrics EMPTY; + field public static final int LATENCY_UNKNOWN = -1; // 0xffffffff + field @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) public final int downlinkBandwidthKBps; + field @IntRange(from=android.net.NetworkScore.Metrics.LATENCY_UNKNOWN) public final int latencyMs; + field @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) public final int uplinkBandwidthKBps; + } + public class NetworkScoreManager { method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException; method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException; @@ -7580,7 +7629,7 @@ package android.net.wifi { method public boolean isEphemeral(); method public boolean isOsuAp(); method public boolean isPasspointAp(); - method @Nullable public static String removeDoubleQuotes(@Nullable String); + method @Nullable public static String sanitizeSsid(@Nullable String); field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00"; field public static final int INVALID_RSSI = -127; // 0xffffff81 } @@ -7622,7 +7671,6 @@ package android.net.wifi { method public boolean isApMacRandomizationSupported(); method public boolean isConnectedMacRandomizationSupported(); method @Deprecated public boolean isDeviceToDeviceRttSupported(); - method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean isDualModeSupported(); method public boolean isPortableHotspotSupported(); method public boolean isVerboseLoggingEnabled(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled(); @@ -8962,7 +9010,6 @@ package android.os { method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isSameProfileGroup(@NonNull android.os.UserHandle, @NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public boolean isUserNameSet(); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUserOfType(@NonNull String); - method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUserOfType(@NonNull android.os.UserHandle, @NonNull String); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isUserUnlockingOrUnlocked(@NonNull android.os.UserHandle); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle); method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException; diff --git a/api/test-current.txt b/api/test-current.txt index e0b5b34fd65f..1e81943705b4 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1688,6 +1688,55 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } + public final class NetworkScore implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.NetworkScore.Metrics getEndToEndMetrics(); + method @NonNull public android.net.NetworkScore.Metrics getLinkLayerMetrics(); + method public int getRange(); + method @IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH, to=android.net.NetworkScore.MAX_SIGNAL_STRENGTH) public int getSignalStrength(); + method public boolean hasPolicy(int); + method public boolean isExiting(); + method @NonNull public android.net.NetworkScore withExiting(boolean); + method @NonNull public android.net.NetworkScore withSignalStrength(@IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH) int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkScore> CREATOR; + field public static final int MAX_SIGNAL_STRENGTH = 1000; // 0x3e8 + field public static final int MIN_SIGNAL_STRENGTH = 0; // 0x0 + field public static final int POLICY_DEFAULT_SUBSCRIPTION = 8; // 0x8 + field public static final int POLICY_IGNORE_ON_WIFI = 4; // 0x4 + field public static final int POLICY_LOCKDOWN_VPN = 1; // 0x1 + field public static final int POLICY_VPN = 2; // 0x2 + field public static final int RANGE_CLOSE = 1; // 0x1 + field public static final int RANGE_LONG = 4; // 0x4 + field public static final int RANGE_MEDIUM = 3; // 0x3 + field public static final int RANGE_SHORT = 2; // 0x2 + field public static final int RANGE_UNKNOWN = 0; // 0x0 + field public static final int UNKNOWN_SIGNAL_STRENGTH = -1; // 0xffffffff + } + + public static class NetworkScore.Builder { + ctor public NetworkScore.Builder(); + method @NonNull public android.net.NetworkScore.Builder addPolicy(int); + method @NonNull public android.net.NetworkScore build(); + method @NonNull public android.net.NetworkScore.Builder clearPolicy(int); + method @NonNull public android.net.NetworkScore.Builder setEndToEndMetrics(@NonNull android.net.NetworkScore.Metrics); + method @NonNull public android.net.NetworkScore.Builder setExiting(boolean); + method @NonNull public android.net.NetworkScore.Builder setLegacyScore(int); + method @NonNull public android.net.NetworkScore.Builder setLinkLayerMetrics(@NonNull android.net.NetworkScore.Metrics); + method @NonNull public android.net.NetworkScore.Builder setRange(int); + method @NonNull public android.net.NetworkScore.Builder setSignalStrength(@IntRange(from=android.net.NetworkScore.UNKNOWN_SIGNAL_STRENGTH, to=android.net.NetworkScore.MAX_SIGNAL_STRENGTH) int); + } + + public static class NetworkScore.Metrics { + ctor public NetworkScore.Metrics(@IntRange(from=android.net.NetworkScore.Metrics.LATENCY_UNKNOWN) int, @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) int, @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) int); + field public static final int BANDWIDTH_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.net.NetworkScore.Metrics EMPTY; + field public static final int LATENCY_UNKNOWN = -1; // 0xffffffff + field @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) public final int downlinkBandwidthKBps; + field @IntRange(from=android.net.NetworkScore.Metrics.LATENCY_UNKNOWN) public final int latencyMs; + field @IntRange(from=android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN) public final int uplinkBandwidthKBps; + } + public class NetworkStack { field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK"; } diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index ac24a553b555..fdc7fce3b884 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -69,7 +69,6 @@ cc_defaults { "src/external/PowerStatsPuller.cpp", "src/external/PullResultReceiver.cpp", "src/external/puller_util.cpp", - "src/external/ResourceHealthManagerPuller.cpp", "src/external/StatsCallbackPuller.cpp", "src/external/StatsPuller.cpp", "src/external/StatsPullerManager.cpp", @@ -127,7 +126,6 @@ cc_defaults { "android.hardware.power@1.1", "libbase", "libcutils", - "libhealthhalutils", "liblog", "libplatformprotos", "libprotoutil", @@ -136,7 +134,6 @@ cc_defaults { "libsysutils", ], shared_libs: [ - "android.hardware.health@2.0", "libbinder", "libgraphicsenv", "libhidlbase", diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 4b336eeb703d..12058cae1a2a 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -180,7 +180,7 @@ message Atom { PhoneServiceStateChanged phone_service_state_changed = 94 [(module) = "framework"]; PhoneStateChanged phone_state_changed = 95 [(module) = "framework"]; UserRestrictionChanged user_restriction_changed = 96; - SettingsUIChanged settings_ui_changed = 97; + SettingsUIChanged settings_ui_changed = 97 [(module) = "settings"]; ConnectivityStateChanged connectivity_state_changed = 98 [(module) = "framework"]; // TODO: service state change is very noisy shortly after boot, as well // as at other transitions - coming out of doze, device plugged in, etc. @@ -226,14 +226,14 @@ message Atom { GnssNfwNotificationReported gnss_nfw_notification_reported = 131 [(module) = "framework"]; GnssConfigurationReported gnss_configuration_reported = 132 [(module) = "framework"]; UsbPortOverheatEvent usb_port_overheat_event_reported = 133; - NfcErrorOccurred nfc_error_occurred = 134; - NfcStateChanged nfc_state_changed = 135; - NfcBeamOccurred nfc_beam_occurred = 136; - NfcCardemulationOccurred nfc_cardemulation_occurred = 137; - NfcTagOccurred nfc_tag_occurred = 138; - NfcHceTransactionOccurred nfc_hce_transaction_occurred = 139; - SeStateChanged se_state_changed = 140; - SeOmapiReported se_omapi_reported = 141; + NfcErrorOccurred nfc_error_occurred = 134 [(module) = "nfc"]; + NfcStateChanged nfc_state_changed = 135 [(module) = "nfc"]; + NfcBeamOccurred nfc_beam_occurred = 136 [(module) = "nfc"]; + NfcCardemulationOccurred nfc_cardemulation_occurred = 137 [(module) = "nfc"]; + NfcTagOccurred nfc_tag_occurred = 138 [(module) = "nfc"]; + NfcHceTransactionOccurred nfc_hce_transaction_occurred = 139 [(module) = "nfc"]; + SeStateChanged se_state_changed = 140 [(module) = "secure_element"]; + SeOmapiReported se_omapi_reported = 141 [(module) = "secure_element"]; BroadcastDispatchLatencyReported broadcast_dispatch_latency_reported = 142 [(module) = "framework"]; AttentionManagerServiceResultReported attention_manager_service_result_reported = @@ -387,6 +387,9 @@ message Atom { 249 [(module) = "cellbroadcast"]; CellBroadcastMessageError cb_message_error = 250 [(module) = "cellbroadcast"]; + WifiHealthStatReported wifi_health_stat_reported = 251 [(module) = "wifi"]; + WifiFailureStatReported wifi_failure_stat_reported = 252 [(module) = "wifi"]; + WifiConnectionResultReported wifi_connection_result_reported = 253 [(module) = "wifi"]; } // Pulled events will start at field 10000. @@ -411,8 +414,8 @@ message Atom { CpuActiveTime cpu_active_time = 10016 [(module) = "framework"]; CpuClusterTime cpu_cluster_time = 10017 [(module) = "framework"]; DiskSpace disk_space = 10018 [deprecated=true]; - RemainingBatteryCapacity remaining_battery_capacity = 10019; - FullBatteryCapacity full_battery_capacity = 10020; + RemainingBatteryCapacity remaining_battery_capacity = 10019 [(module) = "framework"]; + FullBatteryCapacity full_battery_capacity = 10020 [(module) = "framework"]; Temperature temperature = 10021 [(module) = "framework"]; BinderCalls binder_calls = 10022 [(module) = "framework"]; BinderCallsExceptions binder_calls_exceptions = 10023 [(module) = "framework"]; @@ -422,7 +425,7 @@ message Atom { AppSize app_size = 10027 [(module) = "framework"]; CategorySize category_size = 10028 [(module) = "framework"]; ProcStats proc_stats = 10029 [(module) = "framework"]; - BatteryVoltage battery_voltage = 10030; + BatteryVoltage battery_voltage = 10030 [(module) = "framework"]; NumFingerprintsEnrolled num_fingerprints_enrolled = 10031 [(module) = "framework"]; DiskIo disk_io = 10032 [(module) = "framework"]; PowerProfile power_profile = 10033 [(module) = "framework"]; @@ -436,9 +439,9 @@ message Atom { DeviceCalculatedPowerBlameOther device_calculated_power_blame_other = 10041 [(module) = "framework"]; ProcessMemoryHighWaterMark process_memory_high_water_mark = 10042 [(module) = "framework"]; - BatteryLevel battery_level = 10043; + BatteryLevel battery_level = 10043 [(module) = "framework"]; BuildInformation build_information = 10044 [(module) = "framework"]; - BatteryCycleCount battery_cycle_count = 10045; + BatteryCycleCount battery_cycle_count = 10045 [(module) = "framework"]; DebugElapsedClock debug_elapsed_clock = 10046 [(module) = "framework"]; DebugFailingElapsedClock debug_failing_elapsed_clock = 10047 [(module) = "framework"]; NumFacesEnrolled num_faces_enrolled = 10048 [(module) = "framework"]; @@ -658,6 +661,81 @@ message CachedKillReported { } /** + * Logs the change in wifi health. + * + * Logged from: + * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiDataStall.java + */ +message WifiHealthStatReported { + // duration this stat is obtained over in milliseconds + optional int32 duration_millis = 1; + // whether wifi is classified as sufficient for the user's data traffic, determined + // by whether the calculated throughput exceeds the average demand within |duration_millis| + optional bool is_sufficient = 2; + // whether the calculated throughput is exceeds the minimum required for typical usage + optional bool is_throughput_good = 3; + // whether cellular data is available + optional bool is_cell_data_available = 4; + // the WLAN channel the connected network is on (ie. 2412) + optional int32 frequency = 5; +} + +/** + * Logged when wifi detects a significant change in connection failure rate. + * + * Logged from: frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiHealthMonitor.java + * + */ +message WifiFailureStatReported { + enum AbnormalityType { + UNKNOWN = 0; + SIGNIFICANT_INCREASE = 1; + SIGNIFICANT_DECREASE = 2; + SIMPLY_HIGH = 3; + } + enum FailureType { + FAILURE_UNKNOWN = 0; + FAILURE_CONNECTION = 1; + FAILURE_ASSOCIATION_REJECTION = 2; + FAILURE_ASSOCIATION_TIMEOUT = 3; + FAILURE_AUTHENTICATION = 4; + FAILURE_NON_LOCAL_DISCONNECTION = 5; + FAILURE_SHORT_CONNECTION_DUE_TO_NON_LOCAL_DISCONNECTION = 6; + } + // Reason for uploading this stat + optional AbnormalityType abnormality_type = 1; + // The particular type of failure + optional FailureType failure_type = 2; + // How many times we have encountered this combination of AbnormalityType and FailureType + optional int32 failure_count = 3; +} + +/** + * Logs whether a wifi connection is successful and reasons for failure if it isn't. + * + * Logged from: + * frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java + */ +message WifiConnectionResultReported { + enum FailureCode { + FAILURE_UNKNOWN = 0; + FAILURE_ASSOCIATION_TIMEOUT = 1; + FAILURE_ASSOCIATION_REJECTION = 2; + FAILURE_AUTHENTICATION_GENERAL = 3; + FAILURE_AUTHENTICATION_EAP = 4; + FAILURE_DHCP = 5; + FAILURE_NETWORK_DISCONNECTION = 6; + FAILURE_ROAM_TIMEOUT = 7; + } + // true represents a successful connection + optional bool connection_result = 1; + // reason for the connection failure + optional FailureCode failure_code = 2; + // scan rssi before the connection attempt + optional int32 rssi = 3; +} + +/** * Logs when memory stats of a process is reported. * * Logged from: diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp deleted file mode 100644 index 75b63f4b5f9e..000000000000 --- a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define DEBUG false // STOPSHIP if true -#include "Log.h" - -#include <android/hardware/health/2.0/IHealth.h> -#include <healthhalutils/HealthHalUtils.h> -#include "external/ResourceHealthManagerPuller.h" -#include "external/StatsPuller.h" - -#include "ResourceHealthManagerPuller.h" -#include "logd/LogEvent.h" -#include "stats_log_util.h" -#include "statslog.h" - -using android::hardware::hidl_vec; -using android::hardware::Return; -using android::hardware::Void; -using android::hardware::health::V2_0::get_health_service; -using android::hardware::health::V2_0::HealthInfo; -using android::hardware::health::V2_0::IHealth; -using android::hardware::health::V2_0::Result; - -using std::make_shared; -using std::shared_ptr; - -namespace android { -namespace os { -namespace statsd { - -sp<android::hardware::health::V2_0::IHealth> gHealthHal = nullptr; - -bool getHealthHal() { - if (gHealthHal == nullptr) { - gHealthHal = get_health_service(); - } - return gHealthHal != nullptr; -} - -ResourceHealthManagerPuller::ResourceHealthManagerPuller(int tagId) : StatsPuller(tagId) { -} - -// TODO(b/110565992): add other health atoms (eg. Temperature). -bool ResourceHealthManagerPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) { - if (!getHealthHal()) { - ALOGE("Health Hal not loaded"); - return false; - } - - int64_t wallClockTimestampNs = getWallClockNs(); - int64_t elapsedTimestampNs = getElapsedRealtimeNs(); - - data->clear(); - bool result_success = true; - - // Get the data from the Health HAL (hardware/interfaces/health/1.0/types.hal). - Return<void> ret = gHealthHal->getHealthInfo([&](Result r, HealthInfo v) { - if (r != Result::SUCCESS) { - result_success = false; - return; - } - if (mTagId == android::util::REMAINING_BATTERY_CAPACITY) { - auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY, - wallClockTimestampNs, elapsedTimestampNs); - ptr->write(v.legacy.batteryChargeCounter); - ptr->init(); - data->push_back(ptr); - } else if (mTagId == android::util::FULL_BATTERY_CAPACITY) { - auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY, - wallClockTimestampNs, elapsedTimestampNs); - ptr->write(v.legacy.batteryFullCharge); - ptr->init(); - data->push_back(ptr); - } else if (mTagId == android::util::BATTERY_VOLTAGE) { - auto ptr = make_shared<LogEvent>(android::util::BATTERY_VOLTAGE, wallClockTimestampNs, - elapsedTimestampNs); - ptr->write(v.legacy.batteryVoltage); - ptr->init(); - data->push_back(ptr); - } else if (mTagId == android::util::BATTERY_LEVEL) { - auto ptr = make_shared<LogEvent>(android::util::BATTERY_LEVEL, wallClockTimestampNs, - elapsedTimestampNs); - ptr->write(v.legacy.batteryLevel); - ptr->init(); - data->push_back(ptr); - } else if (mTagId == android::util::BATTERY_CYCLE_COUNT) { - auto ptr = make_shared<LogEvent>(android::util::BATTERY_CYCLE_COUNT, - wallClockTimestampNs, elapsedTimestampNs); - ptr->write(v.legacy.batteryCycleCount); - ptr->init(); - data->push_back(ptr); - } else { - ALOGE("Unsupported tag in ResourceHealthManagerPuller: %d", mTagId); - } - }); - if (!result_success || !ret.isOk()) { - ALOGE("getHealthHal() failed: health HAL service not available. Description: %s", - ret.description().c_str()); - if (!ret.isOk() && ret.isDeadObject()) { - gHealthHal = nullptr; - } - return false; - } - return true; -} - -} // namespace statsd -} // namespace os -} // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 85d1e38d6052..668c11ef55f5 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -34,7 +34,6 @@ #include "../statscompanion_util.h" #include "GpuStatsPuller.h" #include "PowerStatsPuller.h" -#include "ResourceHealthManagerPuller.h" #include "StatsCallbackPuller.h" #include "SubsystemSleepStatePuller.h" #include "TrainInfoPuller.h" @@ -62,26 +61,6 @@ StatsPullerManager::StatsPullerManager() // on_device_power_measurement {{.atomTag = android::util::ON_DEVICE_POWER_MEASUREMENT}, new PowerStatsPuller()}, - // remaining_battery_capacity - {{.atomTag = android::util::REMAINING_BATTERY_CAPACITY}, - new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}, - - // full_battery_capacity - {{.atomTag = android::util::FULL_BATTERY_CAPACITY}, - new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}, - - // battery_voltage - {{.atomTag = android::util::BATTERY_VOLTAGE}, - new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}, - - // battery_level - {{.atomTag = android::util::BATTERY_LEVEL}, - new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}, - - // battery_cycle_count - {{.atomTag = android::util::BATTERY_CYCLE_COUNT}, - new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}, - // TrainInfo. {{.atomTag = android::util::TRAIN_INFO}, new TrainInfoPuller()}, diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h index 0f33c56be42a..463a1b68f885 100644 --- a/cmds/statsd/src/logd/LogEvent.h +++ b/cmds/statsd/src/logd/LogEvent.h @@ -255,7 +255,15 @@ private: mValid = false; value = 0; // all primitive types can successfully cast 0 } else { - value = *((T*)mBuf); + // When alignof(T) == 1, hopefully the compiler can optimize away + // this conditional as always true. + if ((reinterpret_cast<uintptr_t>(mBuf) % alignof(T)) == 0) { + // We're properly aligned, and can safely make this assignment. + value = *((T*)mBuf); + } else { + // We need to use memcpy. It's slower, but safe. + memcpy(&value, mBuf, sizeof(T)); + } mBuf += sizeof(T); mRemainingLen -= sizeof(T); } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d8b5e7f3b5b0..f31c6148f89f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2873,7 +2873,13 @@ public class Activity extends ContextThemeWrapper } /** - * Called by the system when picture in picture mode should be entered if supported. + * This method is called by the system in various cases where picture in picture mode should be + * entered if supported. + * + * <p>It is up to the app developer to choose whether to call + * {@link #enterPictureInPictureMode(PictureInPictureParams)} at this time. For example, the + * system will call this method when the activity is being put into the background, so the app + * developer might want to switch an activity into PIP mode instead.</p> */ public void onPictureInPictureRequested() { // Previous recommendation was for apps to enter picture-in-picture in onUserLeaveHint() diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 136c84eaf543..04d3e39b29fc 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2373,13 +2373,13 @@ class ContextImpl extends Context { } @Override - public @NonNull WindowContext createWindowContext(int type) { + public @NonNull WindowContext createWindowContext(int type, Bundle options) { if (getDisplay() == null) { throw new UnsupportedOperationException("WindowContext can only be created from " + "other visual contexts, such as Activity or one created with " + "Context#createDisplayContext(Display)"); } - return new WindowContext(this, null /* token */, type); + return new WindowContext(this, null /* token */, type, options); } ContextImpl createBaseWindowContext(IBinder token) { @@ -2647,7 +2647,8 @@ class ContextImpl extends Context { overrideConfiguration, compatInfo, classLoader, - packageInfo.getApplication().getResources().getLoaders())); + packageInfo.getApplication() == null ? null + : packageInfo.getApplication().getResources().getLoaders())); context.mDisplay = resourcesManager.getAdjustedDisplay(displayId, context.getResources()); return context; diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 5f3bad6ad1a8..cb6a476fb617 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -287,7 +287,7 @@ interface IActivityManager { void killApplicationProcess(in String processName, int uid); // Special low-level communication with activity manager. boolean handleApplicationWtf(in IBinder app, in String tag, boolean system, - in ApplicationErrorReport.ParcelableCrashInfo crashInfo); + in ApplicationErrorReport.ParcelableCrashInfo crashInfo, int immediateCallerPid); @UnsupportedAppUsage void killBackgroundProcesses(in String packageName, int userId); boolean isUserAMonkey(); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 35d26aba9094..576b56fa33f6 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2487,6 +2487,20 @@ public class Notification implements Parcelable if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) { visitor.accept(Uri.parse(extras.getString(EXTRA_BACKGROUND_IMAGE_URI))); } + + ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST); + if (people != null && !people.isEmpty()) { + for (Person p : people) { + if (p.getIconUri() != null) { + visitor.accept(p.getIconUri()); + } + } + } + + final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON); + if (person != null && person.getIconUri() != null) { + visitor.accept(person.getIconUri()); + } } if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) { @@ -2495,6 +2509,11 @@ public class Notification implements Parcelable for (MessagingStyle.Message message : MessagingStyle.Message .getMessagesFromBundleArray(messages)) { visitor.accept(message.getDataUri()); + + Person senderPerson = message.getSenderPerson(); + if (senderPerson != null && senderPerson.getIconUri() != null) { + visitor.accept(senderPerson.getIconUri()); + } } } @@ -2503,6 +2522,11 @@ public class Notification implements Parcelable for (MessagingStyle.Message message : MessagingStyle.Message .getMessagesFromBundleArray(historic)) { visitor.accept(message.getDataUri()); + + Person senderPerson = message.getSenderPerson(); + if (senderPerson != null && senderPerson.getIconUri() != null) { + visitor.accept(senderPerson.getIconUri()); + } } } } diff --git a/core/java/android/app/Person.java b/core/java/android/app/Person.java index 14a5589c04c2..63ef2484ca1d 100644 --- a/core/java/android/app/Person.java +++ b/core/java/android/app/Person.java @@ -19,6 +19,7 @@ package android.app; import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.drawable.Icon; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -122,6 +123,20 @@ public final class Person implements Parcelable { return ""; } + /** + * @return the URI associated with the {@link #getIcon()} for this person, iff the icon exists + * and is URI based. + * @hide + */ + @Nullable + public Uri getIconUri() { + if (mIcon != null && (mIcon.getType() == Icon.TYPE_URI + || mIcon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { + return mIcon.getUri(); + } + return null; + } + @Override public boolean equals(Object obj) { if (obj instanceof Person) { diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 736efb6a5e69..cbd2f1a52c0c 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -297,9 +297,10 @@ public abstract class PropertyInvalidatedCache<Query, Result> { if (currentNonce == NONCE_DISABLED || currentNonce == NONCE_UNSET) { if (DEBUG) { Log.d(TAG, - String.format("cache %s for %s", + String.format("cache %s %s for %s", + cacheName(), currentNonce == NONCE_DISABLED ? "disabled" : "unset", - query)); + queryToString(query))); } return recompute(query); } @@ -310,7 +311,8 @@ public abstract class PropertyInvalidatedCache<Query, Result> { } else { if (DEBUG) { Log.d(TAG, - String.format("clearing cache because nonce changed [%s] -> [%s]", + String.format("clearing cache %s because nonce changed [%s] -> [%s]", + cacheName(), mLastSeenNonce, currentNonce)); } mCache.clear(); @@ -328,13 +330,15 @@ public abstract class PropertyInvalidatedCache<Query, Result> { final Result refreshedResult = refresh(cachedResult, query); if (refreshedResult != cachedResult) { if (DEBUG) { - Log.d(TAG, "cache refresh for " + query); + Log.d(TAG, "cache refresh for " + cacheName() + " " + queryToString(query)); } final long afterRefreshNonce = getCurrentNonce(); if (currentNonce != afterRefreshNonce) { currentNonce = afterRefreshNonce; if (DEBUG) { - Log.d(TAG, "restarting query because nonce changed in refresh"); + Log.d(TAG, String.format("restarting %s %s because nonce changed in refresh", + cacheName(), + queryToString(query))); } continue; } @@ -352,13 +356,13 @@ public abstract class PropertyInvalidatedCache<Query, Result> { return maybeCheckConsistency(query, refreshedResult); } if (DEBUG) { - Log.d(TAG, "cache hit for " + query); + Log.d(TAG, "cache hit for " + cacheName() + " " + queryToString(query)); } return maybeCheckConsistency(query, cachedResult); } // Cache miss: make the value from scratch. if (DEBUG) { - Log.d(TAG, "cache miss for " + query); + Log.d(TAG, "cache miss for " + cacheName() + " " + queryToString(query)); } final Result result = recompute(query); synchronized (mLock) { @@ -451,4 +455,20 @@ public abstract class PropertyInvalidatedCache<Query, Result> { } return proposedResult; } + + /** + * Return the name of the cache, to be used in debug messages. The + * method is public so clients can use it. + */ + public String cacheName() { + return mPropertyName; + } + + /** + * Return the query as a string, to be used in debug messages. The + * method is public so clients can use it in external debug messages. + */ + public String queryToString(Query query) { + return Objects.toString(query); + } } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 59c171923f2b..65a5f6b19cd2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -365,11 +365,9 @@ public final class SystemServiceRegistry { registerService(Context.TETHERING_SERVICE, TetheringManager.class, new CachedServiceFetcher<TetheringManager>() { @Override - public TetheringManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getService(Context.TETHERING_SERVICE); - if (b == null) return null; - - return new TetheringManager(ctx, b); + public TetheringManager createService(ContextImpl ctx) { + return new TetheringManager( + ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE)); }}); diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java index 93b1ea84adf7..761b225a7cdc 100644 --- a/core/java/android/app/TaskEmbedder.java +++ b/core/java/android/app/TaskEmbedder.java @@ -48,7 +48,6 @@ import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.SurfaceControl; -import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.inputmethod.InputMethodManager; @@ -131,6 +130,7 @@ public class TaskEmbedder { private TaskStackListener mTaskStackListener; private Listener mListener; private boolean mOpened; // Protected by mGuard. + private DisplayMetrics mTmpDisplayMetrics; private final CloseGuard mGuard = CloseGuard.get(); @@ -594,10 +594,11 @@ public class TaskEmbedder { /** Get density of the hosting display. */ private int getBaseDisplayDensity() { - final WindowManager wm = mContext.getSystemService(WindowManager.class); - final DisplayMetrics metrics = new DisplayMetrics(); - wm.getDefaultDisplay().getMetrics(metrics); - return metrics.densityDpi; + if (mTmpDisplayMetrics == null) { + mTmpDisplayMetrics = new DisplayMetrics(); + } + mContext.getDisplay().getMetrics(mTmpDisplayMetrics); + return mTmpDisplayMetrics.densityDpi; } /** diff --git a/core/java/android/app/WindowContext.java b/core/java/android/app/WindowContext.java index 22cc14bd5ed6..36ae450d342b 100644 --- a/core/java/android/app/WindowContext.java +++ b/core/java/android/app/WindowContext.java @@ -32,7 +32,7 @@ import android.view.WindowManagerImpl; * windows. Its resources and configuration are adjusted to the area of the display that will be * used when a new window is added via {@link android.view.WindowManager.addView}. * - * @see Context#createWindowContext(int) + * @see Context#createWindowContext(int, Bundle) * @hide */ // TODO(b/128338354): Handle config/display changes from server side. @@ -53,7 +53,7 @@ public class WindowContext extends ContextWrapper { * @param type Window type to be used with this context. * @hide */ - public WindowContext(Context base, IBinder token, int type) { + public WindowContext(Context base, IBinder token, int type, Bundle options) { super(null /* base */); mWms = WindowManagerGlobal.getWindowManagerService(); @@ -76,7 +76,7 @@ public class WindowContext extends ContextWrapper { return; } try { - mWms.addWindowContextToken(mToken, type, mDisplayId, getPackageName()); + mWms.addWindowTokenWithOptions(mToken, type, mDisplayId, options, getPackageName()); // TODO(window-context): remove token with a DeathObserver } catch (RemoteException e) { mOwnsToken = false; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d1b5a83e7142..f71d78b40242 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -7028,21 +7028,28 @@ public class DevicePolicyManager { } /** - * Called by a device owner to set the default SMS application. + * Must be called by a device owner or a profile owner of an organization-owned managed profile + * to set the default SMS application. * <p> - * The calling device admin must be a device owner. If it is not, a security exception will be - * thrown. + * This method can be called on the {@link DevicePolicyManager} instance, returned by + * {@link #getParentProfileInstance(ComponentName)}, where the caller must be the profile owner + * of an organization-owned managed profile and the package must be a pre-installed system + * package. If called on the parent instance, then the default SMS application is set on the + * personal profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package to set as the default SMS application. - * @throws SecurityException if {@code admin} is not a device owner. + * @throws SecurityException if {@code admin} is not a device or profile owner or if + * called on the parent profile and the {@code admin} is not a + * profile owner of an organization-owned managed profile. + * @throws IllegalArgumentException if called on the parent profile and the package + * provided is not a pre-installed system package. */ public void setDefaultSmsApplication(@NonNull ComponentName admin, @NonNull String packageName) { - throwIfParentInstance("setDefaultSmsApplication"); if (mService != null) { try { - mService.setDefaultSmsApplication(admin, packageName); + mService.setDefaultSmsApplication(admin, packageName, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e3dba310ab44..7fd0ae4a1a00 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -202,7 +202,7 @@ interface IDevicePolicyManager { void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity); void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName); - void setDefaultSmsApplication(in ComponentName admin, String packageName); + void setDefaultSmsApplication(in ComponentName admin, String packageName, boolean parent); void setApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName, in Bundle settings); Bundle getApplicationRestrictions(in ComponentName who, in String callerPackage, in String packageName); diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e24b0403cd6a..325fd9418af7 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -2162,6 +2162,33 @@ public final class BluetoothAdapter { } /** + * Fetches a list of the most recently connected bluetooth devices ordered by how recently they + * were connected with most recently first and least recently last + * + * @return {@link List} of bonded {@link BluetoothDevice} ordered by how recently they were + * connected + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public @NonNull List<BluetoothDevice> getMostRecentlyConnectedDevices() { + if (getState() != STATE_ON) { + return new ArrayList<>(); + } + try { + mServiceLock.readLock().lock(); + if (mService != null) { + return mService.getMostRecentlyConnectedDevices(); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + return new ArrayList<>(); + } + + /** * Return the set of {@link BluetoothDevice} objects that are bonded * (paired) to the local adapter. * <p>If Bluetooth state is not {@link #STATE_ON}, this API diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java index a923be62fbce..b5959c06cc1a 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -706,7 +706,7 @@ public final class BluetoothHidDevice implements BluetoothProfile { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index dfa4fb79ef2d..ec40b7e3508c 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -5728,14 +5728,13 @@ public abstract class Context { * shared, however common state (ClassLoader, other Resources for the * same configuration) may be so the Context itself can be fairly lightweight. * - * The returned display Context provides a {@link WindowManager} - * (see {@link #getSystemService(String)}) that is configured to show windows - * on the given display. The WindowManager's {@link WindowManager#getDefaultDisplay} - * method can be used to retrieve the Display from the returned Context. + * To obtain an instance of a {@link WindowManager} (see {@link #getSystemService(String)}) that + * is configured to show windows on the given display call + * {@link #createWindowContext(int, Bundle)} on the returned display Context or use an + * {@link android.app.Activity}. * - * @param display A {@link Display} object specifying the display - * for whose metrics the Context's resources should be tailored and upon which - * new windows should be shown. + * @param display A {@link Display} object specifying the display for whose metrics the + * Context's resources should be tailored. * * @return A {@link Context} for the display. */ @@ -5763,7 +5762,7 @@ public abstract class Context { * final DisplayManager dm = anyContext.getSystemService(DisplayManager.class); * final Display primaryDisplay = dm.getDisplay(DEFAULT_DISPLAY); * final Context windowContext = anyContext.createDisplayContext(primaryDisplay) - * .createWindowContext(TYPE_APPLICATION_OVERLAY); + * .createWindowContext(TYPE_APPLICATION_OVERLAY, null); * final View overlayView = Inflater.from(windowContext).inflate(someLayoutXml, null); * * // WindowManager.LayoutParams initialization @@ -5783,6 +5782,7 @@ public abstract class Context { * </p> * * @param type Window type in {@link WindowManager.LayoutParams} + * @param options Bundle used to pass window-related options. * @return A {@link Context} that can be used to create windows. * @throws UnsupportedOperationException if this is called on a non-UI context, such as * {@link android.app.Application Application} or {@link android.app.Service Service}. @@ -5794,7 +5794,7 @@ public abstract class Context { * @see #WALLPAPER_SERVICE * @throws IllegalArgumentException if token is invalid */ - public @NonNull Context createWindowContext(int type) { + public @NonNull Context createWindowContext(int type, @Nullable Bundle options) { throw new RuntimeException("Not implemented. Must override in a subclass."); } diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index b2b7988de896..f6515e806caa 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -978,8 +978,8 @@ public class ContextWrapper extends Context { @Override @NonNull - public Context createWindowContext(int type) { - return mBase.createWindowContext(type); + public Context createWindowContext(int type, @Nullable Bundle options) { + return mBase.createWindowContext(type, options); } @Override diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 9ee56a928d81..c5b9a43fb523 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -316,6 +316,7 @@ public final class CameraManager { CameraManagerGlobal.get().unregisterTorchCallback(callback); } + // TODO(b/147726300): Investigate how to support foldables/multi-display devices. private Size getDisplaySize() { Size ret = new Size(0, 0); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 92047dcad09e..da9cc8a47a39 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -16,7 +16,6 @@ package android.inputmethodservice; -import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; @@ -52,7 +51,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; @@ -64,6 +62,7 @@ import android.text.method.MovementMethod; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; +import android.util.Size; import android.view.Gravity; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -560,12 +559,10 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void updateInputMethodDisplay(int displayId) { // Update display for adding IME window to the right display. - if (displayId != DEFAULT_DISPLAY) { - // TODO(b/111364446) Need to address context lifecycle issue if need to re-create - // for update resources & configuration correctly when show soft input - // in non-default display. - updateDisplay(displayId); - } + // TODO(b/111364446) Need to address context lifecycle issue if need to re-create + // for update resources & configuration correctly when show soft input + // in non-default display. + updateDisplay(displayId); } /** @@ -1466,8 +1463,9 @@ public class InputMethodService extends AbstractInputMethodService { * screen orientation changes. */ public int getMaxWidth() { - WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - return wm.getDefaultDisplay().getWidth(); + final WindowManager windowManager = getSystemService(WindowManager.class); + final Size windowSize = windowManager.getCurrentWindowMetrics().getSize(); + return windowSize.getWidth(); } /** diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ce9693d88a97..fa12c08f2277 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3322,15 +3322,19 @@ public class ConnectivityManager { // of dependent changes that would conflict throughout the automerger graph. Having this // temporarily helps with the process of going through with all these dependent changes across // the entire tree. + // STOPSHIP (b/148055573) : remove this before R is released. /** * @hide * Register a NetworkAgent with ConnectivityService. * @return Network corresponding to NetworkAgent. + * @deprecated use the version that takes a NetworkScore and a provider ID. */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @Deprecated public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config) { - return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); + final NetworkScore ns = new NetworkScore.Builder().setLegacyScore(score).build(); + return registerNetworkAgent(messenger, ni, lp, nc, ns, config, NetworkProvider.ID_NONE); } /** @@ -3340,7 +3344,7 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + NetworkCapabilities nc, NetworkScore score, NetworkAgentConfig config, int providerId) { try { return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 3e9e7faccb02..0dc66b5052c5 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -26,6 +26,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkState; import android.net.ISocketKeepaliveCallback; import android.net.ProxyInfo; @@ -154,7 +155,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 7cc569a42b0b..ddf8dbbcb953 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -117,13 +117,6 @@ public abstract class NetworkAgent { public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; /** - * Centralize the place where base network score, and network score scaling, will be - * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE - * @hide - */ - public static final int WIFI_BASE_SCORE = 60; - - /** * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. * obj = network score Integer @@ -272,7 +265,13 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; + // STOPSHIP (b/148055573) : remove this before R is released. + private static NetworkScore makeNetworkScore(int score) { + return new NetworkScore.Builder().setLegacyScore(score).build(); + } + /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); @@ -280,6 +279,7 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); @@ -287,6 +287,7 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); @@ -294,10 +295,12 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { - this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); + this(looper, context, logTag, nc, lp, makeNetworkScore(score), config, providerId, ni, + true /* legacy */); register(); } @@ -323,8 +326,9 @@ public abstract class NetworkAgent { * @param provider the {@link NetworkProvider} managing this agent. */ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, + @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), getLegacyNetworkInfo(config), false /* legacy */); @@ -334,12 +338,12 @@ public abstract class NetworkAgent { public final Context context; public final NetworkCapabilities capabilities; public final LinkProperties properties; - public final int score; + public final NetworkScore score; public final NetworkAgentConfig config; public final NetworkInfo info; InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, - @NonNull NetworkInfo info) { + @NonNull LinkProperties properties, @NonNull NetworkScore score, + @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { this.context = context; this.capabilities = capabilities; this.properties = properties; @@ -351,7 +355,7 @@ public abstract class NetworkAgent { private volatile InitialConfiguration mInitialConfiguration; private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, boolean legacy) { mHandler = new NetworkAgentHandler(looper); @@ -646,22 +650,8 @@ public abstract class NetworkAgent { * Must be called by the agent to update the score of this network. * @param score the new score. */ - public void sendNetworkScore(int score) { - if (score < 0) { - throw new IllegalArgumentException("Score must be >= 0"); - } - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, score); - updateScore(ns); - } - - /** - * Must be called by the agent when it has a new {@link NetworkScore} for this network. - * @param ns the new score. - * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore. - */ - public void updateScore(@NonNull NetworkScore ns) { - queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); + public void sendNetworkScore(@NonNull final NetworkScore score) { + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score); } /** diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 01800c6751fb..14442a2088cd 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -539,13 +539,13 @@ public class NetworkPolicyManager { /** @hide */ public static String resolveNetworkId(WifiConfiguration config) { - return WifiInfo.removeDoubleQuotes(config.isPasspoint() + return WifiInfo.sanitizeSsid(config.isPasspoint() ? config.providerFriendlyName : config.SSID); } /** @hide */ public static String resolveNetworkId(String ssid) { - return WifiInfo.removeDoubleQuotes(ssid); + return WifiInfo.sanitizeSsid(ssid); } /** @hide */ diff --git a/core/java/android/net/NetworkScore.aidl b/core/java/android/net/NetworkScore.aidl new file mode 100644 index 000000000000..be9a98b24e74 --- /dev/null +++ b/core/java/android/net/NetworkScore.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.net; + +parcelable NetworkScore; diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index 13f2994110a1..ae17378cfc4c 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -15,12 +15,18 @@ */ package android.net; +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -28,57 +34,392 @@ import java.util.Objects; * * A NetworkScore object represents the characteristics of a network that affects how good the * network is considered for a particular use. + * + * This class is not thread-safe. * @hide */ +@TestApi +@SystemApi public final class NetworkScore implements Parcelable { + /** An object containing scoring-relevant metrics for a network. */ + public static class Metrics { + /** Value meaning the latency is unknown. */ + public static final int LATENCY_UNKNOWN = -1; + + /** Value meaning the bandwidth is unknown. */ + public static final int BANDWIDTH_UNKNOWN = -1; + + /** + * Round-trip delay in milliseconds to the relevant destination for this Metrics object. + * + * LATENCY_UNKNOWN if unknown. + */ + @IntRange(from = LATENCY_UNKNOWN) + public final int latencyMs; + + /** + * Downlink in kB/s with the relevant destination for this Metrics object. + * + * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink + * bandwidth can have the same value. + */ + @IntRange(from = BANDWIDTH_UNKNOWN) + public final int downlinkBandwidthKBps; - // The key of bundle which is used to get the legacy network score of NetworkAgentInfo. - // TODO: Remove this when the transition to NetworkScore is over. - public static final String LEGACY_SCORE = "LEGACY_SCORE"; + /** + * Uplink in kB/s with the relevant destination for this Metrics object. + * + * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink + * bandwidth can have the same value. + */ + @IntRange(from = BANDWIDTH_UNKNOWN) + public final int uplinkBandwidthKBps; + + /** Constructor */ + public Metrics(@IntRange(from = LATENCY_UNKNOWN) final int latency, + @IntRange(from = BANDWIDTH_UNKNOWN) final int downlinkBandwidth, + @IntRange(from = BANDWIDTH_UNKNOWN) final int uplinkBandwidth) { + latencyMs = latency; + downlinkBandwidthKBps = downlinkBandwidth; + uplinkBandwidthKBps = uplinkBandwidth; + } + + /** toString */ + public String toString() { + return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps + + "uplinkBandwidth = " + uplinkBandwidthKBps; + } + + @NonNull + public static final Metrics EMPTY = + new Metrics(LATENCY_UNKNOWN, BANDWIDTH_UNKNOWN, BANDWIDTH_UNKNOWN); + } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "POLICY_", value = { + POLICY_LOCKDOWN_VPN, + POLICY_VPN, + POLICY_IGNORE_ON_WIFI, + POLICY_DEFAULT_SUBSCRIPTION + }) + public @interface Policy { + } + + /** + * This network is a VPN with lockdown enabled. + * + * If a network with this bit is present in the list of candidates and not connected, + * no network can satisfy the request. + */ + public static final int POLICY_LOCKDOWN_VPN = 1 << 0; + + /** + * This network is a VPN. + * + * If a network with this bit is present and the request UID is included in the UID ranges + * of this network, it outscores all other networks without this bit. + */ + public static final int POLICY_VPN = 1 << 1; + + /** + * This network should not be used if a previously validated WiFi network is available. + * + * If a network with this bit is present and a previously validated WiFi is present too, the + * network with this bit is outscored by it. This stays true if the WiFi network + * becomes unvalidated : this network will not be considered. + */ + public static final int POLICY_IGNORE_ON_WIFI = 1 << 2; + + /** + * This network is the default subscription for this transport. + * + * If a network with this bit is present, other networks of the same transport without this + * bit are outscored by it. A device with two active subscriptions and a setting + * to decide the default one would have this policy bit on the network for the default + * subscription so that when both are active at the same time, the device chooses the + * network associated with the default subscription rather than the one with the best link + * quality (which will happen if policy doesn't dictate otherwise). + */ + public static final int POLICY_DEFAULT_SUBSCRIPTION = 1 << 3; + + /** + * Policy bits for this network. Filled in by the NetworkAgent. + */ + private final int mPolicy; + + /** + * Predicted metrics to the gateway (it contains latency and bandwidth to the gateway). + * This is filled by the NetworkAgent with the theoretical values of the link if available, + * although they may fill it with predictions from historical data if available. + * Note that while this member cannot be null, any and all of its members can be unknown. + */ @NonNull - private final Bundle mExtensions; + private final Metrics mLinkLayerMetrics; + + /** + * Predicted metrics to representative servers. + * This is filled by connectivity with (if available) a best-effort estimate of the performance + * information to servers the user connects to in similar circumstances, and predicted from + * actual measurements if possible. + * Note that while this member cannot be null, any and all of its members can be unknown. + */ + @NonNull + private final Metrics mEndToEndMetrics; + + /** Value meaning the signal strength is unknown. */ + public static final int UNKNOWN_SIGNAL_STRENGTH = -1; + + /** The smallest meaningful signal strength. */ + public static final int MIN_SIGNAL_STRENGTH = 0; + + /** The largest meaningful signal strength. */ + public static final int MAX_SIGNAL_STRENGTH = 1000; + + /** + * User-visible measure of the strength of the signal normalized 1~1000. + * This represents a measure of the signal strength for this network. + * If unknown, this has value UNKNOWN_SIGNAL_STRENGTH. + */ + // A good way to populate this value is to fill it with the number of bars displayed in + // the system UI, scaled 0 to 1000. This is what the user sees and it makes sense to them. + // Cellular for example could quantize the ASU value (see SignalStrength#getAsuValue) into + // this, while WiFi could scale the RSSI (see WifiManager#calculateSignalLevel). + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + private final int mSignalStrength; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "RANGE_", value = { + RANGE_UNKNOWN, RANGE_CLOSE, RANGE_SHORT, RANGE_MEDIUM, RANGE_LONG + }) + public @interface Range { + } + + /** + * The range of this network is not known. + * This can be used by VPN the range of which depends on the range of the underlying network. + */ + public static final int RANGE_UNKNOWN = 0; + + /** + * This network typically only operates at close range, like an NFC beacon. + */ + public static final int RANGE_CLOSE = 1; + + /** + * This network typically operates at a range of a few meters to a few dozen meters, like WiFi. + */ + public static final int RANGE_SHORT = 2; + + /** + * This network typically operates at a range of a few dozen to a few hundred meters, like CBRS. + */ + public static final int RANGE_MEDIUM = 3; + + /** + * This network typically offers continuous connectivity up to many kilometers away, like LTE. + */ + public static final int RANGE_LONG = 4; - public NetworkScore() { - mExtensions = new Bundle(); + /** + * The typical range of this networking technology. + * + * This is one of the RANGE_* constants and is filled by the NetworkAgent. + * This may be useful when evaluating how desirable a network is, because for two networks that + * have equivalent performance and cost, the one that won't lose IP continuity when the user + * moves is probably preferable. + * Agents should fill this with the largest typical range this technology provides. See the + * descriptions of the individual constants for guidance. + * + * If unknown, this is set to RANGE_UNKNOWN. + */ + @Range private final int mRange; + + /** + * A prediction of whether this network is likely to be unusable in a few seconds. + * + * NetworkAgents set this to true to mean they are aware that usability is limited due to + * low signal strength, congestion, or other reasons, and indicates that the system should + * only use this network as a last resort. An example would be a WiFi network when the device + * is about to move outside of range. + * + * This is filled by the NetworkAgent. Agents that don't know whether this network is likely + * to be unusable soon should set this to false. + */ + private final boolean mExiting; + + /** + * The legacy score, as a migration strategy from Q to R. + * STOPSHIP : remove this before R ships. + */ + private final int mLegacyScore; + + /** + * Create a new NetworkScore object. + */ + private NetworkScore(@Policy final int policy, @Nullable final Metrics l2Perf, + @Nullable final Metrics e2ePerf, + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + final int signalStrength, + @Range final int range, final boolean exiting, final int legacyScore) { + mPolicy = policy; + mLinkLayerMetrics = null != l2Perf ? l2Perf : Metrics.EMPTY; + mEndToEndMetrics = null != e2ePerf ? e2ePerf : Metrics.EMPTY; + mSignalStrength = signalStrength; + mRange = range; + mExiting = exiting; + mLegacyScore = legacyScore; } - public NetworkScore(@NonNull NetworkScore source) { - mExtensions = new Bundle(source.mExtensions); + /** + * Utility function to return a copy of this with a different exiting value. + */ + @NonNull public NetworkScore withExiting(final boolean exiting) { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, + mSignalStrength, mRange, exiting, mLegacyScore); } /** - * Put the value of parcelable inside the bundle by key. + * Utility function to return a copy of this with a different signal strength. */ - public void putExtension(@Nullable String key, @Nullable Parcelable value) { - mExtensions.putParcelable(key, value); + @NonNull public NetworkScore withSignalStrength( + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH) final int signalStrength) { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, + signalStrength, mRange, mExiting, mLegacyScore); } /** - * Put the value of int inside the bundle by key. + * Returns whether this network has a particular policy flag. + * @param policy the policy, as one of the POLICY_* constants. */ - public void putIntExtension(@Nullable String key, int value) { - mExtensions.putInt(key, value); + public boolean hasPolicy(@Policy final int policy) { + return 0 != (mPolicy & policy); } /** - * Get the value of non primitive type by key. + * Returns the Metrics representing the performance of the link layer. + * + * This contains the theoretical performance of the link, if available. + * Note that while this function cannot return null, any and/or all of the members of the + * returned object can be null if unknown. */ - public <T extends Parcelable> T getExtension(@Nullable String key) { - return mExtensions.getParcelable(key); + @NonNull public Metrics getLinkLayerMetrics() { + return mLinkLayerMetrics; } /** - * Get the value of int by key. + * Returns the Metrics representing the end-to-end performance of the network. + * + * This contains the end-to-end performance of the link, if available. + * Note that while this function cannot return null, any and/or all of the members of the + * returned object can be null if unknown. */ - public int getIntExtension(@Nullable String key) { - return mExtensions.getInt(key); + @NonNull public Metrics getEndToEndMetrics() { + return mEndToEndMetrics; } /** - * Remove the entry by given key. + * Returns the signal strength of this network normalized 0~1000, or UNKNOWN_SIGNAL_STRENGTH. */ - public void removeExtension(@Nullable String key) { - mExtensions.remove(key); + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + public int getSignalStrength() { + return mSignalStrength; + } + + /** + * Returns the typical range of this network technology as one of the RANGE_* constants. + */ + @Range public int getRange() { + return mRange; + } + + /** Returns a prediction of whether this network is likely to be unusable in a few seconds. */ + public boolean isExiting() { + return mExiting; + } + + /** + * Get the legacy score. + * @hide + */ + public int getLegacyScore() { + return mLegacyScore; + } + + /** Builder for NetworkScore. */ + public static class Builder { + private int mPolicy = 0; + @NonNull + private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); + @NonNull + private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); + private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH; + private int mRange = RANGE_UNKNOWN; + private boolean mExiting = false; + private int mLegacyScore = 0; + @NonNull private Bundle mExtensions = new Bundle(); + + /** Create a new builder. */ + public Builder() { } + + /** Add a policy flag. */ + @NonNull public Builder addPolicy(@Policy final int policy) { + mPolicy |= policy; + return this; + } + + /** Clear a policy flag */ + @NonNull public Builder clearPolicy(@Policy final int policy) { + mPolicy &= ~policy; + return this; + } + + /** Set the link layer metrics. */ + @NonNull public Builder setLinkLayerMetrics(@NonNull final Metrics linkLayerMetrics) { + mLinkLayerMetrics = linkLayerMetrics; + return this; + } + + /** Set the end-to-end metrics. */ + @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) { + mEndToMetrics = endToEndMetrics; + return this; + } + + /** Set the signal strength. */ + @NonNull public Builder setSignalStrength( + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + final int signalStrength) { + mSignalStrength = signalStrength; + return this; + } + + /** Set the range. */ + @NonNull public Builder setRange(@Range final int range) { + mRange = range; + return this; + } + + /** Set whether this network is exiting. */ + @NonNull public Builder setExiting(final boolean exiting) { + mExiting = exiting; + return this; + } + + /** Add a parcelable extension. */ + @NonNull public Builder setLegacyScore(final int legacyScore) { + mLegacyScore = legacyScore; + return this; + } + + /** Build the NetworkScore object represented by this builder. */ + @NonNull public NetworkScore build() { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics, + mSignalStrength, mRange, mExiting, mLegacyScore); + } } @Override @@ -88,9 +429,17 @@ public final class NetworkScore implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - synchronized (this) { - dest.writeBundle(mExtensions); - } + dest.writeInt(mPolicy); + dest.writeInt(mLinkLayerMetrics.latencyMs); + dest.writeInt(mLinkLayerMetrics.downlinkBandwidthKBps); + dest.writeInt(mLinkLayerMetrics.uplinkBandwidthKBps); + dest.writeInt(mEndToEndMetrics.latencyMs); + dest.writeInt(mEndToEndMetrics.downlinkBandwidthKBps); + dest.writeInt(mEndToEndMetrics.uplinkBandwidthKBps); + dest.writeInt(mSignalStrength); + dest.writeInt(mRange); + dest.writeBoolean(mExiting); + dest.writeInt(mLegacyScore); } public static final @NonNull Creator<NetworkScore> CREATOR = new Creator<NetworkScore>() { @@ -106,57 +455,52 @@ public final class NetworkScore implements Parcelable { }; private NetworkScore(@NonNull Parcel in) { - mExtensions = in.readBundle(); + mPolicy = in.readInt(); + mLinkLayerMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); + mEndToEndMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); + mSignalStrength = in.readInt(); + mRange = in.readInt(); + mExiting = in.readBoolean(); + mLegacyScore = in.readInt(); } - // TODO: Modify this method once new fields are added into this class. @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof NetworkScore)) { return false; } final NetworkScore other = (NetworkScore) obj; - return bundlesEqual(mExtensions, other.mExtensions); + return mPolicy == other.mPolicy + && mLinkLayerMetrics.latencyMs == other.mLinkLayerMetrics.latencyMs + && mLinkLayerMetrics.uplinkBandwidthKBps + == other.mLinkLayerMetrics.uplinkBandwidthKBps + && mEndToEndMetrics.latencyMs == other.mEndToEndMetrics.latencyMs + && mEndToEndMetrics.uplinkBandwidthKBps + == other.mEndToEndMetrics.uplinkBandwidthKBps + && mSignalStrength == other.mSignalStrength + && mRange == other.mRange + && mExiting == other.mExiting + && mLegacyScore == other.mLegacyScore; } @Override public int hashCode() { - int result = 29; - for (String key : mExtensions.keySet()) { - final Object value = mExtensions.get(key); - // The key may be null, so call Objects.hash() is safer. - result += 31 * value.hashCode() + 37 * Objects.hash(key); - } - return result; - } - - // mExtensions won't be null since the constructor will create it. - private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) { - if (bundle1 == bundle2) { - return true; - } - - // This is unlikely but it's fine to add this clause here. - if (null == bundle1 || null == bundle2) { - return false; - } - - if (bundle1.size() != bundle2.size()) { - return false; - } - - for (String key : bundle1.keySet()) { - final Object value1 = bundle1.get(key); - final Object value2 = bundle2.get(key); - if (!Objects.equals(value1, value2)) { - return false; - } - } - return true; + return Objects.hash(mPolicy, + mLinkLayerMetrics.latencyMs, mLinkLayerMetrics.uplinkBandwidthKBps, + mEndToEndMetrics.latencyMs, mEndToEndMetrics.uplinkBandwidthKBps, + mSignalStrength, mRange, mExiting, mLegacyScore); } /** Convert to a string */ public String toString() { - return "NetworkScore[" + mExtensions.toString() + "]"; + return "NetworkScore [" + + "Policy = " + mPolicy + + " LinkLayerMetrics = " + mLinkLayerMetrics + + " EndToEndMetrics = " + mEndToEndMetrics + + " SignalStrength = " + mSignalStrength + + " Range = " + mRange + + " Exiting = " + mExiting + + " LegacyScore = " + mLegacyScore + + "]"; } } diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5e6c47a47a8e..5498f74ba2cc 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -32,7 +32,7 @@ import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; -import static android.net.wifi.WifiInfo.removeDoubleQuotes; +import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -401,7 +401,7 @@ public class NetworkTemplate implements Parcelable { switch (ident.mType) { case TYPE_WIFI: return Objects.equals( - removeDoubleQuotes(mNetworkId), removeDoubleQuotes(ident.mNetworkId)); + sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId)); default: return false; } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index cdcb3ff94264..be2245820bb6 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -41,7 +41,6 @@ import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; import android.view.Display; -import android.view.WindowManager; import libcore.io.Streams; @@ -615,8 +614,7 @@ public class RecoverySystem { // On TV, reboot quiescently if the screen is off if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - if (wm.getDefaultDisplay().getState() != Display.STATE_ON) { + if (context.getDisplay().getState() != Display.STATE_ON) { reason += ",quiescent"; } } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 3564589e35a4..6ed1d2c345f8 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1775,9 +1775,10 @@ public class UserManager { } /** - * Returns whether the context user's user is of the given user type, such as - * {@link UserManager#USER_TYPE_FULL_GUEST}. + * Returns whether the context user is of the given user type. * + * @param userType the name of the user's user type, e.g. + * {@link UserManager#USER_TYPE_PROFILE_MANAGED}. * @return true if the user is of the given user type. * @hide */ @@ -1793,26 +1794,6 @@ public class UserManager { } /** - * Returns whether the given user is of the given user type, such as - * {@link UserManager#USER_TYPE_FULL_GUEST}. - * - * @param userHandle the user handle of the user whose type is being requested. - * @param userType the name of the user's user type, e.g. - * {@link UserManager#USER_TYPE_PROFILE_MANAGED}. - * @return true if the userHandle user is of type userType - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) - public boolean isUserOfType(@NonNull UserHandle userHandle, @NonNull String userType) { - try { - return mService.isUserOfType(userHandle.getIdentifier(), userType); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - /** * Returns whether the user type is a * {@link UserManager#USER_TYPE_PROFILE_MANAGED managed profile}. * @hide diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java index 3e16640895eb..27782fa74dab 100644 --- a/core/java/android/os/VibrationAttributes.java +++ b/core/java/android/os/VibrationAttributes.java @@ -391,11 +391,23 @@ public final class VibrationAttributes implements Parcelable { * Replaces flags * @param flags any combination of flags. * @return the same Builder instance. + * @hide */ public @NonNull Builder replaceFlags(int flags) { mFlags = flags; return this; } + + /** + * Set flags + * @param flags combination of flags to be set. + * @param mask Bit range that should be changed. + * @return the same Builder instance. + */ + public @NonNull Builder setFlags(int flags, int mask) { + mFlags = (mFlags & ~mask) | (flags & mask); + return this; + } } } diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index 7161b07cee3c..6adba63f42ce 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java @@ -149,7 +149,7 @@ public class WorkSource implements Parcelable { } /** - * Returns the size of this work source. + * Returns the number of uids in this work source. * @hide */ @TestApi diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 9666c12699e8..605c585215a6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8711,6 +8711,14 @@ public final class Settings { "back_gesture_inset_scale_right"; /** + * Current provider of proximity-based sharing services. + * Default value in @string/config_defaultNearbySharingComponent. + * No VALIDATOR as this setting will not be backed up. + * @hide + */ + public static final String NEARBY_SHARING_COMPONENT = "nearby_sharing_component"; + + /** * Controls whether aware is enabled. * @hide */ diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index c5d97b718ff0..74b913645ad4 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -35,6 +35,7 @@ import android.os.Parcelable; import android.os.UserHandle; import android.text.TextUtils; +import com.android.internal.logging.InstanceId; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -68,6 +69,8 @@ public class StatusBarNotification implements Parcelable { private final UserHandle user; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final long postTime; + // A small per-notification ID, used for statsd logging. + private InstanceId mInstanceId; // Not final, see setInstanceId() private Context mContext; // used for inflation & icon expansion @@ -131,8 +134,9 @@ public class StatusBarNotification implements Parcelable { this.postTime = in.readLong(); if (in.readInt() != 0) { this.overrideGroupKey = in.readString(); - } else { - this.overrideGroupKey = null; + } + if (in.readInt() != 0) { + this.mInstanceId = InstanceId.CREATOR.createFromParcel(in); } this.key = key(); this.groupKey = groupKey(); @@ -196,7 +200,6 @@ public class StatusBarNotification implements Parcelable { out.writeInt(this.initialPid); this.notification.writeToParcel(out, flags); user.writeToParcel(out, flags); - out.writeLong(this.postTime); if (this.overrideGroupKey != null) { out.writeInt(1); @@ -204,6 +207,12 @@ public class StatusBarNotification implements Parcelable { } else { out.writeInt(0); } + if (this.mInstanceId != null) { + out.writeInt(1); + mInstanceId.writeToParcel(out, flags); + } else { + out.writeInt(0); + } } public int describeContents() { @@ -390,6 +399,20 @@ public class StatusBarNotification implements Parcelable { /** * @hide */ + public InstanceId getInstanceId() { + return mInstanceId; + } + + /** + * @hide + */ + public void setInstanceId(InstanceId instanceId) { + mInstanceId = instanceId; + } + + /** + * @hide + */ @UnsupportedAppUsage public Context getPackageContext(Context context) { if (mContext == null) { diff --git a/core/java/android/service/quickaccesswallet/TEST_MAPPING b/core/java/android/service/quickaccesswallet/TEST_MAPPING new file mode 100644 index 000000000000..4d97ab6e612d --- /dev/null +++ b/core/java/android/service/quickaccesswallet/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "presubmit": [ + { + "name": "CtsQuickAccessWalletTestCases" + } + ] +} diff --git a/core/java/android/telephony/CellBroadcastIntents.java b/core/java/android/telephony/CellBroadcastIntents.java index 32d330e1a47f..921ad3c74681 100644 --- a/core/java/android/telephony/CellBroadcastIntents.java +++ b/core/java/android/telephony/CellBroadcastIntents.java @@ -81,7 +81,6 @@ public class CellBroadcastIntents { int initialCode, int slotIndex) { Intent backgroundIntent = new Intent(Telephony.Sms.Intents.SMS_CB_RECEIVED_ACTION); backgroundIntent.putExtra(EXTRA_MESSAGE, smsCbMessage); - backgroundIntent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); putPhoneIdAndSubIdExtra(context, backgroundIntent, slotIndex); String receiverPermission = Manifest.permission.RECEIVE_SMS; diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 023f0005eac7..531ade04fe02 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -168,9 +168,11 @@ public class PhoneStateListener { public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100; /** - * Listen for always reported changes of the network signal strengths (cellular), + * Listen for changes of the network signal strengths (cellular) always reported from modem, * even in some situations such as the screen of the device is off. * + * @see #onSignalStrengthsChanged + * * @hide */ @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java index e5bbdf4b6eea..5875761bb1c9 100644 --- a/core/java/android/timezone/CountryTimeZones.java +++ b/core/java/android/timezone/CountryTimeZones.java @@ -56,7 +56,7 @@ public final class CountryTimeZones { */ @NonNull public String getTimeZoneId() { - return mDelegate.timeZoneId; + return mDelegate.getTimeZoneId(); } /** @@ -187,7 +187,7 @@ public final class CountryTimeZones { * would be a good choice <em>generally</em> when there's no other information available. */ public boolean isDefaultTimeZoneBoosted() { - return mDelegate.getDefaultTimeZoneBoost(); + return mDelegate.isDefaultTimeZoneBoosted(); } /** @@ -220,7 +220,8 @@ public final class CountryTimeZones { mDelegate.lookupByOffsetWithBias( totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias); return delegateOffsetResult == null ? null : - new OffsetResult(delegateOffsetResult.mTimeZone, delegateOffsetResult.mOneMatch); + new OffsetResult( + delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch()); } /** diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java index 605155e76c2c..efe50a07da98 100644 --- a/core/java/android/timezone/TzDataSetVersion.java +++ b/core/java/android/timezone/TzDataSetVersion.java @@ -111,23 +111,23 @@ public final class TzDataSetVersion { /** Returns the major version number. See {@link TzDataSetVersion}. */ public int getFormatMajorVersion() { - return mDelegate.formatMajorVersion; + return mDelegate.getFormatMajorVersion(); } /** Returns the minor version number. See {@link TzDataSetVersion}. */ public int getFormatMinorVersion() { - return mDelegate.formatMinorVersion; + return mDelegate.getFormatMinorVersion(); } /** Returns the tzdb version string. See {@link TzDataSetVersion}. */ @NonNull public String getRulesVersion() { - return mDelegate.rulesVersion; + return mDelegate.getRulesVersion(); } /** Returns the Android revision. See {@link TzDataSetVersion}. */ public int getRevision() { - return mDelegate.revision; + return mDelegate.getRevision(); } @Override diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index c325874405a5..36f4e5361ea6 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -81,7 +81,7 @@ public class TimeUtils { } CountryTimeZones.OffsetResult offsetResult = countryTimeZones.lookupByOffsetWithBias( offsetMillis, isDst, null /* dstOffsetMillis */, whenMillis, bias); - return offsetResult != null ? offsetResult.mTimeZone : null; + return offsetResult != null ? offsetResult.getTimeZone() : null; } /** @@ -109,8 +109,8 @@ public class TimeUtils { List<String> timeZoneIds = new ArrayList<>(); for (TimeZoneMapping timeZoneMapping : countryTimeZones.getTimeZoneMappings()) { - if (timeZoneMapping.showInPicker) { - timeZoneIds.add(timeZoneMapping.timeZoneId); + if (timeZoneMapping.isShownInPicker()) { + timeZoneIds.add(timeZoneMapping.getTimeZoneId()); } } return Collections.unmodifiableList(timeZoneIds); diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 0304328f734a..d79fc9a48116 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -57,8 +57,8 @@ import java.util.List; * <li>The application display area specifies the part of the display that may contain * an application window, excluding the system decorations. The application display area may * be smaller than the real display area because the system subtracts the space needed - * for decor elements such as the status bar. Use the following methods to query the - * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li> + * for decor elements such as the status bar. Use {@link WindowMetrics#getSize()} to query the + * application window size.</li> * <li>The real display area specifies the part of the display that contains content * including the system decorations. Even so, the real display area may be smaller than the * physical size of the display if the window manager is emulating a smaller display @@ -97,7 +97,7 @@ public final class Display { // We cache the app width and height properties briefly between calls // to getHeight() and getWidth() to ensure that applications perceive // consistent results when the size changes (most of the time). - // Applications should now be using getSize() instead. + // Applications should now be using WindowMetrics instead. private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; private long mLastCachedAppSizeUpdate; private int mCachedAppWidthCompat; @@ -674,7 +674,10 @@ public final class Display { * </p> * * @param outSize A {@link Point} object to receive the size information. + * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to obtain an instance of + * {@link WindowMetrics} and use {@link WindowMetrics#getSize()} instead. */ + @Deprecated public void getSize(Point outSize) { synchronized (this) { updateDisplayInfoLocked(); @@ -688,8 +691,10 @@ public final class Display { * Gets the size of the display as a rectangle, in pixels. * * @param outSize A {@link Rect} object to receive the size information. - * @see #getSize(Point) + * @deprecated Use {@link WindowMetrics#getSize()} to get the dimensions of the application + * window area. */ + @Deprecated public void getRectSize(Rect outSize) { synchronized (this) { updateDisplayInfoLocked(); @@ -752,7 +757,7 @@ public final class Display { } /** - * @deprecated Use {@link #getSize(Point)} instead. + * @deprecated Use {@link WindowMetrics#getSize()} instead. */ @Deprecated public int getWidth() { @@ -763,7 +768,7 @@ public final class Display { } /** - * @deprecated Use {@link #getSize(Point)} instead. + * @deprecated Use {@link WindowMetrics#getSize()} instead. */ @Deprecated public int getHeight() { @@ -1102,7 +1107,10 @@ public final class Display { * </p> * * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. + * @deprecated Use {@link WindowMetrics#getSize()} to get the dimensions of the application + * window area, and {@link Configuration#densityDpi} to get the current density. */ + @Deprecated public void getMetrics(DisplayMetrics outMetrics) { synchronized (this) { updateDisplayInfoLocked(); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index e1f1581c53bc..f9a023fafc3c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -120,12 +120,14 @@ interface IWindowManager * * @param token Token to be registered. * @param type Window type to be used with this token. + * @param options A bundle used to pass window-related options. * @param displayId The ID of the display where this token should be added. * @param packageName The name of package to request to add window token. * @return {@link WindowManagerGlobal#ADD_OKAY} if the addition was successful, an error code * otherwise. */ - int addWindowContextToken(IBinder token, int type, int displayId, String packageName); + int addWindowTokenWithOptions(IBinder token, int type, int displayId, in Bundle options, + String packageName); void addWindowToken(IBinder token, int type, int displayId); void removeWindowToken(IBinder token, int displayId); void prepareAppTransition(int transit, boolean alwaysKeepCurrent); diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index ddfd38c0320b..9901d053184c 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -181,8 +181,9 @@ public class InsetsSourceConsumer { } private void applyHiddenToControl() { - if (mSourceControl == null || mSourceControl.getLeash() == null - || mController.getAnimationType(mType) != ANIMATION_TYPE_NONE) { + + // TODO: Handle case properly when animation is running already (it shouldn't!) + if (mSourceControl == null || mSourceControl.getLeash() == null) { return; } diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index a66b508cf523..47a79bd5484a 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -28,6 +28,7 @@ import android.os.Build; import android.os.RemoteException; import android.provider.Settings; import android.util.DisplayMetrics; +import android.util.Size; import android.util.SparseArray; import android.util.TypedValue; @@ -408,11 +409,9 @@ public class ViewConfiguration { mAmbiguousGestureMultiplier = multiplierValue.getFloat(); // Size of the screen in bytes, in ARGB_8888 format - final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - final Display display = win.getDefaultDisplay(); - final Point size = new Point(); - display.getRealSize(size); - mMaximumDrawingCacheSize = 4 * size.x * size.y; + final WindowManager windowManager = context.getSystemService(WindowManager.class); + final Size maxWindowSize = windowManager.getMaximumWindowMetrics().getSize(); + mMaximumDrawingCacheSize = 4 * maxWindowSize.getWidth() * maxWindowSize.getHeight(); mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f); mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 841c43fb1392..51ea30b41741 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -216,7 +216,7 @@ public final class ViewRootImpl implements ViewParent, * If set to 1, this will switch to a mode where we only use the new approach for IME, but not * for the status/navigation bar. */ - private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets"; + private static final String USE_NEW_INSETS_PROPERTY = "persist.debug.new_insets"; /** * @see #USE_NEW_INSETS_PROPERTY diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java index 826620710b18..8d3dc83bca0c 100644 --- a/core/java/android/view/autofill/AutofillPopupWindow.java +++ b/core/java/android/view/autofill/AutofillPopupWindow.java @@ -19,13 +19,13 @@ package android.view.autofill; import static android.view.autofill.Helper.sVerbose; import android.annotation.NonNull; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.IBinder; import android.os.RemoteException; import android.transition.Transition; import android.util.Log; +import android.util.Size; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewTreeObserver; @@ -127,11 +127,12 @@ public class AutofillPopupWindow extends PopupWindow { // If it is not fullscreen height, put window at bottom. Computes absolute position. // Note that we cannot easily change default gravity from Gravity.TOP to // Gravity.BOTTOM because PopupWindow base class does not expose computeGravity(). - final Point outPoint = new Point(); - anchor.getContext().getDisplay().getSize(outPoint); - width = outPoint.x; + final WindowManager windowManager = anchor.getContext() + .getSystemService(WindowManager.class); + final Size windowSize = windowManager.getCurrentWindowMetrics().getSize(); + width = windowSize.getWidth(); if (height != LayoutParams.MATCH_PARENT) { - offsetY = outPoint.y - height; + offsetY = windowSize.getHeight() - height; } actualAnchor = anchor; } else if (virtualBounds != null) { diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index c8a7c079994c..78d4e61ea953 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -28,6 +28,7 @@ import android.app.ITransientNotification; import android.app.ITransientNotificationCallback; import android.compat.Compatibility; import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Configuration; @@ -112,11 +113,9 @@ public class Toast { /** * Text toasts will be rendered by SystemUI instead of in-app, so apps can't circumvent * background custom toast restrictions. - * - * TODO(b/144152069): Add @EnabledAfter(Q) to target R+ after assessing impact on dogfood */ @ChangeId - // @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) private static final long CHANGE_TEXT_TOASTS_IN_THE_SYSTEM = 147798919L; diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java index 77d8e0290f20..ab8c19ea8861 100644 --- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java @@ -18,7 +18,9 @@ package com.android.internal.app; import android.annotation.IntDef; import android.annotation.Nullable; import android.content.Context; +import android.content.pm.ResolveInfo; import android.os.UserHandle; +import android.os.UserManager; import android.view.View; import android.view.ViewGroup; @@ -27,6 +29,7 @@ import com.android.internal.widget.PagerAdapter; import com.android.internal.widget.ViewPager; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -46,11 +49,17 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { private int mCurrentPage; private OnProfileSelectedListener mOnProfileSelectedListener; private Set<Integer> mLoadedPages; + private final UserHandle mPersonalProfileUserHandle; + private final UserHandle mWorkProfileUserHandle; - AbstractMultiProfilePagerAdapter(Context context, int currentPage) { + AbstractMultiProfilePagerAdapter(Context context, int currentPage, + UserHandle personalProfileUserHandle, + UserHandle workProfileUserHandle) { mContext = Objects.requireNonNull(context); mCurrentPage = currentPage; mLoadedPages = new HashSet<>(); + mPersonalProfileUserHandle = personalProfileUserHandle; + mWorkProfileUserHandle = workProfileUserHandle; } void setOnProfileSelectedListener(OnProfileSelectedListener listener) { @@ -72,7 +81,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { public void onPageSelected(int position) { mCurrentPage = position; if (!mLoadedPages.contains(position)) { - getActiveListAdapter().rebuildList(); + rebuildActiveTab(true); mLoadedPages.add(position); } if (mOnProfileSelectedListener != null) { @@ -85,6 +94,13 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { mLoadedPages.add(mCurrentPage); } + void clearInactiveProfileCache() { + if (mLoadedPages.size() == 1) { + return; + } + mLoadedPages.remove(1 - mCurrentPage); + } + @Override public ViewGroup instantiateItem(ViewGroup container, int position) { final ProfileDescriptor profileDescriptor = getItem(position); @@ -187,12 +203,53 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { @VisibleForTesting public abstract @Nullable ResolverListAdapter getInactiveListAdapter(); + public abstract ResolverListAdapter getPersonalListAdapter(); + + public abstract @Nullable ResolverListAdapter getWorkListAdapter(); + abstract Object getCurrentRootAdapter(); abstract ViewGroup getActiveAdapterView(); abstract @Nullable ViewGroup getInactiveAdapterView(); + boolean rebuildActiveTab(boolean post) { + return rebuildTab(getActiveListAdapter(), post); + } + + boolean rebuildInactiveTab(boolean post) { + if (getItemCount() == 1) { + return false; + } + return rebuildTab(getInactiveListAdapter(), post); + } + + private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) { + UserHandle listUserHandle = activeListAdapter.getUserHandle(); + if (UserHandle.myUserId() != listUserHandle.getIdentifier() && + !hasAppsInOtherProfile(activeListAdapter)) { + // TODO(arangelov): Show empty state UX here + return false; + } else { + return activeListAdapter.rebuildList(doPostProcessing); + } + } + + private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) { + if (mWorkProfileUserHandle == null) { + return false; + } + List<ResolverActivity.ResolvedComponentInfo> resolversForIntent = + adapter.getResolversForUser(UserHandle.of(UserHandle.myUserId())); + for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) { + ResolveInfo resolveInfo = info.getResolveInfoAt(0); + if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) { + return true; + } + } + return false; + } + protected class ProfileDescriptor { final ViewGroup rootView; ProfileDescriptor(ViewGroup rootView) { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 65128e4a2eda..a43e4fe118a9 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -53,6 +53,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.content.res.Configuration; +import android.content.res.Resources; import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Bitmap; @@ -81,6 +82,7 @@ import android.provider.DeviceConfig; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; +import android.provider.Settings; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; @@ -101,6 +103,7 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.widget.Button; import android.widget.ImageView; import android.widget.Space; import android.widget.TextView; @@ -131,6 +134,7 @@ import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.URISyntaxException; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; @@ -166,6 +170,9 @@ public class ChooserActivity extends ResolverActivity implements private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions"; + private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label"; + private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon"; + private static final boolean DEBUG = true; private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true; @@ -527,6 +534,15 @@ public class ChooserActivity extends ResolverActivity implements mIsSuccessfullySelected = false; Intent intent = getIntent(); Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); + if (targetParcelable instanceof Uri) { + try { + targetParcelable = Intent.parseUri(targetParcelable.toString(), + Intent.URI_INTENT_SCHEME); + } catch (URISyntaxException ex) { + // doesn't parse as an intent; let the next test fail and error out + } + } + if (!(targetParcelable instanceof Intent)) { Log.w("ChooserActivity", "Target is not an intent: " + targetParcelable); finish(); @@ -777,7 +793,9 @@ public class ChooserActivity extends ResolverActivity implements /* userHandle */ UserHandle.of(UserHandle.myUserId())); return new ChooserMultiProfilePagerAdapter( /* context */ this, - adapter); + adapter, + getPersonalProfileUserHandle(), + /* workProfileUserHandle= */ null); } private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForTwoProfiles( @@ -804,7 +822,9 @@ public class ChooserActivity extends ResolverActivity implements /* context */ this, personalAdapter, workAdapter, - /* defaultProfile */ getCurrentProfile()); + /* defaultProfile */ getCurrentProfile(), + getPersonalProfileUserHandle(), + getWorkProfileUserHandle()); } @Override @@ -856,11 +876,11 @@ public class ChooserActivity extends ResolverActivity implements } @Override - protected PackageMonitor createPackageMonitor() { + protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) { return new PackageMonitor() { @Override public void onSomePackagesChanged() { - handlePackagesChanged(); + handlePackagesChanged(listAdapter); } }; } @@ -869,9 +889,19 @@ public class ChooserActivity extends ResolverActivity implements * Update UI to reflect changes in data. */ public void handlePackagesChanged() { - // TODO(arangelov): Dispatch this to all adapters when we have the helper methods - // in a follow-up CL - mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged(); + handlePackagesChanged(/* listAdapter */ null); + } + + /** + * Update UI to reflect changes in data. + * <p>If {@code listAdapter} is {@code null}, both profile list adapters are updated. + */ + private void handlePackagesChanged(@Nullable ResolverListAdapter listAdapter) { + if (listAdapter == null) { + mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged(); + } else { + listAdapter.handlePackagesChanged(); + } updateProfileViewButton(); } @@ -965,6 +995,108 @@ public class ChooserActivity extends ResolverActivity implements return displayContentPreview(previewType, targetIntent, getLayoutInflater(), parent); } + private ComponentName getNearbySharingComponent() { + String nearbyComponent = Settings.Secure.getString( + getContentResolver(), + Settings.Secure.NEARBY_SHARING_COMPONENT); + if (TextUtils.isEmpty(nearbyComponent)) { + nearbyComponent = getString(R.string.config_defaultNearbySharingComponent); + } + if (TextUtils.isEmpty(nearbyComponent)) { + return null; + } + return ComponentName.unflattenFromString(nearbyComponent); + } + + private TargetInfo getNearbySharingTarget(Intent originalIntent) { + final ComponentName cn = getNearbySharingComponent(); + if (cn == null) return null; + + final Intent resolveIntent = new Intent(); + resolveIntent.setComponent(cn); + final ResolveInfo ri = getPackageManager().resolveActivity( + resolveIntent, PackageManager.GET_META_DATA); + if (ri == null || ri.activityInfo == null) { + Log.e(TAG, "Device-specified nearby sharing component (" + cn + + ") not available"); + return null; + } + + // Allow the nearby sharing component to provide a more appropriate icon and label + // for the chip. + CharSequence name = null; + Drawable icon = null; + final Bundle metaData = ri.activityInfo.metaData; + if (metaData != null) { + try { + final Resources pkgRes = getPackageManager().getResourcesForActivity(cn); + final int nameResId = metaData.getInt(CHIP_LABEL_METADATA_KEY); + name = pkgRes.getString(nameResId); + final int resId = metaData.getInt(CHIP_ICON_METADATA_KEY); + icon = pkgRes.getDrawable(resId); + } catch (Resources.NotFoundException ex) { + } catch (NameNotFoundException ex) { + } + } + if (TextUtils.isEmpty(name)) { + name = ri.loadLabel(getPackageManager()); + } + if (icon == null) { + icon = ri.loadIcon(getPackageManager()); + } + + final DisplayResolveInfo dri = new DisplayResolveInfo( + originalIntent, ri, name, "", resolveIntent, null); + dri.setDisplayIcon(icon); + return dri; + } + + private Button createActionButton(Drawable icon, CharSequence title, View.OnClickListener r) { + Button b = (Button) LayoutInflater.from(this).inflate(R.layout.chooser_action_button, null); + if (icon != null) { + final int size = getResources() + .getDimensionPixelSize(R.dimen.chooser_action_button_icon_size); + icon.setBounds(0, 0, size, size); + b.setCompoundDrawablesRelative(icon, null, null, null); + } + b.setText(title); + b.setOnClickListener(r); + return b; + } + + private Button createCopyButton() { + final Button b = createActionButton( + getDrawable(R.drawable.ic_menu_copy_material), + getString(R.string.copy), this::onCopyButtonClicked); + b.setId(R.id.chooser_copy_button); + return b; + } + + private @Nullable Button createNearbyButton(Intent originalIntent) { + final TargetInfo ti = getNearbySharingTarget(originalIntent); + if (ti == null) return null; + + return createActionButton( + ti.getDisplayIcon(this), + ti.getDisplayLabel(), + (View unused) -> { + safelyStartActivity(ti); + finish(); + } + ); + } + + private void addActionButton(ViewGroup parent, Button b) { + if (b == null) return; + final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT + ); + final int gap = getResources().getDimensionPixelSize(R.dimen.resolver_icon_margin) / 2; + lp.setMarginsRelative(gap, 0, gap, 0); + parent.addView(b, lp); + } + private ViewGroup displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent, LayoutInflater layoutInflater, ViewGroup parent) { ViewGroup layout = null; @@ -995,8 +1127,10 @@ public class ChooserActivity extends ResolverActivity implements ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_text, parent, false); - contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener( - this::onCopyButtonClicked); + final ViewGroup actionRow = + (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row); + addActionButton(actionRow, createCopyButton()); + addActionButton(actionRow, createNearbyButton(targetIntent)); CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (sharingText == null) { @@ -1154,7 +1288,8 @@ public class ChooserActivity extends ResolverActivity implements // TODO(b/120417119): Disable file copy until after moving to sysui, // due to permissions issues - contentPreviewLayout.findViewById(R.id.file_copy_button).setVisibility(View.GONE); + //((ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row)) + // .addView(createCopyButton()); String action = targetIntent.getAction(); if (Intent.ACTION_SEND.equals(action)) { @@ -1680,7 +1815,7 @@ public class ChooserActivity extends ResolverActivity implements } return intentFilter; } catch (Exception e) { - Log.e(TAG, "failed to get target intent filter " + e); + Log.e(TAG, "failed to get target intent filter", e); return null; } } @@ -2337,10 +2472,10 @@ public class ChooserActivity extends ResolverActivity implements } @Override // ResolverListCommunicator - public void onHandlePackagesChanged() { + public void onHandlePackagesChanged(ResolverListAdapter listAdapter) { mServicesRequested.clear(); mChooserMultiProfilePagerAdapter.getActiveListAdapter().notifyDataSetChanged(); - super.onHandlePackagesChanged(); + super.onHandlePackagesChanged(listAdapter); } @Override // SelectableTargetInfoCommunicator diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index ca3b7e7a7837..74ae29117b59 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -19,7 +19,6 @@ package com.android.internal.app; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE; import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.prediction.AppPredictor; import android.content.ComponentName; @@ -176,7 +175,7 @@ public class ChooserListAdapter extends ResolverListAdapter { Log.d(TAG, "clearing queryTargets on package change"); } createPlaceHolders(); - mChooserListCommunicator.onHandlePackagesChanged(); + mChooserListCommunicator.onHandlePackagesChanged(this); } @@ -541,7 +540,7 @@ public class ChooserListAdapter extends ResolverListAdapter { @Override AsyncTask<List<ResolvedComponentInfo>, Void, - List<ResolvedComponentInfo>> createSortingTask() { + List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) { return new AsyncTask<List<ResolvedComponentInfo>, Void, List<ResolvedComponentInfo>>() { @@ -554,9 +553,11 @@ public class ChooserListAdapter extends ResolverListAdapter { } @Override protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) { - processSortedList(sortedComponents); - mChooserListCommunicator.updateProfileViewButton(); - notifyDataSetChanged(); + processSortedList(sortedComponents, doPostProcessing); + if (doPostProcessing) { + mChooserListCommunicator.updateProfileViewButton(); + notifyDataSetChanged(); + } } }; } diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java index 663e0255feb9..e3501422f915 100644 --- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java @@ -38,8 +38,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd private final ChooserProfileDescriptor[] mItems; ChooserMultiProfilePagerAdapter(Context context, - ChooserActivity.ChooserGridAdapter adapter) { - super(context, /* currentPage */ 0); + ChooserActivity.ChooserGridAdapter adapter, + UserHandle personalProfileUserHandle, + UserHandle workProfileUserHandle) { + super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle); mItems = new ChooserProfileDescriptor[] { createProfileDescriptor(adapter) }; @@ -48,8 +50,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd ChooserMultiProfilePagerAdapter(Context context, ChooserActivity.ChooserGridAdapter personalAdapter, ChooserActivity.ChooserGridAdapter workAdapter, - @Profile int defaultProfile) { - super(context, /* currentPage */ defaultProfile); + @Profile int defaultProfile, + UserHandle personalProfileUserHandle, + UserHandle workProfileUserHandle) { + super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, + workProfileUserHandle); mItems = new ChooserProfileDescriptor[] { createProfileDescriptor(personalAdapter), createProfileDescriptor(workAdapter) @@ -131,6 +136,17 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd } @Override + public ResolverListAdapter getPersonalListAdapter() { + return getAdapterForIndex(PROFILE_PERSONAL).getListAdapter(); + } + + @Override + @Nullable + public ResolverListAdapter getWorkListAdapter() { + return getAdapterForIndex(PROFILE_WORK).getListAdapter(); + } + + @Override ChooserActivity.ChooserGridAdapter getCurrentRootAdapter() { return getAdapterForIndex(getCurrentPage()); } diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java index 89aa770d7f1c..92e9fe492442 100644 --- a/core/java/com/android/internal/app/NetInitiatedActivity.java +++ b/core/java/com/android/internal/app/NetInitiatedActivity.java @@ -23,7 +23,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.location.LocationManager; +import android.location.LocationManagerInternal; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -32,6 +32,7 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.location.GpsNetInitiatedHandler; +import com.android.server.LocalServices; /** * This activity is shown to the user for him/her to accept or deny network-initiated @@ -68,14 +69,14 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa private final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { - case GPS_NO_RESPONSE_TIME_OUT: { - if (notificationId != -1) { - sendUserResponse(default_response); + case GPS_NO_RESPONSE_TIME_OUT: { + if (notificationId != -1) { + sendUserResponse(default_response); + } + finish(); } - finish(); - } - break; - default: + break; + default: } } }; @@ -137,9 +138,8 @@ public class NetInitiatedActivity extends AlertActivity implements DialogInterfa // Respond to NI Handler under GnssLocationProvider, 1 = accept, 2 = deny private void sendUserResponse(int response) { if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response); - LocationManager locationManager = (LocationManager) - this.getSystemService(Context.LOCATION_SERVICE); - locationManager.sendNiResponse(notificationId, response); + LocationManagerInternal lm = LocalServices.getService(LocationManagerInternal.class); + lm.sendNiResponse(notificationId, response); } @UnsupportedAppUsage diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 30a41d338806..051534cc3eb1 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -16,7 +16,9 @@ package com.android.internal.app; +import static android.Manifest.permission.INTERACT_ACROSS_PROFILES; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.content.PermissionChecker.PID_UNKNOWN; import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL; import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_WORK; @@ -36,6 +38,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.PermissionChecker; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -157,7 +160,8 @@ public class ResolverActivity extends Activity implements private static final String TAB_TAG_PERSONAL = "personal"; private static final String TAB_TAG_WORK = "work"; - private final PackageMonitor mPackageMonitor = createPackageMonitor(); + private PackageMonitor mPersonalPackageMonitor; + private PackageMonitor mWorkPackageMonitor; @VisibleForTesting protected AbstractMultiProfilePagerAdapter mMultiProfilePagerAdapter; @@ -243,11 +247,11 @@ public class ResolverActivity extends Activity implements } } - protected PackageMonitor createPackageMonitor() { + protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) { return new PackageMonitor() { @Override public void onSomePackagesChanged() { - mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged(); + listAdapter.handlePackagesChanged(); updateProfileViewButton(); } @@ -327,8 +331,6 @@ public class ResolverActivity extends Activity implements mPm = getPackageManager(); - mPackageMonitor.register(this, getMainLooper(), false); - mRegistered = true; mReferrerPackage = getReferrerPackageName(); // Add our initial intent as the first item, regardless of what else has already been added. @@ -353,6 +355,18 @@ public class ResolverActivity extends Activity implements return; } + mPersonalPackageMonitor = createPackageMonitor( + mMultiProfilePagerAdapter.getPersonalListAdapter()); + mPersonalPackageMonitor.register( + this, getMainLooper(), getPersonalProfileUserHandle(), false); + if (hasWorkProfile()) { + mWorkPackageMonitor = createPackageMonitor( + mMultiProfilePagerAdapter.getWorkListAdapter()); + mWorkPackageMonitor.register(this, getMainLooper(), getWorkProfileUserHandle(), false); + } + + mRegistered = true; + final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel); if (rdl != null) { rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() { @@ -419,7 +433,9 @@ public class ResolverActivity extends Activity implements /* userHandle */ UserHandle.of(UserHandle.myUserId())); return new ResolverMultiProfilePagerAdapter( /* context */ this, - adapter); + adapter, + getPersonalProfileUserHandle(), + /* workProfileUserHandle= */ null); } private ResolverMultiProfilePagerAdapter createResolverMultiProfilePagerAdapterForTwoProfiles( @@ -438,20 +454,23 @@ public class ResolverActivity extends Activity implements == getPersonalProfileUserHandle().getIdentifier()), mUseLayoutForBrowsables, /* userHandle */ getPersonalProfileUserHandle()); + UserHandle workProfileUserHandle = getWorkProfileUserHandle(); ResolverListAdapter workAdapter = createResolverListAdapter( /* context */ this, /* payloadIntents */ mIntents, initialIntents, rList, (filterLastUsed && UserHandle.myUserId() - == getWorkProfileUserHandle().getIdentifier()), + == workProfileUserHandle.getIdentifier()), mUseLayoutForBrowsables, - /* userHandle */ getWorkProfileUserHandle()); + /* userHandle */ workProfileUserHandle); return new ResolverMultiProfilePagerAdapter( /* context */ this, personalAdapter, workAdapter, - /* defaultProfile */ getCurrentProfile()); + /* defaultProfile */ getCurrentProfile(), + getPersonalProfileUserHandle(), + getWorkProfileUserHandle()); } protected @Profile int getCurrentProfile() { @@ -543,9 +562,6 @@ public class ResolverActivity extends Activity implements public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged(); - if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) { - mMultiProfilePagerAdapter.getInactiveListAdapter().handlePackagesChanged(); - } if (mSystemWindowInsets != null) { mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top, @@ -707,7 +723,16 @@ public class ResolverActivity extends Activity implements protected void onRestart() { super.onRestart(); if (!mRegistered) { - mPackageMonitor.register(this, getMainLooper(), false); + mPersonalPackageMonitor.register(this, getMainLooper(), + getPersonalProfileUserHandle(), false); + if (hasWorkProfile()) { + if (mWorkPackageMonitor == null) { + mWorkPackageMonitor = createPackageMonitor( + mMultiProfilePagerAdapter.getWorkListAdapter()); + } + mWorkPackageMonitor.register(this, getMainLooper(), + getWorkProfileUserHandle(), false); + } mRegistered = true; } mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged(); @@ -718,7 +743,10 @@ public class ResolverActivity extends Activity implements protected void onStop() { super.onStop(); if (mRegistered) { - mPackageMonitor.unregister(); + mPersonalPackageMonitor.unregister(); + if (mWorkPackageMonitor != null) { + mWorkPackageMonitor.unregister(); + } mRegistered = false; } final Intent intent = getIntent(); @@ -913,26 +941,21 @@ public class ResolverActivity extends Activity implements } @Override // ResolverListCommunicator - public void onPostListReady(ResolverListAdapter listAdapter) { - if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() - == UserHandle.myUserId()) { - setHeader(); + public void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) { + if (isAutolaunching() || maybeAutolaunchActivity()) { + return; } - resetButtonBar(); - onListRebuilt(listAdapter); - } - - protected void onListRebuilt(ResolverListAdapter listAdapter) { - int count = listAdapter.getUnfilteredCount(); - if (count == 1 && listAdapter.getOtherProfile() == null) { - // Only one target, so we're a candidate to auto-launch! - final TargetInfo target = listAdapter.targetInfoForPosition(0, false); - if (shouldAutoLaunchSingleChoice(target)) { - safelyStartActivity(target); - finish(); + if (doPostProcessing) { + if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() + == UserHandle.myUserId()) { + setHeader(); } + resetButtonBar(); + onListRebuilt(listAdapter); } + } + protected void onListRebuilt(ResolverListAdapter listAdapter) { final ItemClickListener listener = new ItemClickListener(); setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener); } @@ -1132,6 +1155,11 @@ public class ResolverActivity extends Activity implements } private void safelyStartActivityInternal(TargetInfo cti) { + mPersonalPackageMonitor.unregister(); + if (mWorkPackageMonitor != null) { + mWorkPackageMonitor.unregister(); + } + mRegistered = false; // If needed, show that intent is forwarded // from managed profile to owner or other way around. if (mProfileSwitchMessageId != -1) { @@ -1247,7 +1275,11 @@ public class ResolverActivity extends Activity implements throw new IllegalStateException("mMultiProfilePagerAdapter.getCurrentListAdapter() " + "cannot be null."); } - boolean rebuildCompleted = mMultiProfilePagerAdapter.getActiveListAdapter().rebuildList(); + boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true); + + // We partially rebuild the inactive adapter to determine if we should auto launch + mMultiProfilePagerAdapter.rebuildInactiveTab(false); + if (useLayoutWithDefault()) { mLayoutId = R.layout.resolver_list_with_default; } else { @@ -1274,25 +1306,12 @@ public class ResolverActivity extends Activity implements * @return <code>true</code> if the activity is finishing and creation should halt. */ final boolean postRebuildListInternal(boolean rebuildCompleted) { - int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount(); // We only rebuild asynchronously when we have multiple elements to sort. In the case where // we're already done, we can check if we should auto-launch immediately. - if (rebuildCompleted) { - if (count == 1 - && mMultiProfilePagerAdapter.getActiveListAdapter().getOtherProfile() == null) { - // Only one target, so we're a candidate to auto-launch! - final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter() - .targetInfoForPosition(0, false); - if (shouldAutoLaunchSingleChoice(target)) { - safelyStartActivity(target); - mPackageMonitor.unregister(); - mRegistered = false; - finish(); - return true; - } - } + if (rebuildCompleted && maybeAutolaunchActivity()) { + return true; } setupViewVisibilities(); @@ -1304,6 +1323,129 @@ public class ResolverActivity extends Activity implements return false; } + private int isPermissionGranted(String permission, int uid) { + return ActivityManager.checkComponentPermission(permission, uid, + /* owningUid= */-1, /* exported= */ true); + } + + /** + * @return {@code true} if a resolved target is autolaunched, otherwise {@code false} + */ + private boolean maybeAutolaunchActivity() { + int numberOfProfiles = mMultiProfilePagerAdapter.getItemCount(); + if (numberOfProfiles == 1 && maybeAutolaunchIfSingleTarget()) { + return true; + } else if (numberOfProfiles == 2 && maybeAutolaunchIfCrossProfileSupported()) { + // note that autolaunching when we have 2 profiles, 1 resolved target on the active + // tab and 0 resolved targets on the inactive tab, is already handled before launching + // ResolverActivity + return true; + } + return false; + } + + private boolean maybeAutolaunchIfSingleTarget() { + int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount(); + if (count != 1) { + return false; + } + + // Only one target, so we're a candidate to auto-launch! + final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter() + .targetInfoForPosition(0, false); + if (shouldAutoLaunchSingleChoice(target)) { + safelyStartActivity(target); + finish(); + return true; + } + return false; + } + + /** + * When we have a personal and a work profile, we auto launch in the following scenario: + * - There is 1 resolved target on each profile + * - That target is the same app on both profiles + * - The target app has permission to communicate cross profiles + * - The target app has declared it supports cross-profile communication via manifest metadata + */ + private boolean maybeAutolaunchIfCrossProfileSupported() { + int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount(); + if (count != 1) { + return false; + } + ResolverListAdapter inactiveListAdapter = + mMultiProfilePagerAdapter.getInactiveListAdapter(); + if (inactiveListAdapter.getUnfilteredCount() != 1) { + return false; + } + TargetInfo activeProfileTarget = mMultiProfilePagerAdapter.getActiveListAdapter() + .targetInfoForPosition(0, false); + TargetInfo inactiveProfileTarget = inactiveListAdapter.targetInfoForPosition(0, false); + if (!Objects.equals(activeProfileTarget.getResolvedComponentName(), + inactiveProfileTarget.getResolvedComponentName())) { + return false; + } + if (!shouldAutoLaunchSingleChoice(activeProfileTarget)) { + return false; + } + String packageName = activeProfileTarget.getResolvedComponentName().getPackageName(); + if (!canAppInteractCrossProfiles(packageName)) { + return false; + } + + safelyStartActivity(activeProfileTarget); + finish(); + return true; + } + + /** + * Returns whether the package has the necessary permissions to interact across profiles on + * behalf of a given user. + * + * <p>This means meeting the following condition: + * <ul> + * <li>The app's {@link ApplicationInfo#crossProfile} flag must be true, and at least + * one of the following conditions must be fulfilled</li> + * <li>{@code Manifest.permission.INTERACT_ACROSS_USERS_FULL} granted.</li> + * <li>{@code Manifest.permission.INTERACT_ACROSS_USERS} granted.</li> + * <li>{@code Manifest.permission.INTERACT_ACROSS_PROFILES} granted, or the corresponding + * AppOps {@code android:interact_across_profiles} is set to "allow".</li> + * </ul> + * + */ + private boolean canAppInteractCrossProfiles(String packageName) { + ApplicationInfo applicationInfo; + try { + applicationInfo = getPackageManager().getApplicationInfo(packageName, 0); + } catch (NameNotFoundException e) { + Log.e(TAG, "Package " + packageName + " does not exist on current user."); + return false; + } + if (!applicationInfo.crossProfile) { + return false; + } + + int packageUid = applicationInfo.uid; + + if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + packageUid) == PackageManager.PERMISSION_GRANTED) { + return true; + } + if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS, packageUid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + if (PermissionChecker.checkPermissionForPreflight(this, INTERACT_ACROSS_PROFILES, + PID_UNKNOWN, packageUid, packageName) == PackageManager.PERMISSION_GRANTED) { + return true; + } + return false; + } + + private boolean isAutolaunching() { + return !mRegistered && isFinishing(); + } + private void setupProfileTabs() { TabHost tabHost = findViewById(R.id.profile_tabhost); tabHost.setup(); @@ -1499,12 +1641,20 @@ public class ResolverActivity extends Activity implements } @Override // ResolverListCommunicator - public void onHandlePackagesChanged() { - ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter(); - activeListAdapter.rebuildList(); - if (activeListAdapter.getCount() == 0) { - // We no longer have any items... just finish the activity. - finish(); + public void onHandlePackagesChanged(ResolverListAdapter listAdapter) { + if (listAdapter == mMultiProfilePagerAdapter.getActiveListAdapter()) { + boolean listRebuilt = mMultiProfilePagerAdapter.rebuildActiveTab(true); + if (listRebuilt) { + ResolverListAdapter activeListAdapter = + mMultiProfilePagerAdapter.getActiveListAdapter(); + activeListAdapter.notifyDataSetChanged(); + if (activeListAdapter.getCount() == 0) { + // We no longer have any items... just finish the activity. + finish(); + } + } + } else { + mMultiProfilePagerAdapter.clearInactiveProfileCache(); } } diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 405112d99fe7..2321da14cebe 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -113,7 +113,7 @@ public class ResolverListAdapter extends BaseAdapter { } public void handlePackagesChanged() { - mResolverListCommunicator.onHandlePackagesChanged(); + mResolverListCommunicator.onHandlePackagesChanged(this); } public void setPlaceholderCount(int count) { @@ -176,9 +176,14 @@ public class ResolverListAdapter extends BaseAdapter { * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work * to complete. * + * The {@code doPostProcessing } parameter is used to specify whether to update the UI and + * load additional targets (e.g. direct share) after the list has been rebuilt. This is used + * in the case where we want to load the inactive profile's resolved apps to know the + * number of targets. + * * @return Whether or not the list building is completed. */ - protected boolean rebuildList() { + protected boolean rebuildList(boolean doPostProcessing) { List<ResolvedComponentInfo> currentResolveList = null; // Clear the value of mOtherProfile from previous call. mOtherProfile = null; @@ -186,6 +191,7 @@ public class ResolverListAdapter extends BaseAdapter { mLastChosenPosition = -1; mAllTargetsAreBrowsers = false; mDisplayList.clear(); + if (mBaseResolveList != null) { currentResolveList = mUnfilteredResolveList = new ArrayList<>(); mResolverListController.addResolveListDedupe(currentResolveList, @@ -198,7 +204,7 @@ public class ResolverListAdapter extends BaseAdapter { mResolverListCommunicator.shouldGetActivityMetadata(), mIntents); if (currentResolveList == null) { - processSortedList(currentResolveList); + processSortedList(currentResolveList, doPostProcessing); return true; } List<ResolvedComponentInfo> originalList = @@ -256,22 +262,22 @@ public class ResolverListAdapter extends BaseAdapter { --placeholderCount; } setPlaceholderCount(placeholderCount); - createSortingTask().execute(currentResolveList); - postListReadyRunnable(); + createSortingTask(doPostProcessing).execute(currentResolveList); + postListReadyRunnable(doPostProcessing); return false; } else { - processSortedList(currentResolveList); + processSortedList(currentResolveList, doPostProcessing); return true; } } else { - processSortedList(currentResolveList); + processSortedList(currentResolveList, doPostProcessing); return true; } } AsyncTask<List<ResolvedComponentInfo>, Void, - List<ResolvedComponentInfo>> createSortingTask() { + List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) { return new AsyncTask<List<ResolvedComponentInfo>, Void, List<ResolvedComponentInfo>>() { @@ -283,15 +289,17 @@ public class ResolverListAdapter extends BaseAdapter { } @Override protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) { - processSortedList(sortedComponents); - mResolverListCommunicator.updateProfileViewButton(); + processSortedList(sortedComponents, doPostProcessing); notifyDataSetChanged(); + if (doPostProcessing) { + mResolverListCommunicator.updateProfileViewButton(); + } } }; } - - protected void processSortedList(List<ResolvedComponentInfo> sortedComponents) { + protected void processSortedList(List<ResolvedComponentInfo> sortedComponents, + boolean doPostProcessing) { int n; if (sortedComponents != null && (n = sortedComponents.size()) != 0) { mAllTargetsAreBrowsers = mUseLayoutForBrowsables; @@ -343,20 +351,23 @@ public class ResolverListAdapter extends BaseAdapter { } mResolverListCommunicator.sendVoiceChoicesIfNeeded(); - postListReadyRunnable(); + postListReadyRunnable(doPostProcessing); } /** * Some necessary methods for creating the list are initiated in onCreate and will also * determine the layout known. We therefore can't update the UI inline and post to the * handler thread to update after the current task is finished. + * @param doPostProcessing Whether to update the UI and load additional direct share targets + * after the list has been rebuilt */ - void postListReadyRunnable() { + void postListReadyRunnable(boolean doPostProcessing) { if (mPostListReadyRunnable == null) { mPostListReadyRunnable = new Runnable() { @Override public void run() { - mResolverListCommunicator.onPostListReady(ResolverListAdapter.this); + mResolverListCommunicator.onPostListReady(ResolverListAdapter.this, + doPostProcessing); mPostListReadyRunnable = null; } }; @@ -590,6 +601,12 @@ public class ResolverListAdapter extends BaseAdapter { return mResolverListController.getUserHandle(); } + protected List<ResolvedComponentInfo> getResolversForUser(UserHandle userHandle) { + return mResolverListController.getResolversForIntentAsUser(true, + mResolverListCommunicator.shouldGetActivityMetadata(), + mIntents, userHandle); + } + /** * Necessary methods to communicate between {@link ResolverListAdapter} * and {@link ResolverActivity}. @@ -600,7 +617,7 @@ public class ResolverListAdapter extends BaseAdapter { Intent getReplacementIntent(ActivityInfo activityInfo, Intent defIntent); - void onPostListReady(ResolverListAdapter listAdapter); + void onPostListReady(ResolverListAdapter listAdapter, boolean updateUi); void sendVoiceChoicesIfNeeded(); @@ -612,7 +629,7 @@ public class ResolverListAdapter extends BaseAdapter { Intent getTargetIntent(); - void onHandlePackagesChanged(); + void onHandlePackagesChanged(ResolverListAdapter listAdapter); } static class ViewHolder { diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 0bfe9eb04d28..022aded188fa 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -111,6 +111,15 @@ public class ResolverListController { boolean shouldGetResolvedFilter, boolean shouldGetActivityMetadata, List<Intent> intents) { + return getResolversForIntentAsUser(shouldGetResolvedFilter, shouldGetActivityMetadata, + intents, mUserHandle); + } + + public List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUser( + boolean shouldGetResolvedFilter, + boolean shouldGetActivityMetadata, + List<Intent> intents, + UserHandle userHandle) { List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null; for (int i = 0, N = intents.size(); i < N; i++) { final Intent intent = intents.get(i); @@ -122,7 +131,7 @@ public class ResolverListController { flags |= PackageManager.MATCH_INSTANT; } final List<ResolveInfo> infos = mpm.queryIntentActivitiesAsUser(intent, flags, - mUserHandle); + userHandle); if (infos != null) { if (resolvedComponents == null) { resolvedComponents = new ArrayList<>(); diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java index 9d3c6c9ad8b1..96dc83a3f683 100644 --- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java @@ -36,8 +36,10 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA private final ResolverProfileDescriptor[] mItems; ResolverMultiProfilePagerAdapter(Context context, - ResolverListAdapter adapter) { - super(context, /* currentPage */ 0); + ResolverListAdapter adapter, + UserHandle personalProfileUserHandle, + UserHandle workProfileUserHandle) { + super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle); mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(adapter) }; @@ -46,8 +48,11 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA ResolverMultiProfilePagerAdapter(Context context, ResolverListAdapter personalAdapter, ResolverListAdapter workAdapter, - @Profile int defaultProfile) { - super(context, /* currentPage */ defaultProfile); + @Profile int defaultProfile, + UserHandle personalProfileUserHandle, + UserHandle workProfileUserHandle) { + super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, + workProfileUserHandle); mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(personalAdapter), createProfileDescriptor(workAdapter) @@ -116,6 +121,17 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA } @Override + public ResolverListAdapter getPersonalListAdapter() { + return getAdapterForIndex(PROFILE_PERSONAL); + } + + @Override + @Nullable + public ResolverListAdapter getWorkListAdapter() { + return getAdapterForIndex(PROFILE_WORK); + } + + @Override ResolverListAdapter getCurrentRootAdapter() { return getActiveListAdapter(); } diff --git a/core/java/com/android/internal/logging/InstanceId.java b/core/java/com/android/internal/logging/InstanceId.java index 85dbac3f59bb..85643fcffa2f 100644 --- a/core/java/com/android/internal/logging/InstanceId.java +++ b/core/java/com/android/internal/logging/InstanceId.java @@ -16,20 +16,33 @@ package com.android.internal.logging; +import static java.lang.Math.max; +import static java.lang.Math.min; + import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; /** * An opaque identifier used to disambiguate which logs refer to a particular instance of some * UI element. Useful when there might be multiple instances simultaneously active. - * Obtain from InstanceIdSequence. + * Obtain from InstanceIdSequence. Clipped to range [0, INSTANCE_ID_MAX]. */ -public class InstanceId { - private int mId; - protected InstanceId(int id) { - mId = id; +public final class InstanceId implements Parcelable { + // At most 20 bits: ~1m possibilities, ~0.5% probability of collision in 100 values + static final int INSTANCE_ID_MAX = 1 << 20; + + private final int mId; + InstanceId(int id) { + mId = min(max(0, id), INSTANCE_ID_MAX); + } + + private InstanceId(Parcel in) { + this(in.readInt()); } + @VisibleForTesting public int getId() { return mId; @@ -47,4 +60,28 @@ public class InstanceId { } return mId == ((InstanceId) obj).mId; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mId); + } + + public static final Parcelable.Creator<InstanceId> CREATOR = + new Parcelable.Creator<InstanceId>() { + @Override + public InstanceId createFromParcel(Parcel in) { + return new InstanceId(in); + } + + @Override + public InstanceId[] newArray(int size) { + return new InstanceId[size]; + } + }; + } diff --git a/core/java/com/android/internal/logging/InstanceIdSequence.java b/core/java/com/android/internal/logging/InstanceIdSequence.java index 2e78ed8c5185..aa507e538944 100644 --- a/core/java/com/android/internal/logging/InstanceIdSequence.java +++ b/core/java/com/android/internal/logging/InstanceIdSequence.java @@ -19,6 +19,8 @@ package com.android.internal.logging; import static java.lang.Math.max; import static java.lang.Math.min; +import com.android.internal.annotations.VisibleForTesting; + import java.security.SecureRandom; import java.util.Random; @@ -28,8 +30,6 @@ import java.util.Random; * first use; try to give it a long lifetime. Safe for concurrent use. */ public class InstanceIdSequence { - // At most 20 bits: ~1m possibilities, ~0.5% probability of collision in 100 values - private static final int INSTANCE_ID_MAX = 1 << 20; protected final int mInstanceIdMax; private final Random mRandom = new SecureRandom(); @@ -39,7 +39,7 @@ public class InstanceIdSequence { * an all-zero sequence. */ public InstanceIdSequence(int instanceIdMax) { - mInstanceIdMax = min(max(0, instanceIdMax), INSTANCE_ID_MAX); + mInstanceIdMax = min(max(0, instanceIdMax), InstanceId.INSTANCE_ID_MAX); } /** @@ -47,6 +47,16 @@ public class InstanceIdSequence { * @return new InstanceId */ public InstanceId newInstanceId() { - return new InstanceId(mRandom.nextInt(mInstanceIdMax)); + return newInstanceIdInternal(mRandom.nextInt(mInstanceIdMax)); + } + + /** + * Factory function for instance IDs, used for testing. + * @param id + * @return new InstanceId(id) + */ + @VisibleForTesting + protected InstanceId newInstanceIdInternal(int id) { + return new InstanceId(id); } } diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 7adb27cd9e36..db009f68d28a 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -468,7 +468,8 @@ public class RuntimeInit { try { if (ActivityManager.getService().handleApplicationWtf( mApplicationObject, tag, system, - new ApplicationErrorReport.ParcelableCrashInfo(t))) { + new ApplicationErrorReport.ParcelableCrashInfo(t), + Process.myPid())) { // The Activity Manager has already written us off -- now exit. Process.killProcess(Process.myPid()); System.exit(10); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index f13a638f7844..863e8a2f384d 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -2125,8 +2125,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return new Pair<>(Insets.NONE, insets); } - boolean includeIme = (getAttributes().softInputMode & SOFT_INPUT_MASK_ADJUST) - == SOFT_INPUT_ADJUST_RESIZE; + boolean includeIme = + (getViewRootImpl().mWindowAttributes.softInputMode & SOFT_INPUT_MASK_ADJUST) + == SOFT_INPUT_ADJUST_RESIZE; Insets insetsToApply; if (ViewRootImpl.sNewInsetsMode == 0) { insetsToApply = insets.getSystemWindowInsets(); diff --git a/core/java/com/android/internal/util/LocationPermissionChecker.java b/core/java/com/android/internal/util/LocationPermissionChecker.java index 2db0e9979d94..cd8fc350362d 100644 --- a/core/java/com/android/internal/util/LocationPermissionChecker.java +++ b/core/java/com/android/internal/util/LocationPermissionChecker.java @@ -17,6 +17,7 @@ package com.android.internal.util; import android.Manifest; +import android.annotation.IntDef; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; @@ -26,11 +27,13 @@ import android.location.LocationManager; import android.os.Binder; import android.os.Build; import android.os.UserHandle; -import android.os.UserManager; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * The methods used for location permission and location mode checking. @@ -41,17 +44,27 @@ public class LocationPermissionChecker { private static final String TAG = "LocationPermissionChecker"; + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"LOCATION_PERMISSION_CHECK_STATUS_"}, value = { + SUCCEEDED, + ERROR_LOCATION_MODE_OFF, + ERROR_LOCATION_PERMISSION_MISSING, + }) + public @interface LocationPermissionCheckStatus{} + + // The location permission check succeeded. + public static final int SUCCEEDED = 0; + // The location mode turns off for the caller. + public static final int ERROR_LOCATION_MODE_OFF = 1; + // The location permission isn't granted for the caller. + public static final int ERROR_LOCATION_PERMISSION_MISSING = 2; + private final Context mContext; private final AppOpsManager mAppOpsManager; - private final UserManager mUserManager; - private final LocationManager mLocationManager; public LocationPermissionChecker(Context context) { mContext = context; mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - mLocationManager = - (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } /** @@ -71,12 +84,38 @@ public class LocationPermissionChecker { */ public boolean checkLocationPermission(String pkgName, @Nullable String featureId, int uid, @Nullable String message) { - try { - enforceLocationPermission(pkgName, featureId, uid, message); - return true; - } catch (SecurityException e) { - return false; + return checkLocationPermissionInternal(pkgName, featureId, uid, message) == SUCCEEDED; + } + + /** + * Check location permission granted by the caller. + * + * This API check if the location mode enabled for the caller and the caller has + * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION. + * Compared with {@link #checkLocationPermission(String, String, int, String)}, this API returns + * the detail information about the checking result, including the reason why it's failed and + * logs the error for the caller. + * + * @param pkgName package name of the application requesting access + * @param featureId The feature in the package + * @param uid The uid of the package + * @param message A message describing why the permission was checked. Only needed if this is + * not inside of a two-way binder call from the data receiver + * + * @return {@link LocationPermissionCheckStatus} the result of the location permission check. + */ + public @LocationPermissionCheckStatus int checkLocationPermissionWithDetailInfo( + String pkgName, @Nullable String featureId, int uid, @Nullable String message) { + final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); + switch (result) { + case ERROR_LOCATION_MODE_OFF: + Log.e(TAG, "Location mode is disabled for the device"); + break; + case ERROR_LOCATION_PERMISSION_MISSING: + Log.e(TAG, "UID " + uid + " has no location permission"); + break; } + return result; } /** @@ -94,20 +133,32 @@ public class LocationPermissionChecker { */ public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid, @Nullable String message) throws SecurityException { + final int result = checkLocationPermissionInternal(pkgName, featureId, uid, message); + + switch (result) { + case ERROR_LOCATION_MODE_OFF: + throw new SecurityException("Location mode is disabled for the device"); + case ERROR_LOCATION_PERMISSION_MISSING: + throw new SecurityException("UID " + uid + " has no location permission"); + } + } + private int checkLocationPermissionInternal(String pkgName, @Nullable String featureId, + int uid, @Nullable String message) { checkPackage(uid, pkgName); // Location mode must be enabled if (!isLocationModeEnabled()) { - throw new SecurityException("Location mode is disabled for the device"); + return ERROR_LOCATION_MODE_OFF; } // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to // location information. - if (!checkCallersLocationPermission(pkgName, featureId, - uid, /* coarseForTargetSdkLessThanQ */ true, message)) { - throw new SecurityException("UID " + uid + " has no location permission"); + if (!checkCallersLocationPermission(pkgName, featureId, uid, + true /* coarseForTargetSdkLessThanQ */, message)) { + return ERROR_LOCATION_PERMISSION_MISSING; } + return SUCCEEDED; } /** @@ -155,8 +206,10 @@ public class LocationPermissionChecker { * Retrieves a handle to LocationManager (if not already done) and check if location is enabled. */ public boolean isLocationModeEnabled() { + final LocationManager LocationManager = + (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); try { - return mLocationManager.isLocationEnabledForUser(UserHandle.of( + return LocationManager.isLocationEnabledForUser(UserHandle.of( getCurrentUser())); } catch (Exception e) { Log.e(TAG, "Failure to get location mode via API, falling back to settings", e); diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index f9e98e7eb473..69b1609377b7 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -29,7 +29,6 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; -import android.view.WindowManager; import android.widget.PopupWindow; import com.android.internal.R; @@ -211,8 +210,7 @@ public final class FloatingActionMode extends ActionMode { } private boolean isContentRectWithinBounds() { - mContext.getSystemService(WindowManager.class) - .getDefaultDisplay().getRealSize(mDisplaySize); + mContext.getDisplay().getRealSize(mDisplaySize); mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y); return intersectsClosed(mContentRectOnScreen, mScreenRect) diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index bac602509148..0aeaa47ba3d8 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -24,10 +24,12 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; +import android.util.Size; import android.view.Display; import android.view.Gravity; import android.view.View; import android.view.WindowManager; +import android.view.WindowMetrics; import android.widget.PopupWindow.OnDismissListener; import com.android.internal.view.menu.MenuPresenter.Callback; @@ -224,13 +226,10 @@ public class MenuPopupHelper implements MenuHelper { */ @NonNull private MenuPopup createPopup() { - final WindowManager windowManager = (WindowManager) mContext.getSystemService( - Context.WINDOW_SERVICE); - final Display display = windowManager.getDefaultDisplay(); - final Point displaySize = new Point(); - display.getRealSize(displaySize); + final WindowManager windowManager = mContext.getSystemService(WindowManager.class); + final Size maxWindowSize = windowManager.getMaximumWindowMetrics().getSize(); - final int smallestWidth = Math.min(displaySize.x, displaySize.y); + final int smallestWidth = Math.min(maxWindowSize.getWidth(), maxWindowSize.getHeight()); final int minSmallestWidthCascading = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.cascading_menus_min_smallest_width); final boolean enableCascadingSubmenus = smallestWidth >= minSmallestWidthCascading; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index a2f514a85ff8..c04efa3be596 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -147,7 +147,6 @@ cc_library_shared { "android_service_DataLoaderService.cpp", "android_util_AssetManager.cpp", "android_util_Binder.cpp", - "android_util_StatsLog.cpp", "android_util_MemoryIntArray.cpp", "android_util_Process.cpp", "android_util_StringBlock.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9783b655e057..790ac080e705 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -108,7 +108,6 @@ namespace android { extern int register_android_app_admin_SecurityLog(JNIEnv* env); extern int register_android_content_AssetManager(JNIEnv* env); extern int register_android_util_EventLog(JNIEnv* env); -extern int register_android_util_StatsLog(JNIEnv* env); extern int register_android_util_StatsLogInternal(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); extern int register_android_util_MemoryIntArray(JNIEnv* env); @@ -1441,7 +1440,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_MemoryIntArray), - REG_JNI(register_android_util_StatsLog), REG_JNI(register_android_util_StatsLogInternal), REG_JNI(register_android_app_admin_SecurityLog), REG_JNI(register_android_content_AssetManager), diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp index 4de6c863638f..39483b55992b 100644 --- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp +++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp @@ -277,13 +277,6 @@ private: SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage) { - static bool gInited; - - if (!gInited) { - - gInited = true; - } - return new SkJavaOutputStream(env, stream, storage); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 181a32d06233..3a1b63d56b5f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4858,19 +4858,6 @@ <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES" android:protectionLevel="signature|installer" /> - <!-- Allows an app to log compat change usage. - @hide <p>Not for use by third-party applications.</p> --> - <permission android:name="android.permission.LOG_COMPAT_CHANGE" - android:protectionLevel="signature" /> - <!-- Allows an app to read compat change config. - @hide <p>Not for use by third-party applications.</p> --> - <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" - android:protectionLevel="signature" /> - <!-- Allows an app to override compat change config. - @hide <p>Not for use by third-party applications.</p> --> - <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" - android:protectionLevel="signature" /> - <!-- Allows input events to be monitored. Very dangerous! @hide --> <permission android:name="android.permission.MONITOR_INPUT" android:protectionLevel="signature" /> diff --git a/core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index d915d416ff30..000000000000 --- a/core/res/res/drawable-hdpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-ldpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index d88250ae2325..000000000000 --- a/core/res/res/drawable-ldpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index 47306683f374..000000000000 --- a/core/res/res/drawable-mdpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/drawable-xhdpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index e4e6a5a70df2..000000000000 --- a/core/res/res/drawable-xhdpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/drawable/chooser_action_button_bg.xml b/core/res/res/drawable/chooser_action_button_bg.xml new file mode 100644 index 000000000000..a434c0b9b6a9 --- /dev/null +++ b/core/res/res/drawable/chooser_action_button_bg.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/lighter_gray"> + <item> + <inset + android:insetLeft="0dp" + android:insetTop="8dp" + android:insetRight="0dp" + android:insetBottom="8dp"> + <shape android:shape="rectangle"> + <corners android:radius="16dp"></corners> + <stroke android:width="1dp" + android:color="?attr/textColorSecondary" /> + <solid android:color="?attr/colorBackground" /> + </shape> + </inset> + </item> +</ripple> diff --git a/core/res/res/drawable/ic_content_copy_gm2.xml b/core/res/res/drawable/ic_content_copy_gm2.xml deleted file mode 100644 index ee58738b75d0..000000000000 --- a/core/res/res/drawable/ic_content_copy_gm2.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <path - android:fillColor="?android:attr/textColorSecondary" - android:pathData="M18,21L4,21L4,7L2,7v14c0,1.1 0.9,2 2,2h14v-2zM21,17L21,3c0,-1.1 -0.9,-2 -2,-2L8,1c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2zM19,17L8,17L8,3h11v14z"/> -</vector> diff --git a/core/res/res/drawable/ic_menu_copy_material.xml b/core/res/res/drawable/ic_menu_copy_material.xml index c03723b1fb33..8c9f1c514b97 100644 --- a/core/res/res/drawable/ic_menu_copy_material.xml +++ b/core/res/res/drawable/ic_menu_copy_material.xml @@ -1,26 +1,27 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. --> + <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0" - android:autoMirrored="true" - android:tint="?attr/colorControlNormal"> - <path - android:pathData="M16,1L4,1C2.9,1 2,1.9 2,3l0,14l2,0L4,3l12,0L16,1zM19,5L8,5C6.9,5 6,5.9 6,7l0,14c0,1.1 0.9,2 2,2l11,0c1.1,0 2,-0.9 2,-2L21,7C21,5.9 20.1,5 19,5zM19,21L8,21L8,7l11,0L19,21z" - android:fillColor="@color/white"/> + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:autoMirrored="true" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@color/white" + android:pathData="M18,21L4,21L4,7L2,7v14c0,1.1 0.9,2 2,2h14v-2zM21,17L21,3c0,-1.1 -0.9,-2 -2,-2L8,1c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2zM19,17L8,17L8,3h11v14z"/> </vector> diff --git a/core/res/res/drawable/sym_app_on_sd_unavailable_icon.xml b/core/res/res/drawable/sym_app_on_sd_unavailable_icon.xml new file mode 100644 index 000000000000..50f15cab1814 --- /dev/null +++ b/core/res/res/drawable/sym_app_on_sd_unavailable_icon.xml @@ -0,0 +1,47 @@ +<?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. +--> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/sym_def_app_icon_background" /> + <foreground > + <vector + android:height="108dp" + android:width="108dp" + android:viewportHeight="108.0" + android:viewportWidth="108.0"> + <path android:fillColor="#202124" android:pathData=" +M68,54h-7.25L54,60.75V76c0,2.2,1.8,4,4,4h10c2.2,0,4-1.8,4-4V58C72,55.8,70.2,54,68,54z"/> + + <path android:fillColor="#FFFFFF" android:pathData=" +M64.59,34.48l3.9-3.9c0.6-0.6,0.6-1.53,0-2.13c-0.6-0.6-1.53-0.6-2.13,0l-4.44,4.44 +C59.55,31.69,56.85,31,54,31c-2.88,0-5.58,0.69-7.98,1.89l-4.47-4.44c-0.6-0.6-1.53-0.6-2.13,0c-0.6,0.6-0.6,1.53,0,2.13l3.93,3.93 +C38.91,37.78,36,43.03,36,49h36C72,43.03,69.09,37.75,64.59,34.48z M48,43h-3v-3h3V43z M63,43h-3v-3h3V43z + +M52,76.01C52,76,52,76,52,76.01l0-15.26v-0.83l0,0v-0.01h0.01l0.58-0.58l6.75-6.75L59.92,52v0H40 +c-2.21,0-4,1.79-4,4v20c0,2.21,1.79,4,4,4h12V76.01z + +M66.84,68.75h-2.81v6.75h2.81c0.93,0,1.69-0.75,1.69-1.69v-3.38C68.52,69.5,67.77,68.75,66.84,68.75z +M66.84,73.81h-1.12v-3.38h1.12V73.81z + +M63.02,70.16h-3.09v1.27h1.97c0.62,0,1.12,0.64,1.12,1.26v1.69c0,0.62-0.51,1.12-1.12,1.12h-3.38v-1.41 +h3.09v-1.27h-1.96c-0.62,0-1.12-0.64-1.12-1.26v-1.69c0-0.62,0.51-1.12,1.12-1.12h3.36V70.16z"/> + + <path android:fillColor="#FFE082" android:pathData=" +M 59 58.5 h 2.5 v 4.5 h -2.5z +M 62.5 58.5 h 2.5 v 4.5 h -2.5z +M 66 58.5 h 2.5 v 4.5 h -2.5z"/> + </vector> + </foreground> +</adaptive-icon> diff --git a/core/res/res/layout/chooser_action_button.xml b/core/res/res/layout/chooser_action_button.xml new file mode 100644 index 000000000000..119b2e90292d --- /dev/null +++ b/core/res/res/layout/chooser_action_button.xml @@ -0,0 +1,30 @@ +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + android:gravity="center_vertical|start" + android:paddingStart="12dp" + android:paddingEnd="12dp" + android:drawablePadding="8dp" + android:textColor="?android:textColorSecondary" + android:textSize="12sp" + android:maxWidth="192dp" + android:singleLine="true" + android:clickable="true" + android:background="@drawable/chooser_action_button_bg" + android:drawableTint="?android:attr/colorControlNormal" + android:drawableTintMode="src_in" + /> diff --git a/core/res/res/layout/chooser_action_row.xml b/core/res/res/layout/chooser_action_row.xml new file mode 100644 index 000000000000..ea7561124181 --- /dev/null +++ b/core/res/res/layout/chooser_action_row.xml @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (C) 2019 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingLeft="@dimen/chooser_edge_margin_normal" + android:paddingRight="@dimen/chooser_edge_margin_normal" + android:gravity="center" + > + +</LinearLayout> diff --git a/core/res/res/layout/chooser_grid_preview_file.xml b/core/res/res/layout/chooser_grid_preview_file.xml index f7d60c91052d..2a39215a4bd8 100644 --- a/core/res/res/layout/chooser_grid_preview_file.xml +++ b/core/res/res/layout/chooser_grid_preview_file.xml @@ -65,13 +65,15 @@ android:gravity="start|top" android:paddingRight="24dp" android:singleLine="true"/> - <Button - android:id="@+id/file_copy_button" - android:layout_width="24dp" - android:layout_height="24dp" - android:gravity="center" - android:layout_gravity="center_vertical" - android:background="@drawable/ic_content_copy_gm2"/> </LinearLayout> + + <include + android:id="@+id/chooser_action_row" + layout="@layout/chooser_action_row" + android:layout_width="@dimen/chooser_preview_width" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/chooser_view_spacing" + android:layout_gravity="center" + /> </LinearLayout> diff --git a/core/res/res/layout/chooser_grid_preview_image.xml b/core/res/res/layout/chooser_grid_preview_image.xml index 79a0de4b271f..62df1650612a 100644 --- a/core/res/res/layout/chooser_grid_preview_image.xml +++ b/core/res/res/layout/chooser_grid_preview_image.xml @@ -78,5 +78,15 @@ android:scaleType="centerCrop"/> </RelativeLayout> + + <include + android:id="@+id/chooser_action_row" + layout="@layout/chooser_action_row" + android:layout_width="@dimen/chooser_preview_width" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/chooser_view_spacing" + android:layout_gravity="center" + /> + </LinearLayout> diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml index 4d7846dfb9cc..002917463ab3 100644 --- a/core/res/res/layout/chooser_grid_preview_text.xml +++ b/core/res/res/layout/chooser_grid_preview_text.xml @@ -37,10 +37,9 @@ <TextView android:id="@+id/content_preview_text" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_toStartOf="@id/copy_button" android:layout_centerVertical="true" android:ellipsize="end" android:fontFamily="@android:string/config_headlineFontFamily" @@ -48,40 +47,17 @@ android:maxLines="2" android:focusable="true"/> - <LinearLayout - android:id="@+id/copy_button" - android:orientation="vertical" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerVertical="true" - android:layout_alignParentEnd="true" - android:layout_marginStart="@dimen/chooser_view_spacing" - android:gravity="center" - android:minWidth="48dp" - android:minHeight="48dp" - android:clickable="true" - style="?attr/borderlessButtonStyle"> - - <ImageView - android:layout_width="24dp" - android:layout_height="24dp" - android:gravity="top|center_horizontal" - android:src="@drawable/ic_content_copy_gm2" /> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:gravity="center_horizontal" - android:text="@string/copy" - android:textColor="?android:textColorSecondary" - android:textSize="12sp" - android:maxWidth="72dp" - android:maxLines="2" - android:ellipsize="end" /> - </LinearLayout> </RelativeLayout> + <include + android:id="@+id/chooser_action_row" + layout="@layout/chooser_action_row" + android:layout_width="@dimen/chooser_preview_width" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/chooser_view_spacing" + android:layout_gravity="center" + /> + <!-- Required sub-layout so we can get the nice rounded corners--> <!-- around this section --> <LinearLayout diff --git a/core/res/res/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index d915d416ff30..000000000000 --- a/core/res/res/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index d88250ae2325..000000000000 --- a/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png Binary files differdeleted file mode 100644 index 47306683f374..000000000000 --- a/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png +++ /dev/null diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e98f8ba3cda7..52b92d2660da 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4323,4 +4323,12 @@ <item>4</item> <!-- PROCESS_STATE_FOREGROUND_SERVICE --> <item>12</item> <!-- PROCESS_STATE_TOP_SLEEPING --> </integer-array> + + <!-- Component name that accepts ACTION_SEND intents for nearby (proximity-based) sharing. + Used by ChooserActivity. --> + <string translatable="false" name="config_defaultNearbySharingComponent"></string> + + <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing + check after reboot or airplane mode toggling --> + <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index d437aa1c340c..0b5082cdaf94 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -774,6 +774,8 @@ <dimen name="resolver_edge_margin">24dp</dimen> <dimen name="resolver_elevation">1dp</dimen> + <dimen name="chooser_action_button_icon_size">18dp</dimen> + <!-- Assistant handles --> <dimen name="assist_handle_shadow_radius">2dp</dimen> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index ddd9ba43fe09..51ed08b88111 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -194,6 +194,9 @@ <!-- A tag used to save the index where the custom view is stored --> <item type="id" name="notification_custom_view_index_tag" /> + <!-- Marks the "copy to clipboard" button in the ChooserActivity --> + <item type="id" name="chooser_copy_button" /> + <!-- Accessibility action identifier for {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK}. --> <item type="id" name="accessibilitySystemActionBack" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e4717f817688..21128e33b6e5 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -66,8 +66,7 @@ <java-symbol type="id" name="content_preview_text_layout" /> <java-symbol type="id" name="content_preview_title" /> <java-symbol type="id" name="content_preview_title_layout" /> - <java-symbol type="id" name="copy_button" /> - <java-symbol type="id" name="file_copy_button" /> + <java-symbol type="id" name="chooser_action_row" /> <java-symbol type="id" name="current_scene" /> <java-symbol type="id" name="scene_layoutid_cache" /> <java-symbol type="id" name="customPanel" /> @@ -3783,6 +3782,11 @@ <java-symbol type="string" name="config_factoryResetPackage" /> <java-symbol type="array" name="config_highRefreshRateBlacklist" /> + <java-symbol type="id" name="chooser_copy_button" /> + <java-symbol type="layout" name="chooser_action_button" /> + <java-symbol type="dimen" name="chooser_action_button_icon_size" /> + <java-symbol type="string" name="config_defaultNearbySharingComponent" /> + <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" /> <java-symbol type="bool" name="config_showBuiltinWirelessChargingAnim" /> diff --git a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java b/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java index 8a22aca6464d..a027f9eb3a4e 100644 --- a/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java +++ b/core/tests/coretests/BstatsTestApp/src/com/android/coretests/apps/bstatstestapp/TestService.java @@ -22,12 +22,12 @@ import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.graphics.Color; -import android.graphics.Point; import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.util.Log; +import android.util.Size; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -108,16 +108,15 @@ public class TestService extends Service { @Override public void showApplicationOverlay() throws RemoteException { final WindowManager wm = TestService.this.getSystemService(WindowManager.class); - final Point size = new Point(); - wm.getDefaultDisplay().getSize(size); + final Size size = wm.getCurrentWindowMetrics().getSize(); final WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams( WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - wmlp.width = size.x / 2; - wmlp.height = size.y / 2; + wmlp.width = size.getWidth() / 2; + wmlp.height = size.getHeight() / 2; wmlp.gravity = Gravity.CENTER | Gravity.LEFT; wmlp.setTitle(TAG); diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java index b1a54dcced46..f074233070d1 100644 --- a/core/tests/coretests/src/android/content/ContextTest.java +++ b/core/tests/coretests/src/android/content/ContextTest.java @@ -48,6 +48,7 @@ public class ContextTest { assertEquals(testContext.getDisplay().getDisplayId(), testContext.getDisplayId()); } + // TODO(b/128338354): Re-visit this test after introducing WindowContext @Test public void testDisplayIdForDefaultDisplayContext() { final Context testContext = diff --git a/core/tests/coretests/src/android/util/GridScenario.java b/core/tests/coretests/src/android/util/GridScenario.java index 0f1730e207d5..4809a213ab48 100644 --- a/core/tests/coretests/src/android/util/GridScenario.java +++ b/core/tests/coretests/src/android/util/GridScenario.java @@ -233,7 +233,7 @@ public abstract class GridScenario extends Activity { // turn off title bar requestWindowFeature(Window.FEATURE_NO_TITLE); - mScreenHeight = getWindowManager().getDefaultDisplay().getHeight(); + mScreenHeight = getWindowManager().getCurrentWindowMetrics().getSize().getHeight(); final Params params = new Params(); init(params); diff --git a/core/tests/coretests/src/android/util/ListScenario.java b/core/tests/coretests/src/android/util/ListScenario.java index 129484af75de..d4e5a438d855 100644 --- a/core/tests/coretests/src/android/util/ListScenario.java +++ b/core/tests/coretests/src/android/util/ListScenario.java @@ -306,7 +306,7 @@ public abstract class ListScenario extends Activity { requestWindowFeature(Window.FEATURE_NO_TITLE); - mScreenHeight = getWindowManager().getDefaultDisplay().getHeight(); + mScreenHeight = getWindowManager().getCurrentWindowMetrics().getSize().getHeight(); final Params params = createParams(); init(params); diff --git a/core/tests/coretests/src/android/util/ScrollViewScenario.java b/core/tests/coretests/src/android/util/ScrollViewScenario.java index e9eb978805bf..2c0aa7362dfa 100644 --- a/core/tests/coretests/src/android/util/ScrollViewScenario.java +++ b/core/tests/coretests/src/android/util/ScrollViewScenario.java @@ -239,7 +239,7 @@ public abstract class ScrollViewScenario extends Activity { // for test stability, turn off title bar requestWindowFeature(Window.FEATURE_NO_TITLE); - int screenHeight = getWindowManager().getDefaultDisplay().getHeight() + int screenHeight = getWindowManager().getCurrentWindowMetrics().getSize().getHeight() - 25; mLinearLayout = new LinearLayout(this); mLinearLayout.setOrientation(LinearLayout.VERTICAL); diff --git a/core/tests/coretests/src/android/view/BigCache.java b/core/tests/coretests/src/android/view/BigCache.java index 6a1bcaaf2d00..e465a859218a 100644 --- a/core/tests/coretests/src/android/view/BigCache.java +++ b/core/tests/coretests/src/android/view/BigCache.java @@ -18,6 +18,7 @@ package android.view; import android.app.Activity; import android.os.Bundle; +import android.util.Size; import android.widget.LinearLayout; import android.widget.ScrollView; @@ -38,9 +39,9 @@ public class BigCache extends Activity { ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); final int cacheSize = ViewConfiguration.getMaximumDrawingCacheSize(); - final Display display = getWindowManager().getDefaultDisplay(); - final int screenWidth = display.getWidth(); - final int screenHeight = display.getHeight(); + final Size windowSize = getWindowManager().getCurrentWindowMetrics().getSize(); + final int screenWidth = windowSize.getWidth(); + final int screenHeight = windowSize.getHeight(); final View tiny = new View(this); tiny.setId(R.id.a); diff --git a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java index f63a4548b478..039387c85b11 100644 --- a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java +++ b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java @@ -22,8 +22,7 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import android.content.Context; -import android.util.DisplayMetrics; +import android.util.Size; import android.widget.TextView; import androidx.test.filters.LargeTest; @@ -54,25 +53,23 @@ public class ScaleGestureDetectorTest { final float initialScaleFactor = 1.0f; assertEquals(initialScaleFactor, mScaleGestureActivity.getScaleFactor(), 0f); - // Specify start and end coordinates, irrespective of device display size. - final DisplayMetrics dm = new DisplayMetrics(); - final WindowManager wm = (WindowManager) (mScaleGestureActivity.getApplicationContext()) - .getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(dm); - final int displayWidth = dm.widthPixels; - final int displayHeight = dm.heightPixels; + // Specify start and end coordinates with respect to the window size. + final WindowManager wm = mScaleGestureActivity.getSystemService(WindowManager.class); + final Size windowSize = wm.getCurrentWindowMetrics().getSize(); + final int windowWidth = windowSize.getWidth(); + final int windowHeight = windowSize.getHeight(); // Obtain coordinates to perform pinch and zoom from the center, to 75% of the display. - final int centerX = displayWidth / 2; - final int centerY = displayHeight / 2; + final int centerX = windowWidth / 2; + final int centerY = windowHeight / 2; // Offset center coordinates by one, so that the two starting points are different. final float[] firstFingerStartCoords = new float[] {centerX + 1.0f, centerY - 1.0f}; final float[] firstFingerEndCoords = - new float[] {0.75f * displayWidth, 0.25f * displayHeight}; + new float[] {0.75f * windowWidth, 0.25f * windowHeight}; final float[] secondFingerStartCoords = new float[] {centerX - 1.0f, centerY + 1.0f}; final float[] secondFingerEndCoords = - new float[] {0.25f * displayWidth, 0.75f * displayHeight}; + new float[] {0.25f * windowWidth, 0.75f * windowHeight}; onView(withId(R.id.article)).perform(new PinchZoomAction(firstFingerStartCoords, firstFingerEndCoords, secondFingerStartCoords, secondFingerEndCoords, diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java index 9f259a841319..d70572444128 100644 --- a/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java +++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java @@ -16,11 +16,13 @@ package android.view.inputmethod; +import static android.view.Display.DEFAULT_DISPLAY; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import android.content.Context; -import android.view.WindowManager; +import android.hardware.display.DisplayManager; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -43,9 +45,9 @@ public class InputMethodManagerTest { final Context testContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); - final WindowManager wm = testContext.getSystemService(WindowManager.class); + final DisplayManager dm = testContext.getSystemService(DisplayManager.class); final Context defaultDisplayContext = - testContext.createDisplayContext(wm.getDefaultDisplay()); + testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY)); final InputMethodManager imm = defaultDisplayContext.getSystemService(InputMethodManager.class); assertEquals("InputMethodManager.getInstance() always returns the instance for the default" diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java index ba85d765ceda..d5825e20163c 100644 --- a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java +++ b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java @@ -16,11 +16,9 @@ package android.view.menu; -import android.content.Context; -import android.graphics.Point; import android.test.ActivityInstrumentationTestCase; import android.util.PollingCheck; -import android.view.Display; +import android.util.Size; import android.view.View; import android.view.WindowManager; import android.widget.espresso.ContextMenuUtils; @@ -82,12 +80,9 @@ public class ContextMenuTest extends ActivityInstrumentationTestCase<ContextMenu * Returns the minimum of the default display's width and height. */ private int getMinScreenDimension() { - final WindowManager windowManager = (WindowManager) getActivity().getSystemService( - Context.WINDOW_SERVICE); - final Display display = windowManager.getDefaultDisplay(); - final Point displaySize = new Point(); - display.getRealSize(displaySize); - return Math.min(displaySize.x, displaySize.y); + final WindowManager windowManager = getActivity().getSystemService(WindowManager.class); + final Size maxWindowSize = windowManager.getMaximumWindowMetrics().getSize(); + return Math.min(maxWindowSize.getWidth(), maxWindowSize.getHeight()); } /** diff --git a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java index 73e4ea8f718d..8e90a824c873 100644 --- a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java +++ b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java @@ -17,7 +17,6 @@ package android.widget.focus; import android.app.Activity; -import android.graphics.Point; import android.os.Bundle; import android.util.InternalSelectionView; import android.view.View; @@ -112,9 +111,7 @@ public class ListOfInternalSelectionViews extends Activity { protected void onCreate(Bundle icicle) { super.onCreate(icicle); - Point size = new Point(); - getWindowManager().getDefaultDisplay().getSize(size); - mScreenHeight = size.y; + mScreenHeight = getWindowManager().getCurrentWindowMetrics().getSize().getHeight(); Bundle extras = getIntent().getExtras(); if (extras != null) { diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java index 0d3092cbc2f3..fd1dbfc63708 100644 --- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java +++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java @@ -106,9 +106,10 @@ public class GridTouchVerticalSpacingStackFromBottomTest extends ActivityInstrum int firstTop = firstChild.getTop(); + int windowHeight = mActivity.getWindowManager().getCurrentWindowMetrics().getSize() + .getHeight(); int distance = TouchUtils.dragViewBy(this, firstChild, - Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, - (int) (mActivity.getWindowManager().getDefaultDisplay().getHeight() * 0.75f)); + Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, (int) (windowHeight * 0.75f)); assertEquals("View scrolled to wrong position", firstTop + (distance - mViewConfig.getScaledTouchSlop() - 1), firstChild.getTop()); diff --git a/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java b/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java index 9e49719c6527..e6195b147045 100644 --- a/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java +++ b/core/tests/coretests/src/android/widget/listview/AdjacentListsWithAdjacentISVsInside.java @@ -65,7 +65,8 @@ public class AdjacentListsWithAdjacentISVsInside extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final int desiredHeight = (int) (0.8 * getWindowManager().getDefaultDisplay().getHeight()); + final int desiredHeight = + (int) (0.8 * getWindowManager().getCurrentWindowMetrics().getSize().getHeight()); mLeftListView = new ListView(this); mLeftListView.setAdapter(new AdjacentISVAdapter(desiredHeight)); diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index d4c362143bf0..df6b9066ea5c 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -64,7 +64,6 @@ import android.graphics.Paint; import android.graphics.drawable.Icon; import android.metrics.LogMaker; import android.net.Uri; -import android.os.Bundle; import android.os.UserHandle; import android.service.chooser.ChooserTarget; @@ -77,9 +76,6 @@ import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -482,8 +478,8 @@ public class ChooserActivityTest { .launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - onView(withId(R.id.copy_button)).check(matches(isDisplayed())); - onView(withId(R.id.copy_button)).perform(click()); + onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed())); + onView(withId(R.id.chooser_copy_button)).perform(click()); ClipboardManager clipboard = (ClipboardManager) activity.getSystemService( Context.CLIPBOARD_SERVICE); ClipData clipData = clipboard.getPrimaryClip(); @@ -510,8 +506,8 @@ public class ChooserActivityTest { .launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - onView(withId(R.id.copy_button)).check(matches(isDisplayed())); - onView(withId(R.id.copy_button)).perform(click()); + onView(withId(R.id.chooser_copy_button)).check(matches(isDisplayed())); + onView(withId(R.id.chooser_copy_button)).perform(click()); verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture()); // First is Activity shown, Second is "with preview" diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index 42f7736d37b0..911490f30799 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -27,12 +27,14 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.internal.app.MatcherUtils.first; import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo; +import static com.android.internal.app.ResolverDataProvider.createResolvedComponentInfoWithOtherId; import static com.android.internal.app.ResolverWrapperActivity.sOverrides; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import android.content.Intent; @@ -465,14 +467,33 @@ public class ResolverActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; List<ResolvedComponentInfo> personalResolvedComponentInfos = - createResolvedComponentsForTest(3); + createResolvedComponentsForTestWithOtherProfile(3); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); - when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + when(sOverrides.resolverListController.getResolversForIntentAsUser( Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos); + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + when(sOverrides.resolverListController.getResolversForIntentAsUser( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + Intent sendIntent = createSendImageIntent(); markWorkProfileUserAvailable(); @@ -502,9 +523,9 @@ public class ResolverActivityTest { final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); waitForIdle(); + onView(withText(R.string.resolver_work_tab)) .perform(click()); - waitForIdle(); assertThat(activity.getWorkListAdapter().getCount(), is(4)); } @@ -553,10 +574,35 @@ public class ResolverActivityTest { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); + List<ResolvedComponentInfo> personalResolvedComponentInfos = + createResolvedComponentsForTestWithOtherProfile(1); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); + + when(sOverrides.resolverListController.getResolversForIntentAsUser( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + when(sOverrides.resolverListController.getResolversForIntentAsUser( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), - Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos); + Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos)); + when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class), + eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos)); + Intent sendIntent = createSendImageIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); 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 cd706089929e..cdcf23fc10bb 100644 --- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java @@ -26,7 +26,6 @@ import android.platform.test.annotations.Presubmit; import android.view.Display; import android.view.DisplayAdjustments; import android.view.DisplayInfo; -import android.view.WindowManager; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -71,8 +70,7 @@ public final class DecorContextTest { private static void assertDecorContextDisplay(int expectedDisplayId, DecorContext decorContext) { - WindowManager wm = (WindowManager) decorContext.getSystemService(Context.WINDOW_SERVICE); - Display associatedDisplay = wm.getDefaultDisplay(); + Display associatedDisplay = decorContext.getDisplay(); assertEquals(expectedDisplayId, associatedDisplay.getDisplayId()); } } diff --git a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java index 6010f3962d68..4c3eaeb1730b 100644 --- a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java +++ b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java @@ -15,6 +15,7 @@ */ package com.android.internal.util; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -121,6 +122,7 @@ public class LocationPermissionCheckerTest { private void setupTestCase() throws Exception { setupMocks(); setupMockInterface(); + mChecker = new LocationPermissionChecker(mMockContext); } private void initTestVars() { @@ -136,7 +138,6 @@ public class LocationPermissionCheckerTest { mFineLocationPermission = PackageManager.PERMISSION_DENIED; mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; - mChecker = new LocationPermissionChecker(mMockContext); } private void setupMockInterface() { @@ -180,7 +181,11 @@ public class LocationPermissionCheckerTest { mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; mUid = mCurrentUser; setupTestCase(); - mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + + final int result = + mChecker.checkLocationPermissionWithDetailInfo( + TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + assertEquals(LocationPermissionChecker.SUCCEEDED, result); } @Test @@ -193,7 +198,11 @@ public class LocationPermissionCheckerTest { mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; setupTestCase(); - mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + + final int result = + mChecker.checkLocationPermissionWithDetailInfo( + TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + assertEquals(LocationPermissionChecker.SUCCEEDED, result); } @Test @@ -206,7 +215,7 @@ public class LocationPermissionCheckerTest { setupTestCase(); assertThrows(SecurityException.class, - () -> mChecker.enforceLocationPermission( + () -> mChecker.checkLocationPermissionWithDetailInfo( TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); } @@ -215,9 +224,11 @@ public class LocationPermissionCheckerTest { mThrowSecurityException = false; mIsLocationEnabled = true; setupTestCase(); - assertThrows(SecurityException.class, - () -> mChecker.enforceLocationPermission( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); + + final int result = + mChecker.checkLocationPermissionWithDetailInfo( + TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); } @Test @@ -230,9 +241,10 @@ public class LocationPermissionCheckerTest { mUid = MANAGED_PROFILE_UID; setupTestCase(); - assertThrows(SecurityException.class, - () -> mChecker.enforceLocationPermission( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); + final int result = + mChecker.checkLocationPermissionWithDetailInfo( + TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + assertEquals(LocationPermissionChecker.ERROR_LOCATION_PERMISSION_MISSING, result); verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString()); } @@ -246,9 +258,10 @@ public class LocationPermissionCheckerTest { setupTestCase(); - assertThrows(SecurityException.class, - () -> mChecker.enforceLocationPermission( - TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null)); + final int result = + mChecker.checkLocationPermissionWithDetailInfo( + TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null); + assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result); } private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { diff --git a/data/etc/car/com.android.car.secondaryhome.xml b/data/etc/car/com.android.car.secondaryhome.xml new file mode 100644 index 000000000000..c74b86ed8ae1 --- /dev/null +++ b/data/etc/car/com.android.car.secondaryhome.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 + --> +<permissions> + <privapp-permissions package="com.android.car.secondaryhome"> + <!-- Required to launch app in ActivityView --> + <permission name="android.permission.ACTIVITY_EMBEDDING"/> + <!-- Required to send notification to current user--> + <permission name="android.permission.MANAGE_USERS"/> + </privapp-permissions> +</permissions> diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml index 7296cfdfbec7..3d78eb9c59b7 100644 --- a/data/etc/framework-sysconfig.xml +++ b/data/etc/framework-sysconfig.xml @@ -19,11 +19,29 @@ <!-- Broadcast actions that are currently exempted from O+ background delivery restrictions. --> - <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" /> - <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" /> + <allow-implicit-broadcast action="android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED" /> + <allow-implicit-broadcast action="android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED" /> + <allow-implicit-broadcast action="android.intent.action.DATA_SMS_RECEIVED" /> <allow-implicit-broadcast action="android.intent.action.MEDIA_SCANNER_SCAN_FILE" /> - <allow-implicit-broadcast action="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION" /> + <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" /> + <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" /> <allow-implicit-broadcast action="android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION" /> + <allow-implicit-broadcast action="android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION" /> + <allow-implicit-broadcast action="android.provider.Telephony.SECRET_CODE" /> + <allow-implicit-broadcast action="android.provider.Telephony.SMS_CB_RECEIVED" /> + <allow-implicit-broadcast action="android.provider.Telephony.SMS_DELIVER" /> + <allow-implicit-broadcast action="android.provider.Telephony.SMS_RECEIVED" /> + <allow-implicit-broadcast action="android.provider.Telephony.SMS_REJECTED" /> + <allow-implicit-broadcast action="android.provider.Telephony.WAP_PUSH_DELIVER" /> + <allow-implicit-broadcast action="android.provider.Telephony.WAP_PUSH_RECEIVED" /> + <allow-implicit-broadcast action="android.telephony.action.CARRIER_CONFIG_CHANGED" /> + <allow-implicit-broadcast action="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" /> + <allow-implicit-broadcast action="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" /> + <allow-implicit-broadcast action="android.telephony.action.SECRET_CODE" /> + <allow-implicit-broadcast action="android.telephony.action.SIM_APPLICATION_STATE_CHANGED" /> + <allow-implicit-broadcast action="android.telephony.action.SIM_CARD_STATE_CHANGED" /> + <allow-implicit-broadcast action="android.telephony.action.SIM_SLOT_STATUS_CHANGED" /> + <!-- Whitelist of what components are permitted as backup data transports. The 'service' attribute here is a flattened ComponentName string. --> diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml index 39973715a47d..5c89da05a68c 100644 --- a/data/etc/hiddenapi-package-whitelist.xml +++ b/data/etc/hiddenapi-package-whitelist.xml @@ -53,10 +53,6 @@ Do NOT include any apps that are updatable via Play Store! <hidden-api-whitelisted-app package="com.android.providers.media" /> <hidden-api-whitelisted-app package="com.android.providers.tv" /> <hidden-api-whitelisted-app package="com.android.providers.userdictionary" /> - <!-- TODO (b/141954427): Remove networkstack --> - <hidden-api-whitelisted-app package="com.android.networkstack" /> - <!-- TODO (b/141954427): Remove wifistack --> - <hidden-api-whitelisted-app package="com.android.wifi" /> <hidden-api-whitelisted-app package="com.android.smspush" /> <hidden-api-whitelisted-app package="com.android.spare_parts" /> <hidden-api-whitelisted-app package="com.android.statementservice" /> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index aabd4125d0ed..816bb8789667 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -369,6 +369,8 @@ applications that come with the platform <permission name="android.permission.WRITE_DREAM_STATE" /> <!-- Permission required to test lights control APIs. --> <permission name="android.permission.CONTROL_DEVICE_LIGHTS" /> + <!-- Permission required for ShortcutManagerUsageTest CTS test. --> + <permission name="android.permission.ACCESS_SHORTCUTS"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 79589bf13853..91c5fbec888a 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -331,6 +331,12 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, + "-1410260105": { + "message": "Schedule IME show for %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "-1391944764": { "message": "SURFACE DESTROY: %s. %s", "level": "INFO", @@ -733,12 +739,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DisplayRotation.java" }, - "-554834595": { - "message": "Display id=%d is frozen, return %d", - "level": "VERBOSE", - "group": "WM_DEBUG_ORIENTATION", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "-549028919": { "message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", "level": "INFO", @@ -1063,6 +1063,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowSurfaceController.java" }, + "140319294": { + "message": "IME target changed within ActivityRecord", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "146871307": { "message": "Tried to remove starting window but startingWindow was null: %s", "level": "VERBOSE", @@ -1267,6 +1273,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "438102669": { + "message": "call showInsets(ime) on %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "457951957": { "message": "\tNot visible=%s", "level": "DEBUG", @@ -1387,6 +1399,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "632168013": { + "message": "dcTarget: %s mImeTargetFromIme: %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "633654009": { "message": "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", "level": "INFO", @@ -1693,6 +1711,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "1373000889": { + "message": "abortShowImePostLayout", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "1401700824": { "message": "Window drawn win=%s", "level": "DEBUG", @@ -1987,6 +2011,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/WindowState.java" }, + "1928325128": { + "message": "Run showImeRunner", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "1947239194": { "message": "Deferring rotation, still finishing previous rotation", "level": "VERBOSE", @@ -2139,6 +2169,9 @@ "WM_DEBUG_FOCUS_LIGHT": { "tag": "WindowManager" }, + "WM_DEBUG_IME": { + "tag": "WindowManager" + }, "WM_DEBUG_KEEP_SCREEN_ON": { "tag": "WindowManager" }, diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 7c0efe16838e..58cc08bc2d73 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -479,6 +479,14 @@ bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* str bool Bitmap::compress(const SkBitmap& bitmap, JavaCompressFormat format, int32_t quality, SkWStream* stream) { + if (bitmap.colorType() == kAlpha_8_SkColorType) { + // None of the JavaCompressFormats have a sensible way to compress an + // ALPHA_8 Bitmap. SkPngEncoder will compress one, but it uses a non- + // standard format that most decoders do not understand, so this is + // likely not useful. + return false; + } + SkEncodedImageFormat fm; switch (format) { case JavaCompressFormat::Jpeg: diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 79bec920c10e..6a5c0ec9457a 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -69,8 +69,6 @@ interface ILocationManager double upperRightLatitude, double upperRightLongitude, int maxResults, in GeocoderParams params, out List<Address> addrs); - boolean sendNiResponse(int notifId, int userResponse); - boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, String packageName, String featureId, String listenerIdentifier); void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0c5fe787bbbc..197787e5b6e6 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -2397,21 +2397,6 @@ public class LocationManager { } } - /** - * Used by NetInitiatedActivity to report user response - * for network initiated GPS fix requests. - * - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public boolean sendNiResponse(int notifId, int userResponse) { - try { - return mService.sendNiResponse(notifId, userResponse); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - private void checkPendingIntent(PendingIntent pendingIntent) { Preconditions.checkArgument(pendingIntent != null, "invalid null pending intent"); if (!pendingIntent.isTargetedToPackage()) { diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java index 44d9d2372665..69162bab3167 100644 --- a/location/java/android/location/LocationManagerInternal.java +++ b/location/java/android/location/LocationManagerInternal.java @@ -41,4 +41,19 @@ public abstract class LocationManagerInternal { * @throws IllegalArgumentException if provider is null */ public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed); + + /** + * Returns true if the given package belongs to a location provider, and so should be afforded + * some special privileges. + * + * @param packageName The package name to check + * @return True is the given package belongs to a location provider, false otherwise + */ + public abstract boolean isProviderPackage(@NonNull String packageName); + + /** + * Should only be used by GNSS code. + */ + // TODO: there is no reason for this to exist as part of any API. move all the logic into gnss + public abstract void sendNiResponse(int notifId, int userResponse); } diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java index 074188e01000..adf4d3dcfa09 100644 --- a/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java +++ b/media/java/android/media/audiopolicy/AudioVolumeGroupChangeHandler.java @@ -157,9 +157,7 @@ public class AudioVolumeGroupChangeHandler { Handler handler = eventHandler.handler(); if (handler != null) { Message m = handler.obtainMessage(what, arg1, arg2, obj); - if (what != AUDIOVOLUMEGROUP_EVENT_NEW_LISTENER) { - handler.removeMessages(what); - } + // Do not remove previous messages, as we would lose notification of group changes handler.sendMessage(m); } } diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index aece39d78694..5ef466dfd0e9 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -932,7 +932,7 @@ public final class MediaSessionManager { } /** - * Listener to receive when the media session service + * Listener to be called when the media session service dispatches a media key event. * @hide */ @SystemApi @@ -944,15 +944,15 @@ public final class MediaSessionManager { * is released. * * @param event Dispatched media key event. - * @param packageName Package + * @param packageName The package name * @param sessionToken The media session's token. Can be {@code null}. */ - default void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName, - @Nullable MediaSession.Token sessionToken) { } + void onMediaKeyEventDispatched(@NonNull KeyEvent event, @NonNull String packageName, + @Nullable MediaSession.Token sessionToken); } /** - * Listener to receive changes in the media key event session, which would receive the media key + * Listener to receive changes in the media key event session, which would receive a media key * event unless specified. * @hide */ @@ -964,13 +964,14 @@ public final class MediaSessionManager { * has specified the target. * <p> * The session token can be {@link null} if the media button session is unset. In that case, - * framework would dispatch to the last sessions's media button receiver. + * framework would dispatch to the last sessions's media button receiver. If the media + * button receive isn't set as well, then it * * @param packageName The package name who would receive the media key event. Can be empty. - * @param sessionToken The media session's token. Can be {@code null.} + * @param sessionToken The media session's token. Can be {@code null}. */ - default void onMediaKeyEventSessionChanged(@NonNull String packageName, - @Nullable MediaSession.Token sessionToken) { } + void onMediaKeyEventSessionChanged(@NonNull String packageName, + @Nullable MediaSession.Token sessionToken); } /** diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index f3c071a06eba..a828e2d04347 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -722,6 +722,7 @@ public class MtpDatabase implements AutoCloseable { return MtpConstants.RESPONSE_OK; case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE: // use screen size as max image size + // TODO(b/147721765): Add support for foldables/multi-display devices. Display display = ((WindowManager) mContext.getSystemService( Context.WINDOW_SERVICE)).getDefaultDisplay(); int width = display.getMaximumSizeDimension(); diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java index 0ae640dd7910..25220951dd7b 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java @@ -58,7 +58,6 @@ import android.os.Handler; import android.util.Log; import android.util.Pair; import android.util.Size; -import android.view.Display; import android.view.Surface; import android.view.WindowManager; @@ -2211,14 +2210,14 @@ public class CameraTestUtils extends Assert { } public static Size getPreviewSizeBound(WindowManager windowManager, Size bound) { - Display display = windowManager.getDefaultDisplay(); + Size windowSize = windowManager.getCurrentWindowMetrics().getSize(); - int width = display.getWidth(); - int height = display.getHeight(); + int width = windowSize.getWidth(); + int height = windowSize.getHeight(); if (height > width) { height = width; - width = display.getHeight(); + width = windowSize.getHeight(); } if (bound.getWidth() <= width && diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRoute2InfoTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRoute2InfoTest.java deleted file mode 100644 index c46966fdc6d8..000000000000 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRoute2InfoTest.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 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.mediaroutertest; - - -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; -import static org.testng.Assert.assertThrows; - -import android.media.MediaRoute2Info; -import android.net.Uri; -import android.os.Bundle; -import android.os.Parcel; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.List; - -/** - * Tests {@link MediaRoute2Info} and its {@link MediaRoute2Info.Builder builder}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class MediaRoute2InfoTest { - - public static final String TEST_ID = "test_id"; - public static final String TEST_NAME = "test_name"; - public static final String TEST_ROUTE_TYPE_0 = "test_route_type_0"; - public static final String TEST_ROUTE_TYPE_1 = "test_route_type_1"; - public static final int TEST_DEVICE_TYPE = MediaRoute2Info.DEVICE_TYPE_REMOTE_SPEAKER; - public static final Uri TEST_ICON_URI = Uri.parse("https://developer.android.com"); - public static final String TEST_DESCRIPTION = "test_description"; - public static final int TEST_CONNECTION_STATE = MediaRoute2Info.CONNECTION_STATE_CONNECTING; - public static final String TEST_CLIENT_PACKAGE_NAME = "com.test.client.package.name"; - public static final int TEST_VOLUME_HANDLING = MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE; - public static final int TEST_VOLUME_MAX = 100; - public static final int TEST_VOLUME = 65; - - public static final String TEST_KEY = "test_key"; - public static final String TEST_VALUE = "test_value"; - - @Test - public void testBuilderConstructorWithInvalidValues() { - final String nullId = null; - final String nullName = null; - final String emptyId = ""; - final String emptyName = ""; - final String validId = "valid_id"; - final String validName = "valid_name"; - - // ID is invalid - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(nullId, validName)); - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(emptyId, validName)); - - // name is invalid - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(validId, nullName)); - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(validId, emptyName)); - - // Both are invalid - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(nullId, nullName)); - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(nullId, emptyName)); - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(emptyId, nullName)); - assertThrows(IllegalArgumentException.class, - () -> new MediaRoute2Info.Builder(emptyId, emptyName)); - - - // Null RouteInfo (1-argument constructor) - final MediaRoute2Info nullRouteInfo = null; - assertThrows(NullPointerException.class, - () -> new MediaRoute2Info.Builder(nullRouteInfo)); - } - - @Test - public void testBuilderBuildWithEmptyRouteTypesShouldThrowIAE() { - MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME); - assertThrows(IllegalArgumentException.class, () -> builder.build()); - } - - @Test - public void testBuilderAndGettersOfMediaRoute2Info() { - Bundle extras = new Bundle(); - extras.putString(TEST_KEY, TEST_VALUE); - - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - assertEquals(TEST_ID, routeInfo.getId()); - assertEquals(TEST_NAME, routeInfo.getName()); - - assertEquals(2, routeInfo.getFeatures().size()); - assertEquals(TEST_ROUTE_TYPE_0, routeInfo.getFeatures().get(0)); - assertEquals(TEST_ROUTE_TYPE_1, routeInfo.getFeatures().get(1)); - - assertEquals(TEST_DEVICE_TYPE, routeInfo.getDeviceType()); - assertEquals(TEST_ICON_URI, routeInfo.getIconUri()); - assertEquals(TEST_DESCRIPTION, routeInfo.getDescription()); - assertEquals(TEST_CONNECTION_STATE, routeInfo.getConnectionState()); - assertEquals(TEST_CLIENT_PACKAGE_NAME, routeInfo.getClientPackageName()); - assertEquals(TEST_VOLUME_HANDLING, routeInfo.getVolumeHandling()); - assertEquals(TEST_VOLUME_MAX, routeInfo.getVolumeMax()); - assertEquals(TEST_VOLUME, routeInfo.getVolume()); - - Bundle extrasOut = routeInfo.getExtras(); - assertNotNull(extrasOut); - assertTrue(extrasOut.containsKey(TEST_KEY)); - assertEquals(TEST_VALUE, extrasOut.getString(TEST_KEY)); - } - - @Test - public void testBuilderSetExtrasWithNull() { - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .setExtras(null) - .build(); - - assertNull(routeInfo.getExtras()); - } - - @Test - public void testBuilderaddFeatures() { - List<String> routeTypes = new ArrayList<>(); - routeTypes.add(TEST_ROUTE_TYPE_0); - routeTypes.add(TEST_ROUTE_TYPE_1); - - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeatures(routeTypes) - .build(); - - assertEquals(routeTypes, routeInfo.getFeatures()); - } - - @Test - public void testBuilderclearFeatures() { - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - // clearFeatures should clear the route types. - .clearFeatures() - .addFeature(TEST_ROUTE_TYPE_1) - .build(); - - assertEquals(1, routeInfo.getFeatures().size()); - assertEquals(TEST_ROUTE_TYPE_1, routeInfo.getFeatures().get(0)); - } - - @Test - public void testhasAnyFeaturesReturnsFalse() { - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .build(); - - List<String> testRouteTypes = new ArrayList<>(); - testRouteTypes.add("non_matching_route_type_1"); - testRouteTypes.add("non_matching_route_type_2"); - testRouteTypes.add("non_matching_route_type_3"); - testRouteTypes.add("non_matching_route_type_4"); - - assertFalse(routeInfo.hasAnyFeatures(testRouteTypes)); - } - - @Test - public void testhasAnyFeaturesReturnsTrue() { - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .build(); - - List<String> testRouteTypes = new ArrayList<>(); - testRouteTypes.add("non_matching_route_type_1"); - testRouteTypes.add("non_matching_route_type_2"); - testRouteTypes.add("non_matching_route_type_3"); - testRouteTypes.add(TEST_ROUTE_TYPE_1); - - assertTrue(routeInfo.hasAnyFeatures(testRouteTypes)); - } - - @Test - public void testEqualsCreatedWithSameArguments() { - Bundle extras = new Bundle(); - extras.putString(TEST_KEY, TEST_VALUE); - - MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - MediaRoute2Info routeInfo2 = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - assertEquals(routeInfo1, routeInfo2); - assertEquals(routeInfo1.hashCode(), routeInfo2.hashCode()); - } - - @Test - public void testEqualsCreatedWithBuilderCopyConstructor() { - Bundle extras = new Bundle(); - extras.putString(TEST_KEY, TEST_VALUE); - - MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - MediaRoute2Info routeInfo2 = new MediaRoute2Info.Builder(routeInfo1).build(); - - assertEquals(routeInfo1, routeInfo2); - assertEquals(routeInfo1.hashCode(), routeInfo2.hashCode()); - } - - @Test - public void testEqualsReturnFalse() { - Bundle extras = new Bundle(); - extras.putString(TEST_KEY, TEST_VALUE); - - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - // Now, we will use copy constructor - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .addFeature("randomRouteType") - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setDeviceType(TEST_DEVICE_TYPE + 1) - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setIconUri(Uri.parse("randomUri")) - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setDescription("randomDescription") - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setConnectionState(TEST_CONNECTION_STATE + 1) - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setClientPackageName("randomPackageName") - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setVolumeHandling(TEST_VOLUME_HANDLING + 1) - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setVolumeMax(TEST_VOLUME_MAX + 100) - .build()); - assertNotEquals(routeInfo, new MediaRoute2Info.Builder(routeInfo) - .setVolume(TEST_VOLUME + 10) - .build()); - // Note: Extras will not affect the equals. - } - - @Test - public void testParcelingAndUnParceling() { - Bundle extras = new Bundle(); - extras.putString(TEST_KEY, TEST_VALUE); - - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder(TEST_ID, TEST_NAME) - .addFeature(TEST_ROUTE_TYPE_0) - .addFeature(TEST_ROUTE_TYPE_1) - .setDeviceType(TEST_DEVICE_TYPE) - .setIconUri(TEST_ICON_URI) - .setDescription(TEST_DESCRIPTION) - .setConnectionState(TEST_CONNECTION_STATE) - .setClientPackageName(TEST_CLIENT_PACKAGE_NAME) - .setVolumeHandling(TEST_VOLUME_HANDLING) - .setVolumeMax(TEST_VOLUME_MAX) - .setVolume(TEST_VOLUME) - .setExtras(extras) - .build(); - - Parcel parcel = Parcel.obtain(); - routeInfo.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - MediaRoute2Info routeInfoFromParcel = MediaRoute2Info.CREATOR.createFromParcel(parcel); - assertEquals(routeInfo, routeInfoFromParcel); - assertEquals(routeInfo.hashCode(), routeInfoFromParcel.hashCode()); - - // Check extras - Bundle extrasOut = routeInfoFromParcel.getExtras(); - assertNotNull(extrasOut); - assertTrue(extrasOut.containsKey(TEST_KEY)); - assertEquals(TEST_VALUE, extrasOut.getString(TEST_KEY)); - } -} diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java deleted file mode 100644 index e0b454559456..000000000000 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2Test.java +++ /dev/null @@ -1,780 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.mediaroutertest; - -import static android.media.MediaRoute2Info.CONNECTION_STATE_CONNECTING; -import static android.media.MediaRoute2Info.DEVICE_TYPE_REMOTE_SPEAKER; -import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE; - -import static com.android.mediaroutertest.MediaRouterManagerTest.FEATURES_ALL; -import static com.android.mediaroutertest.MediaRouterManagerTest.FEATURES_SPECIAL; -import static com.android.mediaroutertest.MediaRouterManagerTest.FEATURE_SAMPLE; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID1; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID2; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID3_SESSION_CREATION_FAILED; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID4_TO_SELECT_AND_DESELECT; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID5_TO_TRANSFER_TO; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_SPECIAL_FEATURE; -import static com.android.mediaroutertest.MediaRouterManagerTest.ROUTE_ID_VARIABLE_VOLUME; -import static com.android.mediaroutertest.MediaRouterManagerTest.SYSTEM_PROVIDER_ID; - -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.assertSame; -import static org.junit.Assert.assertTrue; -import static org.testng.Assert.assertThrows; - -import android.annotation.NonNull; -import android.content.Context; -import android.media.MediaRoute2Info; -import android.media.MediaRouter2; -import android.media.MediaRouter2.OnGetControllerHintsListener; -import android.media.MediaRouter2.RouteCallback; -import android.media.MediaRouter2.RoutingController; -import android.media.MediaRouter2.RoutingControllerCallback; -import android.media.RouteDiscoveryPreference; -import android.net.Uri; -import android.os.Bundle; -import android.os.Parcel; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class MediaRouter2Test { - private static final String TAG = "MediaRouter2Test"; - Context mContext; - private MediaRouter2 mRouter2; - private Executor mExecutor; - - private static final int TIMEOUT_MS = 5000; - - private static final String TEST_KEY = "test_key"; - private static final String TEST_VALUE = "test_value"; - - @Before - public void setUp() throws Exception { - mContext = InstrumentationRegistry.getTargetContext(); - mRouter2 = MediaRouter2.getInstance(mContext); - mExecutor = Executors.newSingleThreadExecutor(); - } - - @After - public void tearDown() throws Exception { - } - - /** - * Tests if we get proper routes for application that has special route type. - */ - @Test - public void testGetRoutes() throws Exception { - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(FEATURES_SPECIAL); - - assertEquals(1, routes.size()); - assertNotNull(routes.get(ROUTE_ID_SPECIAL_FEATURE)); - } - - @Test - public void testRouteInfoEquality() { - MediaRoute2Info routeInfo = new MediaRoute2Info.Builder("id", "name") - .setDescription("description") - .setClientPackageName("com.android.mediaroutertest") - .setConnectionState(CONNECTION_STATE_CONNECTING) - .setIconUri(new Uri.Builder().path("icon").build()) - .setVolume(5) - .setVolumeMax(20) - .addFeature(FEATURE_SAMPLE) - .setVolumeHandling(PLAYBACK_VOLUME_VARIABLE) - .setDeviceType(DEVICE_TYPE_REMOTE_SPEAKER) - .build(); - - MediaRoute2Info routeInfoRebuilt = new MediaRoute2Info.Builder(routeInfo).build(); - assertEquals(routeInfo, routeInfoRebuilt); - - Parcel parcel = Parcel.obtain(); - parcel.writeParcelable(routeInfo, 0); - parcel.setDataPosition(0); - MediaRoute2Info routeInfoFromParcel = parcel.readParcelable(null); - - assertEquals(routeInfo, routeInfoFromParcel); - } - - @Test - public void testControlVolumeWithRouter() throws Exception { - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(FEATURES_ALL); - - MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME); - assertNotNull(volRoute); - - int originalVolume = volRoute.getVolume(); - int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1); - - awaitOnRouteChanged( - () -> mRouter2.requestUpdateVolume(volRoute, deltaVolume), - ROUTE_ID_VARIABLE_VOLUME, - (route -> route.getVolume() == originalVolume + deltaVolume), - FEATURES_ALL); - - awaitOnRouteChanged( - () -> mRouter2.requestSetVolume(volRoute, originalVolume), - ROUTE_ID_VARIABLE_VOLUME, - (route -> route.getVolume() == originalVolume), - FEATURES_ALL); - } - - @Test - public void testRegisterControllerCallbackWithInvalidArguments() { - Executor executor = mExecutor; - RoutingControllerCallback callback = new RoutingControllerCallback(); - - // Tests null executor - assertThrows(NullPointerException.class, - () -> mRouter2.registerControllerCallback(null, callback)); - - // Tests null callback - assertThrows(NullPointerException.class, - () -> mRouter2.registerControllerCallback(executor, null)); - } - - @Test - public void testUnregisterControllerCallbackWithNullCallback() { - // Tests null callback - assertThrows(NullPointerException.class, - () -> mRouter2.unregisterControllerCallback(null)); - } - - @Test - public void testRequestCreateControllerWithNullRoute() { - assertThrows(NullPointerException.class, - () -> mRouter2.requestCreateController(null)); - } - - @Test - public void testRequestCreateControllerSuccess() throws Exception { - final List<String> sampleRouteFeature = new ArrayList<>(); - sampleRouteFeature.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteFeature); - MediaRoute2Info route = routes.get(ROUTE_ID1); - assertNotNull(route); - - final CountDownLatch successLatch = new CountDownLatch(1); - final CountDownLatch failureLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with this route - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - assertNotNull(controller); - assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)); - controllers.add(controller); - successLatch.countDown(); - } - - @Override - public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { - failureLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(route); - assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // onSessionCreationFailed should not be called. - assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - @Test - public void testRequestCreateControllerFailure() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info route = routes.get(ROUTE_ID3_SESSION_CREATION_FAILED); - assertNotNull(route); - - final CountDownLatch successLatch = new CountDownLatch(1); - final CountDownLatch failureLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with this route - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - controllers.add(controller); - successLatch.countDown(); - } - - @Override - public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { - assertEquals(route, requestedRoute); - failureLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(route); - assertTrue(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // onSessionCreated should not be called. - assertFalse(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - @Test - public void testRequestCreateControllerMultipleSessions() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - final CountDownLatch successLatch = new CountDownLatch(2); - final CountDownLatch failureLatch = new CountDownLatch(1); - final List<RoutingController> createdControllers = new ArrayList<>(); - - // Create session with this route - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - createdControllers.add(controller); - successLatch.countDown(); - } - - @Override - public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { - failureLatch.countDown(); - } - }; - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info route1 = routes.get(ROUTE_ID1); - MediaRoute2Info route2 = routes.get(ROUTE_ID2); - assertNotNull(route1); - assertNotNull(route2); - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(route1); - mRouter2.requestCreateController(route2); - assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // onSessionCreationFailed should not be called. - assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // Created controllers should have proper info - assertEquals(2, createdControllers.size()); - RoutingController controller1 = createdControllers.get(0); - RoutingController controller2 = createdControllers.get(1); - - assertNotEquals(controller1.getId(), controller2.getId()); - assertTrue(createRouteMap(controller1.getSelectedRoutes()).containsKey(ROUTE_ID1)); - assertTrue(createRouteMap(controller2.getSelectedRoutes()).containsKey(ROUTE_ID2)); - - } finally { - releaseControllers(createdControllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - @Test - public void testSetOnGetControllerHintsListener() throws Exception { - final List<String> sampleRouteFeature = new ArrayList<>(); - sampleRouteFeature.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteFeature); - MediaRoute2Info route = routes.get(ROUTE_ID1); - assertNotNull(route); - - final Bundle createSessionHints = new Bundle(); - createSessionHints.putString(TEST_KEY, TEST_VALUE); - final OnGetControllerHintsListener listener = new OnGetControllerHintsListener() { - @Override - public Bundle onGetControllerHints(MediaRoute2Info route) { - return createSessionHints; - } - }; - - final CountDownLatch successLatch = new CountDownLatch(1); - final CountDownLatch failureLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with this route - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - assertNotNull(controller); - assertTrue(createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)); - - // The SampleMediaRoute2ProviderService supposed to set control hints - // with the given creationSessionHints. - Bundle controlHints = controller.getControlHints(); - assertNotNull(controlHints); - assertTrue(controlHints.containsKey(TEST_KEY)); - assertEquals(TEST_VALUE, controlHints.getString(TEST_KEY)); - - controllers.add(controller); - successLatch.countDown(); - } - - @Override - public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { - failureLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - - // The SampleMediaRoute2ProviderService supposed to set control hints - // with the given creationSessionHints. - mRouter2.setOnGetControllerHintsListener(listener); - mRouter2.requestCreateController(route); - assertTrue(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // onSessionCreationFailed should not be called. - assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - @Test - public void testRoutingControllerCallbackIsNotCalledAfterUnregistered() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info route = routes.get(ROUTE_ID1); - assertNotNull(route); - - final CountDownLatch successLatch = new CountDownLatch(1); - final CountDownLatch failureLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with this route - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - controllers.add(controller); - successLatch.countDown(); - } - - @Override - public void onControllerCreationFailed(MediaRoute2Info requestedRoute) { - failureLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(route); - - // Unregisters session callback - mRouter2.unregisterControllerCallback(controllerCallback); - - // No session callback methods should be called. - assertFalse(successLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - assertFalse(failureLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - // TODO: Add tests for illegal inputs if needed (e.g. selecting already selected route) - @Test - public void testRoutingControllerSelectAndDeselectRoute() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); - assertNotNull(routeToCreateSessionWith); - - final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); - final CountDownLatch onControllerUpdatedLatchForSelect = new CountDownLatch(1); - final CountDownLatch onControllerUpdatedLatchForDeselect = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with ROUTE_ID1 - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - assertNotNull(controller); - assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); - controllers.add(controller); - onControllerCreatedLatch.countDown(); - } - - @Override - public void onControllerUpdated(RoutingController controller) { - if (onControllerCreatedLatch.getCount() != 0 - || !TextUtils.equals( - controllers.get(0).getId(), controller.getId())) { - return; - } - - if (onControllerUpdatedLatchForSelect.getCount() != 0) { - assertEquals(2, controller.getSelectedRoutes().size()); - assertTrue(getRouteIds(controller.getSelectedRoutes()) - .contains(ROUTE_ID1)); - assertTrue(getRouteIds(controller.getSelectedRoutes()) - .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); - assertFalse(getRouteIds(controller.getSelectableRoutes()) - .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - onControllerUpdatedLatchForSelect.countDown(); - } else { - assertEquals(1, controller.getSelectedRoutes().size()); - assertTrue(getRouteIds(controller.getSelectedRoutes()) - .contains(ROUTE_ID1)); - assertFalse(getRouteIds(controller.getSelectedRoutes()) - .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); - assertTrue(getRouteIds(controller.getSelectableRoutes()) - .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - onControllerUpdatedLatchForDeselect.countDown(); - } - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(routeToCreateSessionWith); - assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - assertEquals(1, controllers.size()); - RoutingController controller = controllers.get(0); - assertTrue(getRouteIds(controller.getSelectableRoutes()) - .contains(ROUTE_ID4_TO_SELECT_AND_DESELECT)); - - // Select ROUTE_ID4_TO_SELECT_AND_DESELECT - MediaRoute2Info routeToSelectAndDeselect = routes.get( - ROUTE_ID4_TO_SELECT_AND_DESELECT); - assertNotNull(routeToSelectAndDeselect); - - controller.selectRoute(routeToSelectAndDeselect); - assertTrue(onControllerUpdatedLatchForSelect.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - controller.deselectRoute(routeToSelectAndDeselect); - assertTrue(onControllerUpdatedLatchForDeselect.await( - TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - @Test - public void testRoutingControllerTransferToRoute() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); - assertNotNull(routeToCreateSessionWith); - - final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); - final CountDownLatch onControllerUpdatedLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with ROUTE_ID1 - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - assertNotNull(controller); - assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); - controllers.add(controller); - onControllerCreatedLatch.countDown(); - } - - @Override - public void onControllerUpdated(RoutingController controller) { - if (onControllerCreatedLatch.getCount() != 0 - || !TextUtils.equals( - controllers.get(0).getId(), controller.getId())) { - return; - } - assertEquals(1, controller.getSelectedRoutes().size()); - assertFalse(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); - assertTrue(getRouteIds(controller.getSelectedRoutes()) - .contains(ROUTE_ID5_TO_TRANSFER_TO)); - assertFalse(getRouteIds(controller.getTransferrableRoutes()) - .contains(ROUTE_ID5_TO_TRANSFER_TO)); - - onControllerUpdatedLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(routeToCreateSessionWith); - assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - assertEquals(1, controllers.size()); - RoutingController controller = controllers.get(0); - assertTrue(getRouteIds(controller.getTransferrableRoutes()) - .contains(ROUTE_ID5_TO_TRANSFER_TO)); - - // Transfer to ROUTE_ID5_TO_TRANSFER_TO - MediaRoute2Info routeToTransferTo = routes.get(ROUTE_ID5_TO_TRANSFER_TO); - assertNotNull(routeToTransferTo); - - controller.transferToRoute(routeToTransferTo); - assertTrue(onControllerUpdatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - // TODO: Add tests for onSessionReleased() when provider releases the session. - - @Test - public void testRoutingControllerRelease() throws Exception { - final List<String> sampleRouteType = new ArrayList<>(); - sampleRouteType.add(FEATURE_SAMPLE); - - Map<String, MediaRoute2Info> routes = waitAndGetRoutes(sampleRouteType); - MediaRoute2Info routeToCreateSessionWith = routes.get(ROUTE_ID1); - assertNotNull(routeToCreateSessionWith); - - final CountDownLatch onControllerCreatedLatch = new CountDownLatch(1); - final CountDownLatch onControllerUpdatedLatch = new CountDownLatch(1); - final CountDownLatch onControllerReleasedLatch = new CountDownLatch(1); - final List<RoutingController> controllers = new ArrayList<>(); - - // Create session with ROUTE_ID1 - RoutingControllerCallback controllerCallback = new RoutingControllerCallback() { - @Override - public void onControllerCreated(RoutingController controller) { - assertNotNull(controller); - assertTrue(getRouteIds(controller.getSelectedRoutes()).contains(ROUTE_ID1)); - controllers.add(controller); - onControllerCreatedLatch.countDown(); - } - - @Override - public void onControllerUpdated(RoutingController controller) { - if (onControllerCreatedLatch.getCount() != 0 - || !TextUtils.equals(controllers.get(0).getId(), controller.getId())) { - return; - } - onControllerUpdatedLatch.countDown(); - } - - @Override - public void onControllerReleased(RoutingController controller) { - if (onControllerCreatedLatch.getCount() != 0 - || !TextUtils.equals(controllers.get(0).getId(), controller.getId())) { - return; - } - onControllerReleasedLatch.countDown(); - } - }; - - // TODO: Remove this once the MediaRouter2 becomes always connected to the service. - RouteCallback routeCallback = new RouteCallback(); - mRouter2.registerRouteCallback(mExecutor, routeCallback, RouteDiscoveryPreference.EMPTY); - - try { - mRouter2.registerControllerCallback(mExecutor, controllerCallback); - mRouter2.requestCreateController(routeToCreateSessionWith); - assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - assertEquals(1, controllers.size()); - RoutingController controller = controllers.get(0); - assertTrue(getRouteIds(controller.getTransferrableRoutes()) - .contains(ROUTE_ID5_TO_TRANSFER_TO)); - - // Release controller. Future calls should be ignored. - controller.release(); - - // Transfer to ROUTE_ID5_TO_TRANSFER_TO - MediaRoute2Info routeToTransferTo = routes.get(ROUTE_ID5_TO_TRANSFER_TO); - assertNotNull(routeToTransferTo); - - // This call should be ignored. - // The onSessionInfoChanged() shouldn't be called. - controller.transferToRoute(routeToTransferTo); - assertFalse(onControllerUpdatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - - // onControllerReleased should be called. - assertTrue(onControllerReleasedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - releaseControllers(controllers); - mRouter2.unregisterRouteCallback(routeCallback); - mRouter2.unregisterControllerCallback(controllerCallback); - } - } - - // TODO: Consider adding tests with bluetooth connection/disconnection. - @Test - public void testGetSystemController() { - final RoutingController systemController = mRouter2.getSystemController(); - assertNotNull(systemController); - assertFalse(systemController.isReleased()); - } - - @Test - public void testControllers() { - List<RoutingController> controllers = mRouter2.getControllers(); - assertNotNull(controllers); - assertFalse(controllers.isEmpty()); - assertSame(mRouter2.getSystemController(), controllers.get(0)); - } - - // Helper for getting routes easily - static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) { - Map<String, MediaRoute2Info> routeMap = new HashMap<>(); - for (MediaRoute2Info route : routes) { - routeMap.put(route.getId(), route); - } - return routeMap; - } - - Map<String, MediaRoute2Info> waitAndGetRoutes(List<String> routeTypes) - throws Exception { - CountDownLatch latch = new CountDownLatch(1); - - // A dummy callback is required to send route type info. - RouteCallback routeCallback = new RouteCallback() { - @Override - public void onRoutesAdded(List<MediaRoute2Info> routes) { - for (int i = 0; i < routes.size(); i++) { - //TODO: use isSystem() or similar method when it's ready - if (!TextUtils.equals(routes.get(i).getProviderId(), SYSTEM_PROVIDER_ID)) { - latch.countDown(); - } - } - } - }; - - mRouter2.registerRouteCallback(mExecutor, routeCallback, - new RouteDiscoveryPreference.Builder(routeTypes, true).build()); - try { - latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); - return createRouteMap(mRouter2.getRoutes()); - } finally { - mRouter2.unregisterRouteCallback(routeCallback); - } - } - - static void releaseControllers(@NonNull List<RoutingController> controllers) { - for (RoutingController controller : controllers) { - controller.release(); - } - } - - /** - * Returns a list of IDs of the given route list. - */ - List<String> getRouteIds(@NonNull List<MediaRoute2Info> routes) { - List<String> result = new ArrayList<>(); - for (MediaRoute2Info route : routes) { - result.add(route.getId()); - } - return result; - } - - void awaitOnRouteChanged(Runnable task, String routeId, - Predicate<MediaRoute2Info> predicate, - List<String> routeTypes) throws Exception { - CountDownLatch latch = new CountDownLatch(1); - RouteCallback routeCallback = new RouteCallback() { - @Override - public void onRoutesChanged(List<MediaRoute2Info> changed) { - MediaRoute2Info route = createRouteMap(changed).get(routeId); - if (route != null && predicate.test(route)) { - latch.countDown(); - } - } - }; - mRouter2.registerRouteCallback(mExecutor, routeCallback, - new RouteDiscoveryPreference.Builder(routeTypes, true).build()); - try { - task.run(); - assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); - } finally { - mRouter2.unregisterRouteCallback(routeCallback); - } - } -} diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryPreferenceTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryPreferenceTest.java deleted file mode 100644 index fa129350ed8b..000000000000 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/RouteDiscoveryPreferenceTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 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.mediaroutertest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import android.media.RouteDiscoveryPreference; -import android.os.Parcel; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class RouteDiscoveryPreferenceTest { - @Before - public void setUp() throws Exception { } - - @After - public void tearDown() throws Exception { } - - @Test - public void testEquality() { - List<String> testTypes = new ArrayList<>(); - testTypes.add("TEST_TYPE_1"); - testTypes.add("TEST_TYPE_2"); - RouteDiscoveryPreference request = new RouteDiscoveryPreference.Builder(testTypes, true) - .build(); - - RouteDiscoveryPreference requestRebuilt = new RouteDiscoveryPreference.Builder(request) - .build(); - - assertEquals(request, requestRebuilt); - - Parcel parcel = Parcel.obtain(); - parcel.writeParcelable(request, 0); - parcel.setDataPosition(0); - RouteDiscoveryPreference requestFromParcel = parcel.readParcelable(null); - - assertEquals(request, requestFromParcel); - } - - @Test - public void testInequality() { - List<String> testTypes = new ArrayList<>(); - testTypes.add("TEST_TYPE_1"); - testTypes.add("TEST_TYPE_2"); - - List<String> testTypes2 = new ArrayList<>(); - testTypes.add("TEST_TYPE_3"); - - RouteDiscoveryPreference request = new RouteDiscoveryPreference.Builder(testTypes, true) - .build(); - - RouteDiscoveryPreference requestTypes = new RouteDiscoveryPreference.Builder(request) - .setPreferredFeatures(testTypes2) - .build(); - assertNotEquals(request, requestTypes); - - RouteDiscoveryPreference requestActiveScan = new RouteDiscoveryPreference.Builder(request) - .setActiveScan(false) - .build(); - assertNotEquals(request, requestActiveScan); - } -} diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java deleted file mode 100644 index 704dca0427ed..000000000000 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright 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.mediaroutertest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.testng.Assert.assertThrows; - -import android.media.RoutingSessionInfo; -import android.os.Bundle; -import android.os.Parcel; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests {@link RoutingSessionInfo} and its {@link RoutingSessionInfo.Builder builder}. - */ -@RunWith(AndroidJUnit4.class) -@SmallTest -public class RoutingSessionInfoTest { - public static final String TEST_ID = "test_id"; - public static final String TEST_CLIENT_PACKAGE_NAME = "com.test.client.package.name"; - public static final String TEST_ROUTE_FEATURE = "test_route_feature"; - - public static final String TEST_ROUTE_ID_0 = "test_route_type_0"; - public static final String TEST_ROUTE_ID_1 = "test_route_type_1"; - public static final String TEST_ROUTE_ID_2 = "test_route_type_2"; - public static final String TEST_ROUTE_ID_3 = "test_route_type_3"; - public static final String TEST_ROUTE_ID_4 = "test_route_type_4"; - public static final String TEST_ROUTE_ID_5 = "test_route_type_5"; - public static final String TEST_ROUTE_ID_6 = "test_route_type_6"; - public static final String TEST_ROUTE_ID_7 = "test_route_type_7"; - - public static final String TEST_KEY = "test_key"; - public static final String TEST_VALUE = "test_value"; - - @Test - public void testBuilderConstructorWithInvalidValues() { - final String nullId = null; - final String nullClientPackageName = null; - - final String emptyId = ""; - // Note: An empty string as client package name is valid. - - final String validId = TEST_ID; - final String validClientPackageName = TEST_CLIENT_PACKAGE_NAME; - - // ID is invalid - assertThrows(IllegalArgumentException.class, () -> new RoutingSessionInfo.Builder( - nullId, validClientPackageName)); - assertThrows(IllegalArgumentException.class, () -> new RoutingSessionInfo.Builder( - emptyId, validClientPackageName)); - - // client package name is invalid (null) - assertThrows(NullPointerException.class, () -> new RoutingSessionInfo.Builder( - validId, nullClientPackageName)); - - // Both are invalid - assertThrows(IllegalArgumentException.class, () -> new RoutingSessionInfo.Builder( - nullId, nullClientPackageName)); - assertThrows(IllegalArgumentException.class, () -> new RoutingSessionInfo.Builder( - emptyId, nullClientPackageName)); - } - - @Test - public void testBuilderCopyConstructorWithNull() { - // Null RouteInfo (1-argument constructor) - final RoutingSessionInfo nullRoutingSessionInfo = null; - assertThrows(NullPointerException.class, - () -> new RoutingSessionInfo.Builder(nullRoutingSessionInfo)); - } - - @Test - public void testBuilderConstructorWithEmptyClientPackageName() { - // An empty string for client package name is valid. (for unknown cases) - // Creating builder with it should not throw any exception. - RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( - TEST_ID, "" /* clientPackageName*/); - } - - @Test - public void testBuilderBuildWithEmptySelectedRoutesThrowsIAE() { - RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME); - // Note: Calling build() without adding any selected routes. - assertThrows(IllegalArgumentException.class, () -> builder.build()); - } - - @Test - public void testBuilderAddRouteMethodsWithIllegalArgumentsThrowsIAE() { - RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME); - - final String nullRouteId = null; - final String emptyRouteId = ""; - - assertThrows(IllegalArgumentException.class, - () -> builder.addSelectedRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addSelectableRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addDeselectableRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addTransferrableRoute(nullRouteId)); - - assertThrows(IllegalArgumentException.class, - () -> builder.addSelectedRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addSelectableRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addDeselectableRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.addTransferrableRoute(emptyRouteId)); - } - - @Test - public void testBuilderRemoveRouteMethodsWithIllegalArgumentsThrowsIAE() { - RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME); - - final String nullRouteId = null; - final String emptyRouteId = ""; - - assertThrows(IllegalArgumentException.class, - () -> builder.removeSelectedRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeSelectableRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeDeselectableRoute(nullRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeTransferrableRoute(nullRouteId)); - - assertThrows(IllegalArgumentException.class, - () -> builder.removeSelectedRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeSelectableRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeDeselectableRoute(emptyRouteId)); - assertThrows(IllegalArgumentException.class, - () -> builder.removeTransferrableRoute(emptyRouteId)); - } - - @Test - public void testBuilderAndGettersOfRoutingSessionInfo() { - Bundle controlHints = new Bundle(); - controlHints.putString(TEST_KEY, TEST_VALUE); - - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - assertEquals(TEST_ID, sessionInfo.getId()); - assertEquals(TEST_CLIENT_PACKAGE_NAME, sessionInfo.getClientPackageName()); - - assertEquals(2, sessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, sessionInfo.getSelectedRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_1, sessionInfo.getSelectedRoutes().get(1)); - - assertEquals(2, sessionInfo.getSelectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_2, sessionInfo.getSelectableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_3, sessionInfo.getSelectableRoutes().get(1)); - - assertEquals(2, sessionInfo.getDeselectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_4, sessionInfo.getDeselectableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_5, sessionInfo.getDeselectableRoutes().get(1)); - - assertEquals(2, sessionInfo.getTransferrableRoutes().size()); - assertEquals(TEST_ROUTE_ID_6, sessionInfo.getTransferrableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_7, sessionInfo.getTransferrableRoutes().get(1)); - - Bundle controlHintsOut = sessionInfo.getControlHints(); - assertNotNull(controlHintsOut); - assertTrue(controlHintsOut.containsKey(TEST_KEY)); - assertEquals(TEST_VALUE, controlHintsOut.getString(TEST_KEY)); - } - - @Test - public void testBuilderAddRouteMethodsWithBuilderCopyConstructor() { - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .build(); - - RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .build(); - - assertEquals(2, newSessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, newSessionInfo.getSelectedRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_1, newSessionInfo.getSelectedRoutes().get(1)); - - assertEquals(2, newSessionInfo.getSelectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_2, newSessionInfo.getSelectableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_3, newSessionInfo.getSelectableRoutes().get(1)); - - assertEquals(2, newSessionInfo.getDeselectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_4, newSessionInfo.getDeselectableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_5, newSessionInfo.getDeselectableRoutes().get(1)); - - assertEquals(2, newSessionInfo.getTransferrableRoutes().size()); - assertEquals(TEST_ROUTE_ID_6, newSessionInfo.getTransferrableRoutes().get(0)); - assertEquals(TEST_ROUTE_ID_7, newSessionInfo.getTransferrableRoutes().get(1)); - } - - @Test - public void testBuilderRemoveRouteMethods() { - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .removeSelectedRoute(TEST_ROUTE_ID_1) - - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .removeSelectableRoute(TEST_ROUTE_ID_3) - - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .removeDeselectableRoute(TEST_ROUTE_ID_5) - - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .removeTransferrableRoute(TEST_ROUTE_ID_7) - - .build(); - - assertEquals(1, sessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, sessionInfo.getSelectedRoutes().get(0)); - - assertEquals(1, sessionInfo.getSelectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_2, sessionInfo.getSelectableRoutes().get(0)); - - assertEquals(1, sessionInfo.getDeselectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_4, sessionInfo.getDeselectableRoutes().get(0)); - - assertEquals(1, sessionInfo.getTransferrableRoutes().size()); - assertEquals(TEST_ROUTE_ID_6, sessionInfo.getTransferrableRoutes().get(0)); - } - - @Test - public void testBuilderRemoveRouteMethodsWithBuilderCopyConstructor() { - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .build(); - - RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo) - .removeSelectedRoute(TEST_ROUTE_ID_1) - .removeSelectableRoute(TEST_ROUTE_ID_3) - .removeDeselectableRoute(TEST_ROUTE_ID_5) - .removeTransferrableRoute(TEST_ROUTE_ID_7) - .build(); - - assertEquals(1, newSessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, newSessionInfo.getSelectedRoutes().get(0)); - - assertEquals(1, newSessionInfo.getSelectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_2, newSessionInfo.getSelectableRoutes().get(0)); - - assertEquals(1, newSessionInfo.getDeselectableRoutes().size()); - assertEquals(TEST_ROUTE_ID_4, newSessionInfo.getDeselectableRoutes().get(0)); - - assertEquals(1, newSessionInfo.getTransferrableRoutes().size()); - assertEquals(TEST_ROUTE_ID_6, newSessionInfo.getTransferrableRoutes().get(0)); - } - - @Test - public void testBuilderClearRouteMethods() { - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .clearSelectedRoutes() - - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .clearSelectableRoutes() - - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .clearDeselectableRoutes() - - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .clearTransferrableRoutes() - - // SelectedRoutes must not be empty - .addSelectedRoute(TEST_ROUTE_ID_0) - .build(); - - assertEquals(1, sessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, sessionInfo.getSelectedRoutes().get(0)); - - assertTrue(sessionInfo.getSelectableRoutes().isEmpty()); - assertTrue(sessionInfo.getDeselectableRoutes().isEmpty()); - assertTrue(sessionInfo.getTransferrableRoutes().isEmpty()); - } - - @Test - public void testBuilderClearRouteMethodsWithBuilderCopyConstructor() { - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .build(); - - RoutingSessionInfo newSessionInfo = new RoutingSessionInfo.Builder(sessionInfo) - .clearSelectedRoutes() - .clearSelectableRoutes() - .clearDeselectableRoutes() - .clearTransferrableRoutes() - // SelectedRoutes must not be empty - .addSelectedRoute(TEST_ROUTE_ID_0) - .build(); - - assertEquals(1, newSessionInfo.getSelectedRoutes().size()); - assertEquals(TEST_ROUTE_ID_0, newSessionInfo.getSelectedRoutes().get(0)); - - assertTrue(newSessionInfo.getSelectableRoutes().isEmpty()); - assertTrue(newSessionInfo.getDeselectableRoutes().isEmpty()); - assertTrue(newSessionInfo.getTransferrableRoutes().isEmpty()); - } - - @Test - public void testEqualsCreatedWithSameArguments() { - Bundle controlHints = new Bundle(); - controlHints.putString(TEST_KEY, TEST_VALUE); - - RoutingSessionInfo sessionInfo1 = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - RoutingSessionInfo sessionInfo2 = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - assertEquals(sessionInfo1, sessionInfo2); - assertEquals(sessionInfo1.hashCode(), sessionInfo2.hashCode()); - } - - @Test - public void testEqualsCreatedWithBuilderCopyConstructor() { - Bundle controlHints = new Bundle(); - controlHints.putString(TEST_KEY, TEST_VALUE); - - RoutingSessionInfo sessionInfo1 = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - RoutingSessionInfo sessionInfo2 = new RoutingSessionInfo.Builder(sessionInfo1).build(); - - assertEquals(sessionInfo1, sessionInfo2); - assertEquals(sessionInfo1.hashCode(), sessionInfo2.hashCode()); - } - - @Test - public void testEqualsReturnFalse() { - Bundle controlHints = new Bundle(); - controlHints.putString(TEST_KEY, TEST_VALUE); - - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - // Now, we will use copy constructor - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .addSelectedRoute("randomRoute") - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .addSelectableRoute("randomRoute") - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .addDeselectableRoute("randomRoute") - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .addTransferrableRoute("randomRoute") - .build()); - - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .removeSelectedRoute(TEST_ROUTE_ID_1) - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .removeSelectableRoute(TEST_ROUTE_ID_3) - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .removeDeselectableRoute(TEST_ROUTE_ID_5) - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .removeTransferrableRoute(TEST_ROUTE_ID_7) - .build()); - - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .clearSelectedRoutes() - // Note: Calling build() with empty selected routes will throw IAE. - .addSelectedRoute(TEST_ROUTE_ID_0) - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .clearSelectableRoutes() - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .clearDeselectableRoutes() - .build()); - assertNotEquals(sessionInfo, new RoutingSessionInfo.Builder(sessionInfo) - .clearTransferrableRoutes() - .build()); - - // Note: ControlHints will not affect the equals. - } - - @Test - public void testParcelingAndUnParceling() { - Bundle controlHints = new Bundle(); - controlHints.putString(TEST_KEY, TEST_VALUE); - - RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( - TEST_ID, TEST_CLIENT_PACKAGE_NAME) - .addSelectedRoute(TEST_ROUTE_ID_0) - .addSelectedRoute(TEST_ROUTE_ID_1) - .addSelectableRoute(TEST_ROUTE_ID_2) - .addSelectableRoute(TEST_ROUTE_ID_3) - .addDeselectableRoute(TEST_ROUTE_ID_4) - .addDeselectableRoute(TEST_ROUTE_ID_5) - .addTransferrableRoute(TEST_ROUTE_ID_6) - .addTransferrableRoute(TEST_ROUTE_ID_7) - .setControlHints(controlHints) - .build(); - - Parcel parcel = Parcel.obtain(); - sessionInfo.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - RoutingSessionInfo sessionInfoFromParcel = - RoutingSessionInfo.CREATOR.createFromParcel(parcel); - assertEquals(sessionInfo, sessionInfoFromParcel); - assertEquals(sessionInfo.hashCode(), sessionInfoFromParcel.hashCode()); - - // Check controlHints - Bundle controlHintsOut = sessionInfoFromParcel.getControlHints(); - assertNotNull(controlHintsOut); - assertTrue(controlHintsOut.containsKey(TEST_KEY)); - assertEquals(TEST_VALUE, controlHintsOut.getString(TEST_KEY)); - } -} diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java index cf55eba6e5ba..f07cd5e34062 100644 --- a/mms/java/android/telephony/MmsManager.java +++ b/mms/java/android/telephony/MmsManager.java @@ -55,10 +55,12 @@ public class MmsManager { * sending the message. * @param sentIntent if not NULL this <code>PendingIntent</code> is broadcast when the message * is successfully sent, or failed + * @param messageId an id that uniquely identifies the message requested to be sent. + * Used for logging and diagnostics purposes. The id may be 0. */ public void sendMultimediaMessage(int subId, @NonNull Uri contentUri, @Nullable String locationUrl, @Nullable Bundle configOverrides, - @Nullable PendingIntent sentIntent) { + @Nullable PendingIntent sentIntent, long messageId) { try { final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); if (iMms == null) { @@ -66,7 +68,7 @@ public class MmsManager { } iMms.sendMessage(subId, ActivityThread.currentPackageName(), contentUri, - locationUrl, configOverrides, sentIntent); + locationUrl, configOverrides, sentIntent, messageId); } catch (RemoteException e) { // Ignore it } @@ -83,18 +85,22 @@ public class MmsManager { * downloading the message. * @param downloadedIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is downloaded, or the download is failed + * @param messageId an id that uniquely identifies the message requested to be downloaded. + * Used for logging and diagnostics purposes. The id may be 0. + * downloaded. * @throws IllegalArgumentException if locationUrl or contentUri is empty */ public void downloadMultimediaMessage(int subId, @NonNull String locationUrl, @NonNull Uri contentUri, @Nullable Bundle configOverrides, - @Nullable PendingIntent downloadedIntent) { + @Nullable PendingIntent downloadedIntent, long messageId) { try { final IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms")); if (iMms == null) { return; } iMms.downloadMessage(subId, ActivityThread.currentPackageName(), - locationUrl, contentUri, configOverrides, downloadedIntent); + locationUrl, contentUri, configOverrides, downloadedIntent, + messageId); } catch (RemoteException e) { // Ignore it } diff --git a/mms/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl index 8be511186800..e0e0a4a812e4 100644 --- a/mms/java/com/android/internal/telephony/IMms.aidl +++ b/mms/java/com/android/internal/telephony/IMms.aidl @@ -37,9 +37,11 @@ interface IMms { * sending the message. See {@link android.telephony.SmsManager} for the value names and types. * @param sentIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is successfully sent, or failed + * @param messageId An id that uniquely identifies the message requested to be sent. */ void sendMessage(int subId, String callingPkg, in Uri contentUri, - String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent); + String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent, + in long messageId); /** * Download an MMS message using known location and transaction id @@ -54,10 +56,11 @@ interface IMms { * types. * @param downloadedIntent if not NULL this <code>PendingIntent</code> is * broadcast when the message is downloaded, or the download is failed - */ + * @param messageId An id that uniquely identifies the message requested to be downloaded. + */ void downloadMessage(int subId, String callingPkg, String locationUrl, in Uri contentUri, in Bundle configOverrides, - in PendingIntent downloadedIntent); + in PendingIntent downloadedIntent, in long messageId); /** * Import a text message into system's SMS store diff --git a/native/android/Android.bp b/native/android/Android.bp index 0c6f507787d9..34ab7a0a0770 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -64,6 +64,7 @@ cc_library_shared { "libgui", "libharfbuzz_ng", // Only for including hb.h via minikin "libsensor", + "libstats_jni", "libandroid_runtime", "libminikin", "libnetd_client", diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java index c9e0d0ab351d..d4eb2a9c75d0 100644 --- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java +++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeApp.java @@ -16,6 +16,9 @@ package com.android.fakeoemfeatures; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + import android.app.ActivityManager; import android.app.ActivityThread; import android.app.AlertDialog; @@ -25,9 +28,11 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.util.Size; import android.util.Slog; import android.view.Display; import android.view.ViewGroup; @@ -94,8 +99,13 @@ public class FakeApp extends Application { return; } - final WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); - final Display display = wm.getDefaultDisplay(); + // Construct an instance of WindowManager to add the window of TYPE_APPLICATION_OVERLAY to + // the default display. + final DisplayManager dm = getSystemService(DisplayManager.class); + final Display defaultDisplay = dm.getDisplay(DEFAULT_DISPLAY); + final Context windowContext = createDisplayContext(defaultDisplay) + .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */); + final WindowManager wm = windowContext.getSystemService(WindowManager.class); // Check to make sure we are not running on a user build. If this // is a user build, WARN! Do not want! @@ -108,14 +118,14 @@ public class FakeApp extends Application { builder.setCancelable(false); builder.setPositiveButton("I understand", null); Dialog dialog = builder.create(); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + dialog.getWindow().setType(TYPE_APPLICATION_OVERLAY); dialog.show(); } // Make a fake window that is always around eating graphics resources. FakeView view = new FakeView(this); WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); @@ -124,7 +134,8 @@ public class FakeApp extends Application { } lp.width = ViewGroup.LayoutParams.MATCH_PARENT; lp.height = ViewGroup.LayoutParams.MATCH_PARENT; - int maxSize = display.getMaximumSizeDimension(); + Size maxWindowSize = wm.getMaximumWindowMetrics().getSize(); + int maxSize = Math.max(maxWindowSize.getWidth(), maxWindowSize.getHeight()); maxSize *= 2; lp.x = maxSize; lp.y = maxSize; diff --git a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java index ff09000b7bbd..df00eee63b50 100644 --- a/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java +++ b/packages/FakeOemFeatures/src/com/android/fakeoemfeatures/FakeBackgroundService.java @@ -16,6 +16,9 @@ package com.android.fakeoemfeatures; +import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; + import java.util.ArrayList; import java.util.Random; @@ -23,9 +26,11 @@ import android.app.Dialog; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.util.Size; import android.view.Display; import android.view.ViewGroup; import android.view.WindowManager; @@ -68,13 +73,15 @@ public class FakeBackgroundService extends Service { super.onCreate(); mHandler.sendEmptyMessageDelayed(MSG_TICK, TICK_DELAY); - final WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); - final Display display = wm.getDefaultDisplay(); + final DisplayManager dm = getSystemService(DisplayManager.class); + final Display display = dm.getDisplay(DEFAULT_DISPLAY); + final Context windowContext = createDisplayContext(display) + .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */); // Make a fake window that is always around eating graphics resources. - FakeView view = new FakeView(this); - Dialog dialog = new Dialog(this, android.R.style.Theme_Holo_Dialog); - dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + FakeView view = new FakeView(windowContext); + Dialog dialog = new Dialog(windowContext, android.R.style.Theme_Holo_Dialog); + dialog.getWindow().setType(TYPE_APPLICATION_OVERLAY); dialog.getWindow().setFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE @@ -89,7 +96,11 @@ public class FakeBackgroundService extends Service { dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); WindowManager.LayoutParams lp = dialog.getWindow().getAttributes(); - int maxSize = display.getMaximumSizeDimension(); + // Create an instance of WindowManager that is adjusted to the area of the display dedicated + // for windows with type TYPE_APPLICATION_OVERLAY. + final WindowManager wm = windowContext.getSystemService(WindowManager.class); + Size maxWindowSize = wm.getMaximumWindowMetrics().getSize(); + int maxSize = Math.max(maxWindowSize.getWidth(), maxWindowSize.getHeight()); maxSize *= 2; lp.x = maxSize; lp.y = maxSize; diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml index 851a3d8f136a..d65d821e71ab 100644 --- a/packages/SettingsLib/res/values-ar/arrays.xml +++ b/packages/SettingsLib/res/values-ar/arrays.xml @@ -252,7 +252,7 @@ <item msgid="3474333938380896988">"عرض مناطق العجز في رؤية اللونين الأخضر والأحمر"</item> </string-array> <string-array name="app_process_limit_entries"> - <item msgid="794656271086646068">"الحد القياسي"</item> + <item msgid="794656271086646068">"الحدّ العادي"</item> <item msgid="8628438298170567201">"ليست هناك عمليات بالخلفية"</item> <item msgid="915752993383950932">"عملية واحدة بحد أقصى"</item> <item msgid="8554877790859095133">"عمليتان بحد أقصى"</item> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 54856566e021..5103345401f4 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -124,7 +124,7 @@ <string name="bluetooth_talkback_headset" msgid="3406852564400882682">"سماعة رأس"</string> <string name="bluetooth_talkback_phone" msgid="868393783858123880">"هاتف"</string> <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"تصوير"</string> - <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"سماعة أذن"</string> + <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"السمّاعة"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"جهاز إدخال طرفي"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"بلوتوث"</string> <string name="bluetooth_hearingaid_left_pairing_message" msgid="8561855779703533591">"جارٍ إقران سماعة الأذن الطبية اليسرى…"</string> @@ -157,7 +157,7 @@ <string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string> <string name="tts_settings_title" msgid="7602210956640483039">"تحويل النص إلى كلام"</string> <string name="tts_default_rate_title" msgid="3964187817364304022">"معدل سرعة الكلام"</string> - <string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة نطق الكلام"</string> + <string name="tts_default_rate_summary" msgid="3781937042151716987">"سرعة قول الكلام"</string> <string name="tts_default_pitch_title" msgid="6988592215554485479">"درجة الصوت"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"للتأثير في نبرة الكلام المُرَكَّب"</string> <string name="tts_default_lang_title" msgid="4698933575028098940">"اللغة"</string> @@ -181,7 +181,7 @@ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"المحرّك المفضّل"</string> <string name="tts_general_section_title" msgid="8919671529502364567">"عامة"</string> <string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"إعادة ضبط طبقة صوت الكلام"</string> - <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"إعادة ضبط طبقة الصوت التي يتم نطق النص بها على الإعداد التلقائي."</string> + <string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"إعادة ضبط طبقة الصوت التي يتم قول النص بها على الإعداد التلقائي."</string> <string-array name="tts_rate_entries"> <item msgid="9004239613505400644">"بطيء جدًا"</item> <item msgid="1815382991399815061">"بطيء"</item> @@ -353,7 +353,7 @@ <string-array name="color_mode_names"> <item msgid="3836559907767149216">"نابض بالحياة (تلقائي)"</item> <item msgid="9112200311983078311">"طبيعي"</item> - <item msgid="6564241960833766170">"قياسي"</item> + <item msgid="6564241960833766170">"عادي"</item> </string-array> <string-array name="color_mode_descriptions"> <item msgid="6828141153199944847">"ألوان محسَّنة"</item> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index cda42d348c45..5bcff5ad27b2 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -201,7 +201,7 @@ <string name="development_settings_summary" msgid="8718917813868735095">"Đặt tùy chọn cho phát triển ứng dụng"</string> <string name="development_settings_not_available" msgid="355070198089140951">"Tùy chọn dành cho nhà phát triển không khả dụng cho người dùng này"</string> <string name="vpn_settings_not_available" msgid="2894137119965668920">"Cài đặt VPN không khả dụng cho người dùng này"</string> - <string name="tethering_settings_not_available" msgid="266821736434699780">"Cài đặt chia sẻ kết nối không khả dụng cho người dùng này"</string> + <string name="tethering_settings_not_available" msgid="266821736434699780">"Cài đặt cách chia sẻ kết nối không khả dụng cho người dùng này"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"Cài đặt tên điểm truy cập không khả dụng cho người dùng này"</string> <string name="enable_adb" msgid="8072776357237289039">"Gỡ lỗi qua USB"</string> <string name="enable_adb_summary" msgid="3711526030096574316">"Bật chế độ gỡ lỗi khi kết nối USB"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java index b01fc8541957..f5aa652f3194 100644 --- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java +++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java @@ -216,7 +216,7 @@ public class NetworkPolicyEditor { private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) { if (template == null) return null; final String networkId = template.getNetworkId(); - final String strippedNetworkId = WifiInfo.removeDoubleQuotes(networkId); + final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId); if (!TextUtils.equals(strippedNetworkId, networkId)) { return new NetworkTemplate( template.getMatchRule(), template.getSubscriberId(), strippedNetworkId); diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java index aac7fc3c927a..d48aa246ecba 100644 --- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java +++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java @@ -402,7 +402,7 @@ public class ZoneGetter { private static List<String> extractTimeZoneIds(List<TimeZoneMapping> timeZoneMappings) { final List<String> zoneIds = new ArrayList<>(timeZoneMappings.size()); for (TimeZoneMapping timeZoneMapping : timeZoneMappings) { - zoneIds.add(timeZoneMapping.timeZoneId); + zoneIds.add(timeZoneMapping.getTimeZoneId()); } return Collections.unmodifiableList(zoneIds); } diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 84dde05afb2e..3b1a0c327c9f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -654,7 +654,7 @@ public class AccessPoint implements Comparable<AccessPoint> { } } } - return oldMetering == mIsScoredNetworkMetered; + return oldMetering != mIsScoredNetworkMetered; } /** diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 65269c9d5a89..dee1d7eced66 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -728,6 +728,7 @@ public class SettingsBackupTest { Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, Settings.Secure.FACE_UNLOCK_RE_ENROLL, Settings.Secure.TAP_GESTURE, + Settings.Secure.NEARBY_SHARING_COMPONENT, // not user configurable Settings.Secure.WINDOW_MAGNIFICATION, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, Settings.Secure.SUPPRESS_DOZE); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 0f3585303ed8..84d9bb673d1f 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -219,6 +219,9 @@ <!-- Permission required for CTS test - CrossProfileAppsHostSideTest --> <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/> + <!-- permissions required for CTS test - PhoneStateListenerTest --> + <uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" /> + <!-- Permission required for CTS test - UiModeManagerTest --> <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/> @@ -240,6 +243,9 @@ <!-- Allows setting brightness from the shell --> <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/> + <!-- Permission required for CTS test - ShortcutManagerUsageTest --> + <uses-permission android:name="android.permission.ACCESS_SHORTCUTS"/> + <!-- Permissions required to test ambient display. --> <uses-permission android:name="android.permission.READ_DREAM_STATE"/> <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/> diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index c238d7d49f9b..de174b13a459 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -69,10 +69,6 @@ android_library { ], manifest: "AndroidManifest.xml", - libs: [ - "telephony-common", - ], - kotlincflags: ["-Xjvm-default=enable"], plugins: ["dagger2-compiler-2.19"], @@ -136,7 +132,6 @@ android_library { ], libs: [ "android.test.runner", - "telephony-common", "android.test.base", ], kotlincflags: ["-Xjvm-default=enable"], @@ -163,10 +158,6 @@ android_app { proguard_flags_files: ["proguard.flags"], }, - libs: [ - "telephony-common", - ], - kotlincflags: ["-Xjvm-default=enable"], dxflags: ["--multi-dex"], diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md index 2fb0c996111a..9fe2e181971a 100644 --- a/packages/SystemUI/docs/plugin_hooks.md +++ b/packages/SystemUI/docs/plugin_hooks.md @@ -56,11 +56,6 @@ Expected interface: [ClockPlugin](/packages/SystemUI/plugin/src/com/android/syst Use: Allows replacement of the keyguard main clock. -### Action: com.android.systemui.action.PLUGIN_NPV -Expected interface: [NPVPlugin](/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java) - -Use: Attach a view under QQS for prototyping. - # Global plugin dependencies These classes can be accessed by any plugin using PluginDependency as long as they @Requires them. diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java deleted file mode 100644 index c1d4b03b6620..000000000000 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/HomeControlsPlugin.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.plugins; - -import android.view.ViewGroup; - -import com.android.systemui.plugins.annotations.ProvidesInterface; - -/** - * Test plugin for home controls - */ -@ProvidesInterface(action = HomeControlsPlugin.ACTION, version = HomeControlsPlugin.VERSION) -public interface HomeControlsPlugin extends Plugin { - - String ACTION = "com.android.systemui.action.PLUGIN_HOME_CONTROLS"; - int VERSION = 1; - - /** - * Pass the container for the plugin to use however it wants. Ideally the plugin impl - * will add home controls to this space. - */ - void sendParentGroup(ViewGroup group); - - /** - * When visible, will poll for updates. - */ - void setVisible(boolean visible); -} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java deleted file mode 100644 index 1426266a7048..000000000000 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.plugins; - -import android.view.View; -import android.widget.FrameLayout; - -import com.android.systemui.plugins.annotations.ProvidesInterface; - -/** - * Plugin to attach custom views under QQS. - * - * A parent view is provided to the plugin to which they can add Views. - * <br> - * The parent is a {@link FrameLayout} with same background as QS and 96dp height. - * - * {@see NPVPluginManager} - * {@see status_bar_expanded_plugin_frame} - */ -@ProvidesInterface(action = NPVPlugin.ACTION, version = NPVPlugin.VERSION) -public interface NPVPlugin extends Plugin { - String ACTION = "com.android.systemui.action.PLUGIN_NPV"; - int VERSION = 1; - - /** - * Attach views to the parent. - * - * @param parent a {@link FrameLayout} to which to attach views. Preferably a root view. - * @return a view attached to parent. - */ - View attachToRoot(FrameLayout parent); - - /** - * Indicate to the plugin when it is listening (QS expanded) - * @param listening - */ - default void setListening(boolean listening) {}; -} diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 17f2f476c9f2..6518924ca0c2 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -133,7 +133,6 @@ public interface QSTile { public CharSequence label; public CharSequence secondaryLabel; public CharSequence contentDescription; - public CharSequence stateDescription; public CharSequence dualLabelContentDescription; public boolean disabledByPolicy; public boolean dualTarget = false; @@ -152,7 +151,6 @@ public interface QSTile { || !Objects.equals(other.label, label) || !Objects.equals(other.secondaryLabel, secondaryLabel) || !Objects.equals(other.contentDescription, contentDescription) - || !Objects.equals(other.stateDescription, stateDescription) || !Objects.equals(other.dualLabelContentDescription, dualLabelContentDescription) || !Objects.equals(other.expandedAccessibilityClassName, @@ -170,7 +168,6 @@ public interface QSTile { other.label = label; other.secondaryLabel = secondaryLabel; other.contentDescription = contentDescription; - other.stateDescription = stateDescription; other.dualLabelContentDescription = dualLabelContentDescription; other.expandedAccessibilityClassName = expandedAccessibilityClassName; other.disabledByPolicy = disabledByPolicy; @@ -198,7 +195,6 @@ public interface QSTile { sb.append(",label=").append(label); sb.append(",secondaryLabel=").append(secondaryLabel); sb.append(",contentDescription=").append(contentDescription); - sb.append(",stateDescription=").append(stateDescription); sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription); sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName); sb.append(",disabledByPolicy=").append(disabledByPolicy); diff --git a/packages/SystemUI/res/drawable/control_no_favorites_background.xml b/packages/SystemUI/res/drawable/control_no_favorites_background.xml index 1e282ad0eec7..947c77b4e39e 100644 --- a/packages/SystemUI/res/drawable/control_no_favorites_background.xml +++ b/packages/SystemUI/res/drawable/control_no_favorites_background.xml @@ -17,6 +17,6 @@ */ --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <stroke android:width="1dp" android:color="?android:attr/colorBackgroundFloating"/> + <stroke android:width="1dp" android:color="@*android:color/foreground_material_dark"/> <corners android:radius="@dimen/control_corner_radius" /> </shape> diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml index 3c4c61e30bc1..cd7ec5eb5c81 100644 --- a/packages/SystemUI/res/layout/controls_base_item.xml +++ b/packages/SystemUI/res/layout/controls_base_item.xml @@ -23,8 +23,8 @@ android:padding="@dimen/control_padding" android:clickable="true" android:focusable="true" - android:layout_marginLeft="3dp" - android:layout_marginRight="3dp" + android:layout_marginLeft="2dp" + android:layout_marginRight="2dp" android:background="@drawable/control_background"> <ImageView @@ -60,9 +60,9 @@ android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="18sp" + android:textSize="14sp" android:textColor="?android:attr/textColorPrimary" - android:fontFamily="@*android:string/config_headlineFontFamily" + android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toTopOf="@+id/subtitle" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/icon" /> @@ -71,9 +71,9 @@ android:id="@+id/subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="16sp" + android:textSize="12sp" android:textColor="?android:attr/textColorSecondary" - android:fontFamily="@*android:string/config_headlineFontFamily" + android:textAppearance="?android:attr/textAppearanceSmall" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/layout/controls_no_favorites.xml b/packages/SystemUI/res/layout/controls_no_favorites.xml index 79672caed61b..096f1f49aaba 100644 --- a/packages/SystemUI/res/layout/controls_no_favorites.xml +++ b/packages/SystemUI/res/layout/controls_no_favorites.xml @@ -12,7 +12,7 @@ android:paddingBottom="40dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" - android:textColor="?android:attr/textColorPrimary" + android:textColor="@*android:color/foreground_material_dark" android:fontFamily="@*android:string/config_headlineFontFamily" android:background="@drawable/control_no_favorites_background"/> </merge> diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml index 7804fe6b6272..6a3e95d34358 100644 --- a/packages/SystemUI/res/layout/controls_with_favorites.xml +++ b/packages/SystemUI/res/layout/controls_with_favorites.xml @@ -4,7 +4,8 @@ <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:paddingBottom="20dp"> <TextView android:text="@string/quick_controls_title" @@ -13,17 +14,23 @@ android:singleLine="true" android:gravity="center" android:textSize="25dp" - android:textColor="?android:attr/textColorPrimary" + android:textColor="@*android:color/foreground_material_dark" android:fontFamily="@*android:string/config_headlineFontFamily" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent"/> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + <ImageView android:id="@+id/controls_more" android:src="@drawable/ic_more_vert" android:layout_width="34dp" android:layout_height="24dp" android:layout_marginEnd="10dp" - app:layout_constraintEnd_toEndOf="parent"/> + android:tint="@*android:color/foreground_material_dark" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml index 674148495478..f90012d790e0 100644 --- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml +++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml @@ -96,18 +96,18 @@ app:layout_constraintTop_toBottomOf="@id/global_actions_view"> <FrameLayout - android:translationY="@dimen/global_actions_plugin_offset" android:id="@+id/global_actions_panel_container" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout - android:translationY="@dimen/global_actions_plugin_offset" android:id="@+id/global_actions_controls" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:layout_marginRight="@dimen/global_actions_grid_horizontal_padding" + android:layout_marginLeft="@dimen/global_actions_grid_horizontal_padding" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/global_actions_panel"> diff --git a/packages/SystemUI/res/layout/home_controls.xml b/packages/SystemUI/res/layout/home_controls.xml deleted file mode 100644 index 69a0e872dc8c..000000000000 --- a/packages/SystemUI/res/layout/home_controls.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/home_controls_layout" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="@integer/notification_panel_layout_gravity" - android:visibility="gone" - android:padding="8dp" - android:layout_margin="5dp" - android:background="?android:attr/colorBackgroundFloating"> -</FrameLayout> diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 76c1045ef1dd..4fae3c500a45 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -42,32 +42,6 @@ android:visibility="gone" /> - <LinearLayout - android:id="@+id/divider_container" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal" - android:background="@color/transparent" > - - <android.widget.Space - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="@integer/qqs_split_fraction" /> - - <com.android.systemui.DarkReceiverImpl - android:id="@+id/divider" - android:layout_height="match_parent" - android:layout_width="1dp" - android:layout_marginTop="4dp" - android:layout_marginBottom="4dp" /> - - <android.widget.Space - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="@integer/qs_split_fraction" /> - - </LinearLayout> - <LinearLayout android:id="@+id/status_bar_contents" android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 479f255b7e44..115b4a86b86d 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -55,9 +55,6 @@ android:clipChildren="false" systemui:viewType="com.android.systemui.plugins.qs.QS" /> - <!-- Temporary area to test out home controls --> - <include layout="@layout/home_controls" /> - <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout android:id="@+id/notification_stack_scroller" android:layout_marginTop="@dimen/notification_panel_margin_top" diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index cc58b2014496..1f9fb0511d26 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -972,7 +972,6 @@ <!-- Global actions power menu --> <dimen name="global_actions_top_margin">12dp</dimen> - <dimen name="global_actions_plugin_offset">-145dp</dimen> <dimen name="global_actions_panel_width">120dp</dimen> <dimen name="global_actions_padding">12dp</dimen> @@ -1182,7 +1181,7 @@ <dimen name="magnifier_up_down_controls_height">40dp</dimen> <!-- Home Controls --> - <dimen name="control_spacing">5dp</dimen> + <dimen name="control_spacing">4dp</dimen> <dimen name="control_corner_radius">15dp</dimen> <dimen name="control_height">100dp</dimen> <dimen name="control_padding">15dp</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8d935ecc691d..1f13f8dc02fe 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2549,7 +2549,4 @@ <!-- Quick Controls strings [CHAR LIMIT=30] --> <string name="quick_controls_title">Quick Controls</string> - - <!-- The tile in quick settings is unavailable. [CHAR LIMIT=32] --> - <string name="tile_unavailable">Unvailable</string> </resources> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java deleted file mode 100644 index 78b1b26140d5..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.systemui.shared.recents.model; - -import static android.content.pm.PackageManager.MATCH_ANY_USER; - -import android.app.ActivityManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.UserHandle; -import android.util.IconDrawableFactory; -import android.util.Log; -import android.util.LruCache; - -import com.android.systemui.shared.system.PackageManagerWrapper; - -public abstract class IconLoader { - - private static final String TAG = "IconLoader"; - - protected final Context mContext; - protected final TaskKeyLruCache<Drawable> mIconCache; - protected final LruCache<ComponentName, ActivityInfo> mActivityInfoCache; - - public IconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, - ActivityInfo> activityInfoCache) { - mContext = context; - mIconCache = iconCache; - mActivityInfoCache = activityInfoCache; - } - - /** - * Returns the activity info for the given task key, retrieving one from the system if the - * task key is expired. - * - * TODO: Move this to an ActivityInfoCache class - */ - public ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) { - ComponentName cn = taskKey.getComponent(); - ActivityInfo activityInfo = mActivityInfoCache.get(cn); - if (activityInfo == null) { - activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, taskKey.userId); - if (cn == null || activityInfo == null) { - Log.e(TAG, "Unexpected null component name or activity info: " + cn + ", " + - activityInfo); - return null; - } - mActivityInfoCache.put(cn, activityInfo); - } - return activityInfo; - } - - public Drawable getIcon(Task t) { - Drawable cachedIcon = mIconCache.get(t.key); - if (cachedIcon == null) { - cachedIcon = createNewIconForTask(t.key, t.taskDescription, true /* returnDefault */); - mIconCache.put(t.key, cachedIcon); - } - return cachedIcon; - } - - /** - * Returns the cached task icon if the task key is not expired, updating the cache if it is. - */ - public Drawable getAndInvalidateIfModified(Task.TaskKey taskKey, - ActivityManager.TaskDescription td, boolean loadIfNotCached) { - // Return the cached activity icon if it exists - Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey); - if (icon != null) { - return icon; - } - - if (loadIfNotCached) { - icon = createNewIconForTask(taskKey, td, false /* returnDefault */); - if (icon != null) { - mIconCache.put(taskKey, icon); - return icon; - } - } - - // We couldn't load any icon - return null; - } - - private Drawable createNewIconForTask(Task.TaskKey taskKey, - ActivityManager.TaskDescription desc, boolean returnDefault) { - int userId = taskKey.userId; - Bitmap tdIcon = desc.getInMemoryIcon(); - if (tdIcon != null) { - return createDrawableFromBitmap(tdIcon, userId, desc); - } - if (desc.getIconResource() != 0) { - try { - PackageManager pm = mContext.getPackageManager(); - ApplicationInfo appInfo = pm.getApplicationInfo(taskKey.getPackageName(), - MATCH_ANY_USER); - Resources res = pm.getResourcesForApplication(appInfo); - return createBadgedDrawable(res.getDrawable(desc.getIconResource(), null), userId, - desc); - } catch (Resources.NotFoundException|PackageManager.NameNotFoundException e) { - Log.e(TAG, "Could not find icon drawable from resource", e); - } - } - - tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon( - desc.getIconFilename(), userId); - if (tdIcon != null) { - return createDrawableFromBitmap(tdIcon, userId, desc); - } - - // Load the icon from the activity info and cache it - ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey); - if (activityInfo != null) { - Drawable icon = getBadgedActivityIcon(activityInfo, userId, desc); - if (icon != null) { - return icon; - } - } - - // At this point, even if we can't load the icon, we will set the default icon. - return returnDefault ? getDefaultIcon(userId) : null; - } - - public abstract Drawable getDefaultIcon(int userId); - - protected Drawable createDrawableFromBitmap(Bitmap icon, int userId, - ActivityManager.TaskDescription desc) { - return createBadgedDrawable( - new BitmapDrawable(mContext.getResources(), icon), userId, desc); - } - - protected abstract Drawable createBadgedDrawable(Drawable icon, int userId, - ActivityManager.TaskDescription desc); - - /** - * @return the activity icon for the ActivityInfo for a user, badging if necessary. - */ - protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId, - ActivityManager.TaskDescription desc); - - public static class DefaultIconLoader extends IconLoader { - - private final BitmapDrawable mDefaultIcon; - private final IconDrawableFactory mDrawableFactory; - - public DefaultIconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, - LruCache<ComponentName, ActivityInfo> activityInfoCache) { - super(context, iconCache, activityInfoCache); - - // Create the default assets - Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); - icon.eraseColor(0); - mDefaultIcon = new BitmapDrawable(context.getResources(), icon); - mDrawableFactory = IconDrawableFactory.newInstance(context); - } - - @Override - public Drawable getDefaultIcon(int userId) { - return mDefaultIcon; - } - - @Override - protected Drawable createBadgedDrawable(Drawable icon, int userId, - ActivityManager.TaskDescription desc) { - if (userId != UserHandle.myUserId()) { - icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(userId)); - } - return icon; - } - - @Override - protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId, - ActivityManager.TaskDescription desc) { - return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId); - } - } -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java deleted file mode 100644 index 8a244bf81c7c..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyCache.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui.shared.recents.model; - -import android.util.Log; -import android.util.SparseArray; - -import com.android.systemui.shared.recents.model.Task.TaskKey; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Base class for both strong and LRU task key cache. - */ -public abstract class TaskKeyCache<V> { - - protected static final String TAG = "TaskKeyCache"; - - protected final SparseArray<TaskKey> mKeys = new SparseArray<>(); - - /** - * Gets a specific entry in the cache with the specified key, regardless of whether the cached - * value is valid or not. - */ - public final synchronized V get(TaskKey key) { - return getCacheEntry(key.id); - } - - /** - * Returns the value only if the key is valid (has not been updated since the last time it was - * in the cache) - */ - public final synchronized V getAndInvalidateIfModified(TaskKey key) { - TaskKey lastKey = mKeys.get(key.id); - if (lastKey != null) { - if ((lastKey.windowingMode != key.windowingMode) || - (lastKey.lastActiveTime != key.lastActiveTime)) { - // The task has updated (been made active since the last time it was put into the - // LRU cache) or the stack id for the task has changed, invalidate that cache item - remove(key); - return null; - } - } - // Either the task does not exist in the cache, or the last active time is the same as - // the key specified, so return what is in the cache - return getCacheEntry(key.id); - } - - /** Puts an entry in the cache for a specific key. */ - public final synchronized void put(TaskKey key, V value) { - if (key == null || value == null) { - Log.e(TAG, "Unexpected null key or value: " + key + ", " + value); - return; - } - mKeys.put(key.id, key); - putCacheEntry(key.id, value); - } - - - /** Removes a cache entry for a specific key. */ - public final synchronized void remove(TaskKey key) { - // Remove the key after the cache value because we need it to make the callback - removeCacheEntry(key.id); - mKeys.remove(key.id); - } - - /** @return {@link Collection} of {@link TaskKey} */ - public Collection<TaskKey> getValues() { - Collection<TaskKey> result = new ArrayList<>(mKeys.size()); - for (int i = 0; i < mKeys.size(); i++) { - result.add(mKeys.valueAt(i)); - } - return result; - } - - /** Removes all the entries in the cache. */ - public final synchronized void evictAll() { - evictAllCache(); - mKeys.clear(); - } - - protected abstract V getCacheEntry(int id); - protected abstract void putCacheEntry(int id, V value); - protected abstract void removeCacheEntry(int id); - protected abstract void evictAllCache(); -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java deleted file mode 100644 index bc57b08236cf..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.shared.recents.model; - -import android.util.LruCache; - -import com.android.systemui.shared.recents.model.Task.TaskKey; - -import java.io.PrintWriter; - -/** - * A mapping of {@link TaskKey} to value, with additional LRU functionality where the least - * recently referenced key/values will be evicted as more values than the given cache size are - * inserted. - * - * In addition, this also allows the caller to invalidate cached values for keys that have since - * changed. - */ -public class TaskKeyLruCache<V> extends TaskKeyCache<V> { - - public interface EvictionCallback { - void onEntryEvicted(TaskKey key); - } - - private final LruCache<Integer, V> mCache; - private final EvictionCallback mEvictionCallback; - - public TaskKeyLruCache(int cacheSize) { - this(cacheSize, null); - } - - public TaskKeyLruCache(int cacheSize, EvictionCallback evictionCallback) { - mEvictionCallback = evictionCallback; - mCache = new LruCache<Integer, V>(cacheSize) { - - @Override - protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) { - if (mEvictionCallback != null && evicted) { - mEvictionCallback.onEntryEvicted(mKeys.get(taskId)); - } - - // Only remove from mKeys on cache remove, not a cache update. - if (newV == null) { - mKeys.remove(taskId); - } - } - }; - } - - /** Trims the cache to a specific size */ - public final void trimToSize(int cacheSize) { - mCache.trimToSize(cacheSize); - } - - public void dump(String prefix, PrintWriter writer) { - String innerPrefix = prefix + " "; - - writer.print(prefix); writer.print(TAG); - writer.print(" numEntries="); writer.print(mKeys.size()); - writer.println(); - int keyCount = mKeys.size(); - for (int i = 0; i < keyCount; i++) { - writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i))); - } - } - - @Override - protected V getCacheEntry(int id) { - return mCache.get(id); - } - - @Override - protected void putCacheEntry(int id, V value) { - mCache.put(id, value); - } - - @Override - protected void removeCacheEntry(int id) { - mCache.remove(id); - } - - @Override - protected void evictAllCache() { - mCache.evictAll(); - } -} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index ed1cd8191092..d5a08dda9853 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -409,15 +409,6 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { mAudioManager.dispatchMediaKeyEvent(keyEvent); } - @Override - public void dispatchSystemUiVisibilityChanged(int visibility) { - super.dispatchSystemUiVisibilityChanged(visibility); - - if (!(mContext instanceof Activity)) { - setSystemUiVisibility(STATUS_BAR_DISABLE_BACK); - } - } - /** * 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 diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index ae787260adca..29c67ae1b4a6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -15,7 +15,12 @@ */ package com.android.keyguard; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.ViewRootImpl.sNewInsetsMode; +import static android.view.WindowInsets.Type.ime; +import static android.view.WindowInsets.Type.systemBars; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static java.lang.Integer.max; import android.app.Activity; import android.app.AlertDialog; @@ -38,6 +43,7 @@ import android.view.SurfaceControl; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; +import android.view.WindowInsets; import android.view.WindowManager; import android.widget.FrameLayout; @@ -339,13 +345,22 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } @Override - protected boolean fitSystemWindows(Rect insets) { + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + // Consume bottom insets because we're setting the padding locally (for IME and navbar.) - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), insets.bottom); - insets.bottom = 0; - return false; + int inset; + if (sNewInsetsMode == NEW_INSETS_MODE_FULL) { + int bottomInset = insets.getInsetsIgnoringVisibility(systemBars()).bottom; + int imeInset = insets.getInsets(ime()).bottom; + inset = max(bottomInset, imeInset); + } else { + inset = insets.getSystemWindowInsetBottom(); + } + setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), inset); + return insets.inset(0, 0, 0, inset); } + private void showDialog(String title, String message) { if (mAlertDialog != null) { mAlertDialog.dismiss(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 58a6c17e8239..6a04583b70ba 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -371,7 +371,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab checkIsHandlerThread(); if (DEBUG_SIM_STATES) { Log.v(TAG, "onSubscriptionInfoChanged()"); - List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(false); + List<SubscriptionInfo> sil = mSubscriptionManager + .getActiveAndHiddenSubscriptionInfoList(); if (sil != null) { for (SubscriptionInfo subInfo : sil) { Log.v(TAG, "SubInfo:" + subInfo); @@ -425,10 +426,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) { List<SubscriptionInfo> sil = mSubscriptionInfo; if (sil == null || forceReload) { - sil = mSubscriptionManager.getActiveSubscriptionInfoList(false); + sil = mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList(); } if (sil == null) { - // getActiveSubscriptionInfoList was null callers expect an empty list. + // getActiveAndHiddenSubscriptionInfoList was null callers expect an empty list. mSubscriptionInfo = new ArrayList<SubscriptionInfo>(); } else { mSubscriptionInfo = sil; @@ -1882,9 +1883,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep; final int user = getCurrentUser(); final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user); - final boolean isLockOutOrLockDown = - containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) - || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) + final boolean isLockDown = + containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); final boolean isEncryptedOrTimedOut = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT) @@ -1898,9 +1898,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass; // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing. - // Lockout/lockdown modes shouldn't scan, since they are more explicit. + // Lock-down mode shouldn't scan, since it is more explicit. boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass && !mBouncer) - && !isLockOutOrLockDown; + && !isLockDown; // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index c243309d960a..581cf7a2fbef 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -86,6 +86,8 @@ public class WindowMagnificationController implements View.OnClickListener, private SurfaceView mMirrorSurfaceView; private View mControlsView; private View mOverlayView; + // The boundary of magnification frame. + private final Rect mMagnificationFrameBoundary = new Rect(); private MoveMirrorRunnable mMoveMirrorRunnable = new MoveMirrorRunnable(); @@ -93,7 +95,7 @@ public class WindowMagnificationController implements View.OnClickListener, mContext = context; mHandler = handler; Display display = mContext.getDisplay(); - display.getSize(mDisplaySize); + display.getRealSize(mDisplaySize); mDisplayId = mContext.getDisplayId(); mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); @@ -114,6 +116,7 @@ public class WindowMagnificationController implements View.OnClickListener, return; } setInitialStartBounds(); + setMagnificationFrameBoundary(); createOverlayWindow(); } @@ -330,7 +333,7 @@ public class WindowMagnificationController implements View.OnClickListener, @Override public void onClick(View v) { setMoveOffset(v, mMoveFrameAmountShort); - moveMirrorFromControls(); + moveMirrorWindow(mMoveWindowOffset.x, mMoveWindowOffset.y); } @Override @@ -370,10 +373,8 @@ public class WindowMagnificationController implements View.OnClickListener, case MotionEvent.ACTION_MOVE: int xDiff = (int) (event.getRawX() - mLastDrag.x); int yDiff = (int) (event.getRawY() - mLastDrag.y); - mMagnificationFrame.offset(xDiff, yDiff); + moveMirrorWindow(xDiff, yDiff); mLastDrag.set(event.getRawX(), event.getRawY()); - modifyWindowMagnification(mTransaction); - mTransaction.apply(); return true; } return false; @@ -393,11 +394,11 @@ public class WindowMagnificationController implements View.OnClickListener, } } - private void moveMirrorFromControls() { - mMagnificationFrame.offset(mMoveWindowOffset.x, mMoveWindowOffset.y); - - modifyWindowMagnification(mTransaction); - mTransaction.apply(); + private void moveMirrorWindow(int xOffset, int yOffset) { + if (updateMagnificationFramePosition(xOffset, yOffset)) { + modifyWindowMagnification(mTransaction); + mTransaction.apply(); + } } /** @@ -414,6 +415,52 @@ public class WindowMagnificationController implements View.OnClickListener, return new Rect(left, top, right, bottom); } + private void setMagnificationFrameBoundary() { + // Calculates width and height for magnification frame could exceed out the screen. + // TODO : re-calculating again when scale is changed. + // The half width of magnification frame. + final int halfWidth = mMagnificationFrame.width() / 2; + // The half height of magnification frame. + final int halfHeight = mMagnificationFrame.height() / 2; + // The scaled half width of magnified region. + final int scaledWidth = (int) (halfWidth / mScale); + // The scaled half height of magnified region. + final int scaledHeight = (int) (halfHeight / mScale); + final int exceededWidth = halfWidth - scaledWidth; + final int exceededHeight = halfHeight - scaledHeight; + + mMagnificationFrameBoundary.set(-exceededWidth, -exceededHeight, + mDisplaySize.x + exceededWidth, mDisplaySize.y + exceededHeight); + } + + /** + * Calculates and sets the real position of magnification frame based on the magnified region + * should be limited by the region of the display. + */ + private boolean updateMagnificationFramePosition(int xOffset, int yOffset) { + mTmpRect.set(mMagnificationFrame); + mTmpRect.offset(xOffset, yOffset); + + if (mTmpRect.left < mMagnificationFrameBoundary.left) { + mTmpRect.offsetTo(mMagnificationFrameBoundary.left, mTmpRect.top); + } else if (mTmpRect.right > mMagnificationFrameBoundary.right) { + final int leftOffset = mMagnificationFrameBoundary.right - mMagnificationFrame.width(); + mTmpRect.offsetTo(leftOffset, mTmpRect.top); + } + + if (mTmpRect.top < mMagnificationFrameBoundary.top) { + mTmpRect.offsetTo(mTmpRect.left, mMagnificationFrameBoundary.top); + } else if (mTmpRect.bottom > mMagnificationFrameBoundary.bottom) { + final int topOffset = mMagnificationFrameBoundary.bottom - mMagnificationFrame.height(); + mTmpRect.offsetTo(mTmpRect.left, topOffset); + } + + if (!mTmpRect.equals(mMagnificationFrame)) { + mMagnificationFrame.set(mTmpRect); + return true; + } + return false; + } @Override public void surfaceCreated(SurfaceHolder holder) { createMirror(); @@ -431,7 +478,7 @@ public class WindowMagnificationController implements View.OnClickListener, @Override public void run() { if (mIsPressedDown) { - moveMirrorFromControls(); + moveMirrorWindow(mMoveWindowOffset.x, mMoveWindowOffset.y); mHandler.postDelayed(mMoveMirrorRunnable, 100); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index ac06f95cadf4..a26cce0bfc0c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -414,7 +414,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager.addNotificationEntryListener( new NotificationEntryListener() { @Override - public void onNotificationAdded(NotificationEntry entry) { + public void onPendingEntryAdded(NotificationEntry entry) { onEntryAdded(entry); } @@ -866,10 +866,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mOverflowCallback.run(); } - if (update.addedBubble != null) { - mStackView.addBubble(update.addedBubble); - } - // Collapsing? Do this first before remaining steps. if (update.expandedChanged && !update.expanded) { mStackView.setExpanded(false); @@ -916,6 +912,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } + if (update.addedBubble != null) { + mStackView.addBubble(update.addedBubble); + } + if (update.updatedBubble != null) { mStackView.updateBubble(update.updatedBubble); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 685bb9490a9a..6062a3d45be0 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -526,8 +526,13 @@ public class BubbleStackView extends FrameLayout { R.layout.bubble_expanded_view, this /* root */, false /* attachToRoot */); mOverflowExpandedView.setOverflow(true); - mInflater.inflate(R.layout.bubble_overflow_button, this); - mOverflowBtn = findViewById(R.id.bubble_overflow_button); + mOverflowBtn = (ImageView) mInflater.inflate(R.layout.bubble_overflow_button, + this /* root */, + false /* attachToRoot */); + + mBubbleContainer.addView(mOverflowBtn, 0, + new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); + mOverflowBtn.setOnClickListener(v -> { setSelectedBubble(null); }); @@ -541,11 +546,13 @@ public class BubbleStackView extends FrameLayout { ColorDrawable bg = new ColorDrawable(bgColor); AdaptiveIconDrawable adaptiveIcon = new AdaptiveIconDrawable(bg, fg); mOverflowBtn.setImageDrawable(adaptiveIcon); + mOverflowBtn.setVisibility(GONE); } void showExpandedViewContents(int displayId) { - if (mOverflowExpandedView.getVirtualDisplayId() == displayId) { + if (mOverflowExpandedView != null + && mOverflowExpandedView.getVirtualDisplayId() == displayId) { mOverflowExpandedView.setContentVisibility(true); } else if (mExpandedBubble != null && mExpandedBubble.getExpandedView().getVirtualDisplayId() == displayId) { @@ -714,7 +721,7 @@ public class BubbleStackView extends FrameLayout { private void updateSystemGestureExcludeRects() { // Exclude the region occupied by the first BubbleView in the stack Rect excludeZone = mSystemGestureExclusionRects.get(0); - if (mBubbleContainer.getChildCount() > 0) { + if (getBubbleCount() > 0) { View firstBubble = mBubbleContainer.getChildAt(0); excludeZone.set(firstBubble.getLeft(), firstBubble.getTop(), firstBubble.getRight(), firstBubble.getBottom()); @@ -775,7 +782,7 @@ public class BubbleStackView extends FrameLayout { Log.d(TAG, "addBubble: " + bubble); } - if (mBubbleContainer.getChildCount() == 0) { + if (getBubbleCount() == 0) { mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide(); } @@ -817,16 +824,13 @@ public class BubbleStackView extends FrameLayout { } if (mIsExpanded) { if (DEBUG_BUBBLE_STACK_VIEW) { - Log.d(TAG, "Expanded && overflow > 0. Show overflow button at"); - Log.d(TAG, "x: " + mExpandedAnimationController.getOverflowBtnLeft()); - Log.d(TAG, "y: " + mExpandedAnimationController.getExpandedY()); + Log.d(TAG, "Show overflow button."); } - mOverflowBtn.setX(mExpandedAnimationController.getOverflowBtnLeft()); - mOverflowBtn.setY(mExpandedAnimationController.getExpandedY()); mOverflowBtn.setVisibility(VISIBLE); - mExpandedAnimationController.setShowOverflowBtn(true); if (apply) { - mExpandedAnimationController.expandFromStack(null /* after */); + mExpandedAnimationController.expandFromStack(() -> { + updatePointerPosition(); + } /* after */); } } else { if (DEBUG_BUBBLE_STACK_VIEW) { @@ -947,7 +951,7 @@ public class BubbleStackView extends FrameLayout { if (mIsExpanded) { if (isIntersecting(mBubbleContainer, x, y)) { // Could be tapping or dragging a bubble while expanded - for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { + for (int i = 0; i < getBubbleCount(); i++) { BadgedImageView view = (BadgedImageView) mBubbleContainer.getChildAt(i); if (isIntersecting(view, x, y)) { return view; @@ -1103,7 +1107,7 @@ public class BubbleStackView extends FrameLayout { /** Return the BubbleView at the given index from the bubble container. */ public BadgedImageView getBubbleAt(int i) { - return mBubbleContainer.getChildCount() > i + return getBubbleCount() > i ? (BadgedImageView) mBubbleContainer.getChildAt(i) : null; } @@ -1567,7 +1571,7 @@ public class BubbleStackView extends FrameLayout { return; } if (!mIsExpanded) { - if (mBubbleContainer.getChildCount() > 0) { + if (getBubbleCount() > 0) { mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect); } // Increase the touch target size of the bubble @@ -1661,7 +1665,7 @@ public class BubbleStackView extends FrameLayout { /** Sets the appropriate Z-order and dot position for each bubble in the stack. */ private void updateBubbleZOrdersAndDotPosition(boolean animate) { - int bubbleCount = mBubbleContainer.getChildCount(); + int bubbleCount = getBubbleCount(); for (int i = 0; i < bubbleCount; i++) { BadgedImageView bv = (BadgedImageView) mBubbleContainer.getChildAt(i); bv.setZ((mMaxBubbles * mBubbleElevation) - i); @@ -1677,30 +1681,23 @@ public class BubbleStackView extends FrameLayout { if (expandedBubble == null) { return; } - int index = getBubbleIndex(expandedBubble); - if (index >= mMaxBubbles) { - // In between state, where extra bubble will be overflowed, and new bubble added - index = 0; - } float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index); float halfBubble = mBubbleSize / 2f; float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble; // Padding might be adjusted for insets, so get it directly from the view bubbleCenter -= mExpandedViewContainer.getPaddingLeft(); - - if (index >= mMaxBubbles) { - Bubble first = mBubbleData.getBubbles().get(0); - first.getExpandedView().setPointerPosition(bubbleCenter); - } else { - expandedBubble.getExpandedView().setPointerPosition(bubbleCenter); - } + expandedBubble.getExpandedView().setPointerPosition(bubbleCenter); } /** * @return the number of bubbles in the stack view. */ public int getBubbleCount() { + if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) { + // Subtract 1 for the overflow button which is always in the bubble container. + return mBubbleContainer.getChildCount() - 1; + } return mBubbleContainer.getChildCount(); } @@ -1797,7 +1794,7 @@ public class BubbleStackView extends FrameLayout { /** For debugging only */ List<Bubble> getBubblesOnScreen() { List<Bubble> bubbles = new ArrayList<>(); - for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { + for (int i = 0; i < getBubbleCount(); i++) { View child = mBubbleContainer.getChildAt(i); if (child instanceof BadgedImageView) { String key = ((BadgedImageView) child).getKey(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index 6d6969da8c8a..aa549dc23f9b 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -31,6 +31,7 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.systemui.Interpolators; import com.android.systemui.R; +import com.android.systemui.bubbles.BubbleExperimentConfig; import com.google.android.collect.Sets; @@ -67,13 +68,13 @@ public class ExpandedAnimationController private float mBubblePaddingTop; /** Size of each bubble. */ private float mBubbleSizePx; - /** Width of the overflow button. */ - private float mOverflowBtnWidth; + /** Space between bubbles in row above expanded view. */ + private float mSpaceBetweenBubbles; /** Height of the status bar. */ private float mStatusBarHeight; /** Size of display. */ private Point mDisplaySize; - /** Max number of bubbles shown in row above expanded view.*/ + /** Max number of bubbles shown in row above expanded view. */ private int mBubblesMaxRendered; /** What the current screen orientation is. */ private int mScreenOrientation; @@ -99,7 +100,6 @@ public class ExpandedAnimationController private boolean mSpringingBubbleToTouch = false; private int mExpandedViewPadding; - private boolean mShowOverflowBtn; public ExpandedAnimationController(Point displaySize, int expandedViewPadding, int orientation) { @@ -153,14 +153,6 @@ public class ExpandedAnimationController } } - public void setShowOverflowBtn(boolean showBtn) { - mShowOverflowBtn = showBtn; - } - - public boolean getShowOverflowBtn() { - return mShowOverflowBtn; - } - /** * Animates the bubbles along a curved path, either to expand them along the top or collapse * them back into a stack. @@ -369,10 +361,10 @@ public class ExpandedAnimationController } final WindowInsets insets = mLayout.getRootWindowInsets(); return mBubblePaddingTop + Math.max( - mStatusBarHeight, - insets.getDisplayCutout() != null - ? insets.getDisplayCutout().getSafeInsetTop() - : 0); + mStatusBarHeight, + insets.getDisplayCutout() != null + ? insets.getDisplayCutout().getSafeInsetTop() + : 0); } /** Description of current animation controller state. */ @@ -391,11 +383,15 @@ public class ExpandedAnimationController mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top); mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size); - mOverflowBtnWidth = mBubbleSizePx; mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered); + // Includes overflow button. + float totalGapWidth = getWidthForDisplayingBubbles() - (mExpandedViewPadding * 2) + - (mBubblesMaxRendered + 1) * mBubbleSizePx; + mSpaceBetweenBubbles = totalGapWidth / mBubblesMaxRendered; + // Ensure that all child views are at 1x scale, and visible, in case they were animating // in. mLayout.setVisibility(View.VISIBLE); @@ -506,18 +502,10 @@ public class ExpandedAnimationController * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { - final float bubbleFromRowLeft = index * (mBubbleSizePx + getSpaceBetweenBubbles()); + final float bubbleFromRowLeft = index * (mBubbleSizePx + mSpaceBetweenBubbles); return getRowLeft() + bubbleFromRowLeft; } - public float getOverflowBtnLeft() { - if (mLayout == null || mLayout.getChildCount() == 0) { - return 0; - } - return getBubbleLeft(mLayout.getChildCount() - 1) + mBubbleSizePx - + getSpaceBetweenBubbles(); - } - /** * When expanded, the bubbles are centered in the screen. In portrait, all available space is * used. In landscape we have too much space so the value is restricted. This method accounts @@ -539,7 +527,7 @@ public class ExpandedAnimationController * Determines the available screen width without the cutout. * * @param subtractStableInsets Whether or not stable insets should also be removed from the - * returned width. + * returned width. * @return the total screen width available accounting for cutouts and insets, * iff {@param includeStableInsets} is true. */ @@ -566,38 +554,13 @@ public class ExpandedAnimationController if (mLayout == null) { return 0; } - - int bubbleCount = mLayout.getChildCount(); - - final float totalBubbleWidth = bubbleCount * mBubbleSizePx; - final float totalGapWidth = (bubbleCount - 1) * getSpaceBetweenBubbles(); - float rowWidth = totalGapWidth + totalBubbleWidth; - if (mShowOverflowBtn) { - rowWidth += getSpaceBetweenBubbles(); - rowWidth += mOverflowBtnWidth; - } + float rowWidth = (mLayout.getChildCount() * mBubbleSizePx) + + ((mLayout.getChildCount() - 1) * mSpaceBetweenBubbles); // This display size we're using includes the size of the insets, we want the true // center of the display minus the notch here, which means we should include the // stable insets (e.g. status bar, nav bar) in this calculation. final float trueCenter = getAvailableScreenWidth(false /* subtractStableInsets */) / 2f; - final float halfRow = rowWidth / 2f; - final float rowLeft = trueCenter - halfRow; - return rowLeft; - } - - /** - * @return Space between bubbles in row above expanded view. - */ - private float getSpaceBetweenBubbles() { - final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx; - final float rowMargins = mExpandedViewPadding * 2; - float totalGapWidth = getWidthForDisplayingBubbles() - rowMargins - totalBubbleWidth; - if (mShowOverflowBtn) { - totalGapWidth -= mBubbleSizePx; - } - final int gapCount = mBubblesMaxRendered - 1; - final float gapWidth = totalGapWidth / gapCount; - return gapWidth; + return trueCenter - (rowWidth / 2f); } } 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 926fb6e75594..40a93d69fef4 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -29,6 +29,8 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.Space import android.widget.TextView import com.android.systemui.controls.controller.ControlsController @@ -144,10 +146,17 @@ class ControlsUiControllerImpl @Inject constructor ( inflater.inflate(R.layout.controls_no_favorites, parent, true) val textView = parent.requireViewById(R.id.controls_title) as TextView - textView.setOnClickListener { + textView.setOnClickListener(launchSelectorActivityListener(context)) + } + + private fun launchSelectorActivityListener(context: Context): (View) -> Unit { + return { _ -> + val closeDialog = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) + context.sendBroadcast(closeDialog) + val i = Intent() i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java)) - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(i) } } @@ -171,13 +180,12 @@ class ControlsUiControllerImpl @Inject constructor ( controlViewsById.put(it.controlId, cvh) } - val moreImageView = parent.requireViewById(R.id.controls_more) as View - moreImageView.setOnClickListener { - val i = Intent() - i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java)) - i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - context.startActivity(i) + if ((controlInfos.size % 2) == 1) { + lastRow.addView(Space(context), LinearLayout.LayoutParams(0, 0, 1f)) } + + val moreImageView = parent.requireViewById(R.id.controls_more) as View + moreImageView.setOnClickListener(launchSelectorActivityListener(context)) } override fun hide() { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java index e14581ffcde8..e8509b366c5b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java @@ -26,6 +26,7 @@ import com.android.systemui.InitController; import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.SystemUIFactory; import com.android.systemui.fragments.FragmentService; +import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; @@ -105,4 +106,9 @@ public interface SystemUIRootComponent { * Member injection into the supplied argument. */ void inject(ContentProvider contentProvider); + + /** + * Member injection into the supplied argument. + */ + void inject(KeyguardSliceProvider keyguardSliceProvider); } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java b/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java deleted file mode 100644 index d2fe39424875..000000000000 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeEvent.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.doze; - -import android.annotation.IntDef; - -import com.android.systemui.log.RichEvent; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * An event related to dozing. {@link DozeLog} stores and prints these events for debugging - * and triaging purposes. - */ -public class DozeEvent extends RichEvent { - /** - * Initializes a doze event - */ - public DozeEvent init(@EventType int type, String reason) { - super.init(DEBUG, type, reason); - return this; - } - - /** - * Event labels for each doze event - * Index corresponds to the integer associated with each {@link EventType} - */ - @Override - public String[] getEventLabels() { - final String[] events = new String[]{ - "PickupWakeup", - "PulseStart", - "PulseFinish", - "NotificationPulse", - "Dozing", - "Fling", - "EmergencyCall", - "KeyguardBouncerChanged", - "ScreenOn", - "ScreenOff", - "MissedTick", - "TimeTickScheduled", - "KeyguardVisibilityChanged", - "DozeStateChanged", - "WakeDisplay", - "ProximityResult", - "PulseDropped", - "PulseDisabledByProx", - "SensorTriggered" - }; - - if (events.length != TOTAL_EVENT_TYPES) { - throw new IllegalStateException("DozeEvent events.length should match TOTAL_EVENT_TYPES" - + " events.length=" + events.length - + " TOTAL_EVENT_LENGTH=" + TOTAL_EVENT_TYPES); - } - return events; - } - - /** - * Converts the reason (integer) to a user-readable string - */ - public static String reasonToString(@Reason int pulseReason) { - switch (pulseReason) { - case PULSE_REASON_INTENT: return "intent"; - case PULSE_REASON_NOTIFICATION: return "notification"; - case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion"; - case REASON_SENSOR_PICKUP: return "pickup"; - case REASON_SENSOR_DOUBLE_TAP: return "doubletap"; - case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress"; - case PULSE_REASON_DOCKING: return "docking"; - case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen"; - case REASON_SENSOR_WAKE_UP: return "wakeup"; - case REASON_SENSOR_TAP: return "tap"; - default: throw new IllegalArgumentException("invalid reason: " + pulseReason); - } - } - - @IntDef({PICKUP_WAKEUP, PULSE_START, PULSE_FINISH, NOTIFICATION_PULSE, DOZING, FLING, - EMERGENCY_CALL, KEYGUARD_BOUNCER_CHANGED, SCREEN_ON, SCREEN_OFF, MISSED_TICK, - TIME_TICK_SCHEDULED, KEYGUARD_VISIBILITY_CHANGE, DOZE_STATE_CHANGED, WAKE_DISPLAY, - PROXIMITY_RESULT, PULSE_DROPPED, PULSE_DISABLED_BY_PROX, SENSOR_TRIGGERED}) - /** - * Types of DozeEvents - */ - @Retention(RetentionPolicy.SOURCE) - public @interface EventType {} - public static final int PICKUP_WAKEUP = 0; - public static final int PULSE_START = 1; - public static final int PULSE_FINISH = 2; - public static final int NOTIFICATION_PULSE = 3; - public static final int DOZING = 4; - public static final int FLING = 5; - public static final int EMERGENCY_CALL = 6; - public static final int KEYGUARD_BOUNCER_CHANGED = 7; - public static final int SCREEN_ON = 8; - public static final int SCREEN_OFF = 9; - public static final int MISSED_TICK = 10; - public static final int TIME_TICK_SCHEDULED = 11; - public static final int KEYGUARD_VISIBILITY_CHANGE = 12; - public static final int DOZE_STATE_CHANGED = 13; - public static final int WAKE_DISPLAY = 14; - public static final int PROXIMITY_RESULT = 15; - public static final int PULSE_DROPPED = 16; - public static final int PULSE_DISABLED_BY_PROX = 17; - public static final int SENSOR_TRIGGERED = 18; - public static final int TOTAL_EVENT_TYPES = 19; - - public static final int TOTAL_REASONS = 10; - @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION, - PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP, - PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP, - PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP}) - @Retention(RetentionPolicy.SOURCE) - public @interface Reason {} - public static final int PULSE_REASON_NONE = -1; - public static final int PULSE_REASON_INTENT = 0; - public static final int PULSE_REASON_NOTIFICATION = 1; - public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; - public static final int REASON_SENSOR_PICKUP = 3; - public static final int REASON_SENSOR_DOUBLE_TAP = 4; - public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5; - public static final int PULSE_REASON_DOCKING = 6; - public static final int REASON_SENSOR_WAKE_UP = 7; - public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8; - public static final int REASON_SENSOR_TAP = 9; -} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index fe504216b166..8afdf1aeb023 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -16,15 +16,20 @@ package com.android.systemui.doze; +import android.annotation.IntDef; import android.util.TimeUtils; +import androidx.annotation.NonNull; + import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.DumpController; -import com.android.systemui.log.SysuiLog; +import com.android.systemui.Dumpable; +import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.Date; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; import javax.inject.Singleton; @@ -32,13 +37,11 @@ import javax.inject.Singleton; /** * Logs doze events for debugging and triaging purposes. Logs are dumped in bugreports or on demand: * adb shell dumpsys activity service com.android.systemui/.SystemUIService \ - * dependency DumpController DozeLog + * dependency DumpController DozeLog,DozeStats */ @Singleton -public class DozeLog extends SysuiLog<DozeEvent> { - private static final String TAG = "DozeLog"; - - private DozeEvent mRecycledEvent; +public class DozeLog implements Dumpable { + private final DozeLogger mLogger; private boolean mPulsing; private long mSince; @@ -51,8 +54,11 @@ public class DozeLog extends SysuiLog<DozeEvent> { private SummaryStats[][] mProxStats; // [reason][near/far] @Inject - public DozeLog(KeyguardUpdateMonitor keyguardUpdateMonitor, DumpController dumpController) { - super(dumpController, TAG, MAX_DOZE_DEBUG_LOGS, MAX_DOZE_LOGS); + public DozeLog( + KeyguardUpdateMonitor keyguardUpdateMonitor, + DumpController dumpController, + DozeLogger logger) { + mLogger = logger; mSince = System.currentTimeMillis(); mPickupPulseNearVibrationStats = new SummaryStats(); mPickupPulseNotNearVibrationStats = new SummaryStats(); @@ -60,8 +66,8 @@ public class DozeLog extends SysuiLog<DozeEvent> { mScreenOnPulsingStats = new SummaryStats(); mScreenOnNotPulsingStats = new SummaryStats(); mEmergencyCallStats = new SummaryStats(); - mProxStats = new SummaryStats[DozeEvent.TOTAL_REASONS][2]; - for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { + mProxStats = new SummaryStats[TOTAL_REASONS][2]; + for (int i = 0; i < TOTAL_REASONS; i++) { mProxStats[i][0] = new SummaryStats(); mProxStats[i][1] = new SummaryStats(); } @@ -69,42 +75,42 @@ public class DozeLog extends SysuiLog<DozeEvent> { if (keyguardUpdateMonitor != null) { keyguardUpdateMonitor.registerCallback(mKeyguardCallback); } + + dumpController.registerDumpable("DumpStats", this); } /** * Appends pickup wakeup event to the logs */ public void tracePickupWakeUp(boolean withinVibrationThreshold) { - log(DozeEvent.PICKUP_WAKEUP, "withinVibrationThreshold=" + withinVibrationThreshold); - if (mEnabled) { - (withinVibrationThreshold ? mPickupPulseNearVibrationStats - : mPickupPulseNotNearVibrationStats).append(); - } + mLogger.logPickupWakeup(withinVibrationThreshold); + (withinVibrationThreshold ? mPickupPulseNearVibrationStats + : mPickupPulseNotNearVibrationStats).append(); } /** * Appends pulse started event to the logs. * @param reason why the pulse started */ - public void tracePulseStart(@DozeEvent.Reason int reason) { - log(DozeEvent.PULSE_START, DozeEvent.reasonToString(reason)); - if (mEnabled) mPulsing = true; + public void tracePulseStart(@Reason int reason) { + mLogger.logPulseStart(reason); + mPulsing = true; } /** * Appends pulse finished event to the logs */ public void tracePulseFinish() { - log(DozeEvent.PULSE_FINISH); - if (mEnabled) mPulsing = false; + mLogger.logPulseFinish(); + mPulsing = false; } /** * Appends pulse event to the logs */ public void traceNotificationPulse() { - log(DozeEvent.NOTIFICATION_PULSE); - if (mEnabled) mNotificationPulseStats.append(); + mLogger.logNotificationPulse(); + mNotificationPulseStats.append(); } /** @@ -112,8 +118,8 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param dozing true if dozing, else false */ public void traceDozing(boolean dozing) { - log(DozeEvent.DOZING, "dozing=" + dozing); - if (mEnabled) mPulsing = false; + mLogger.logDozing(dozing); + mPulsing = false; } /** @@ -121,18 +127,15 @@ public class DozeLog extends SysuiLog<DozeEvent> { */ public void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded, boolean screenOnFromTouch) { - log(DozeEvent.FLING, "expand=" + expand - + " aboveThreshold=" + aboveThreshold - + " thresholdNeeded=" + thresholdNeeded - + " screenOnFromTouch=" + screenOnFromTouch); + mLogger.logFling(expand, aboveThreshold, thresholdNeeded, screenOnFromTouch); } /** * Appends emergency call event to the logs */ public void traceEmergencyCall() { - log(DozeEvent.EMERGENCY_CALL); - if (mEnabled) mEmergencyCallStats.append(); + mLogger.logEmergencyCall(); + mEmergencyCallStats.append(); } /** @@ -140,18 +143,16 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param showing true if the keyguard bouncer is showing, else false */ public void traceKeyguardBouncerChanged(boolean showing) { - log(DozeEvent.KEYGUARD_BOUNCER_CHANGED, "showing=" + showing); + mLogger.logKeyguardBouncerChanged(showing); } /** * Appends screen-on event to the logs */ public void traceScreenOn() { - log(DozeEvent.SCREEN_ON, "pulsing=" + mPulsing); - if (mEnabled) { - (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append(); - mPulsing = false; - } + mLogger.logScreenOn(mPulsing); + (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append(); + mPulsing = false; } /** @@ -159,7 +160,7 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param why reason the screen is off */ public void traceScreenOff(int why) { - log(DozeEvent.SCREEN_OFF, "why=" + why); + mLogger.logScreenOff(why); } /** @@ -167,7 +168,7 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param delay of the missed tick */ public void traceMissedTick(String delay) { - log(DozeEvent.MISSED_TICK, "delay=" + delay); + mLogger.logMissedTick(delay); } /** @@ -176,9 +177,7 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param triggerAt time tick trigger at */ public void traceTimeTickScheduled(long when, long triggerAt) { - log(DozeEvent.TIME_TICK_SCHEDULED, - "scheduledAt=" + DATE_FORMAT.format(new Date(when)) - + " triggerAt=" + DATE_FORMAT.format(new Date(triggerAt))); + mLogger.logTimeTickScheduled(when, triggerAt); } /** @@ -186,8 +185,8 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param showing whether the keyguard is now showing */ public void traceKeyguard(boolean showing) { - log(DozeEvent.KEYGUARD_VISIBILITY_CHANGE, "showing=" + showing); - if (mEnabled && !showing) mPulsing = false; + mLogger.logKeyguardVisibilityChange(showing); + if (!showing) mPulsing = false; } /** @@ -195,7 +194,7 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param state new DozeMachine state */ public void traceState(DozeMachine.State state) { - log(DozeEvent.DOZE_STATE_CHANGED, state.name()); + mLogger.logDozeStateChanged(state); } /** @@ -203,31 +202,22 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param wake if we're waking up or sleeping. */ public void traceWakeDisplay(boolean wake) { - log(DozeEvent.WAKE_DISPLAY, "wake=" + wake); + mLogger.logWakeDisplay(wake); } /** * Appends proximity result event to the logs * @param near true if near, else false - * @param millis * @param reason why proximity result was triggered */ - public void traceProximityResult(boolean near, long millis, @DozeEvent.Reason int reason) { - log(DozeEvent.PROXIMITY_RESULT, - " reason=" + DozeEvent.reasonToString(reason) - + " near=" + near - + " millis=" + millis); - if (mEnabled) mProxStats[reason][near ? 0 : 1].append(); + public void traceProximityResult(boolean near, long millis, @Reason int reason) { + mLogger.logProximityResult(near, millis, reason); + mProxStats[reason][near ? 0 : 1].append(); } - /** - * Prints doze log timeline and consolidated stats - * @param pw - */ - public void dump(PrintWriter pw) { + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { synchronized (DozeLog.class) { - super.dump(null, pw, null); // prints timeline - pw.print(" Doze summary stats (for "); TimeUtils.formatDuration(System.currentTimeMillis() - mSince, pw); pw.println("):"); @@ -237,32 +227,19 @@ public class DozeLog extends SysuiLog<DozeEvent> { mScreenOnPulsingStats.dump(pw, "Screen on (pulsing)"); mScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)"); mEmergencyCallStats.dump(pw, "Emergency call"); - for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { - final String reason = DozeEvent.reasonToString(i); + for (int i = 0; i < TOTAL_REASONS; i++) { + final String reason = reasonToString(i); mProxStats[i][0].dump(pw, "Proximity near (" + reason + ")"); mProxStats[i][1].dump(pw, "Proximity far (" + reason + ")"); } } } - private void log(@DozeEvent.EventType int eventType) { - log(eventType, ""); - } - - private void log(@DozeEvent.EventType int eventType, String msg) { - if (mRecycledEvent != null) { - mRecycledEvent = log(mRecycledEvent.init(eventType, msg)); - } else { - mRecycledEvent = log(new DozeEvent().init(eventType, msg)); - } - } - /** * Appends pulse dropped event to logs */ public void tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked) { - log(DozeEvent.PULSE_DROPPED, "pulsePending=" + pulsePending + " state=" - + state.name() + " blocked=" + blocked); + mLogger.logPulseDropped(pulsePending, state, blocked); } /** @@ -270,7 +247,7 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param reason why the pulse was dropped */ public void tracePulseDropped(String reason) { - log(DozeEvent.PULSE_DROPPED, "why=" + reason); + mLogger.logPulseDropped(reason); } /** @@ -278,15 +255,15 @@ public class DozeLog extends SysuiLog<DozeEvent> { * @param disabled */ public void tracePulseTouchDisabledByProx(boolean disabled) { - log(DozeEvent.PULSE_DISABLED_BY_PROX, "disabled=" + disabled); + mLogger.logPulseTouchDisabledByProx(disabled); } /** * Appends sensor triggered event to logs * @param reason why the sensor was triggered */ - public void traceSensor(@DozeEvent.Reason int reason) { - log(DozeEvent.SENSOR_TRIGGERED, "type=" + DozeEvent.reasonToString(reason)); + public void traceSensor(@Reason int reason) { + mLogger.logSensorTriggered(reason); } private class SummaryStats { @@ -339,6 +316,42 @@ public class DozeLog extends SysuiLog<DozeEvent> { } }; - private static final int MAX_DOZE_DEBUG_LOGS = 400; - private static final int MAX_DOZE_LOGS = 50; + /** + * Converts the reason (integer) to a user-readable string + */ + public static String reasonToString(@Reason int pulseReason) { + switch (pulseReason) { + case PULSE_REASON_INTENT: return "intent"; + case PULSE_REASON_NOTIFICATION: return "notification"; + case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion"; + case REASON_SENSOR_PICKUP: return "pickup"; + case REASON_SENSOR_DOUBLE_TAP: return "doubletap"; + case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress"; + case PULSE_REASON_DOCKING: return "docking"; + case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen"; + case REASON_SENSOR_WAKE_UP: return "wakeup"; + case REASON_SENSOR_TAP: return "tap"; + default: throw new IllegalArgumentException("invalid reason: " + pulseReason); + } + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION, + PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP, + PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP, + PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP}) + public @interface Reason {} + public static final int PULSE_REASON_NONE = -1; + public static final int PULSE_REASON_INTENT = 0; + public static final int PULSE_REASON_NOTIFICATION = 1; + public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; + public static final int REASON_SENSOR_PICKUP = 3; + public static final int REASON_SENSOR_DOUBLE_TAP = 4; + public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5; + public static final int PULSE_REASON_DOCKING = 6; + public static final int REASON_SENSOR_WAKE_UP = 7; + public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8; + public static final int REASON_SENSOR_TAP = 9; + + public static final int TOTAL_REASONS = 10; } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt new file mode 100644 index 000000000000..42decd592071 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -0,0 +1,201 @@ +/* + * 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.doze + +import com.android.systemui.doze.DozeLog.Reason +import com.android.systemui.doze.DozeLog.reasonToString +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogLevel.DEBUG +import com.android.systemui.log.LogLevel.ERROR +import com.android.systemui.log.LogLevel.INFO +import com.android.systemui.log.dagger.DozeLog +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import javax.inject.Inject + +/** Interface for logging messages to the [DozeLog]. */ +class DozeLogger @Inject constructor( + @DozeLog private val buffer: LogBuffer +) { + fun logPickupWakeup(isWithinVibrationThreshold: Boolean) { + buffer.log(TAG, DEBUG, { + bool1 = isWithinVibrationThreshold + }, { + "PickupWakeup withinVibrationThreshold=$bool1" + }) + } + + fun logPulseStart(@Reason reason: Int) { + buffer.log(TAG, INFO, { + int1 = reason + }, { + "Pulse start, reason=${reasonToString(int1)}" + }) + } + + fun logPulseFinish() { + buffer.log(TAG, INFO, {}, { "Pulse finish" }) + } + + fun logNotificationPulse() { + buffer.log(TAG, INFO, {}, { "Notification pulse" }) + } + + fun logDozing(isDozing: Boolean) { + buffer.log(TAG, INFO, { + bool1 = isDozing + }, { + "Dozing=$bool1" + }) + } + + fun logFling( + expand: Boolean, + aboveThreshold: Boolean, + thresholdNeeded: Boolean, + screenOnFromTouch: Boolean + ) { + buffer.log(TAG, DEBUG, { + bool1 = expand + bool2 = aboveThreshold + bool3 = thresholdNeeded + bool4 = screenOnFromTouch + }, { + "Fling expand=$bool1 aboveThreshold=$bool2 thresholdNeeded=$bool3 " + + "screenOnFromTouch=$bool4" + }) + } + + fun logEmergencyCall() { + buffer.log(TAG, INFO, {}, { "Emergency call" }) + } + + fun logKeyguardBouncerChanged(isShowing: Boolean) { + buffer.log(TAG, INFO, { + bool1 = isShowing + }, { + "Keyguard bouncer changed, showing=$bool1" + }) + } + + fun logScreenOn(isPulsing: Boolean) { + buffer.log(TAG, INFO, { + bool1 = isPulsing + }, { + "Screen on, pulsing=$bool1" + }) + } + + fun logScreenOff(why: Int) { + buffer.log(TAG, INFO, { + int1 = why + }, { + "Screen off, why=$int1" + }) + } + + fun logMissedTick(delay: String) { + buffer.log(TAG, ERROR, { + str1 = delay + }, { + "Missed AOD time tick by $str1" + }) + } + + fun logTimeTickScheduled(whenAt: Long, triggerAt: Long) { + buffer.log(TAG, DEBUG, { + long1 = whenAt + long2 = triggerAt + }, { + "Time tick scheduledAt=${DATE_FORMAT.format(Date(long1))} " + + "triggerAt=${DATE_FORMAT.format(Date(long2))}" + }) + } + + fun logKeyguardVisibilityChange(isShowing: Boolean) { + buffer.log(TAG, INFO, { + bool1 = isShowing + }, { + "Keyguard visibility change, isShowing=$bool1" + }) + } + + fun logDozeStateChanged(state: DozeMachine.State) { + buffer.log(TAG, INFO, { + str1 = state.name + }, { + "Doze state changed to $str1" + }) + } + + fun logWakeDisplay(isAwake: Boolean) { + buffer.log(TAG, DEBUG, { + bool1 = isAwake + }, { + "Display wakefulness changed, isAwake=$bool1" + }) + } + + fun logProximityResult(isNear: Boolean, millis: Long, @Reason reason: Int) { + buffer.log(TAG, DEBUG, { + bool1 = isNear + long1 = millis + int1 = reason + }, { + "Proximity result reason=${reasonToString(int1)} near=$bool1 millis=$long1" + }) + } + + fun logPulseDropped(pulsePending: Boolean, state: DozeMachine.State, blocked: Boolean) { + buffer.log(TAG, INFO, { + bool1 = pulsePending + str1 = state.name + bool2 = blocked + }, { + "Pulse dropped, pulsePending=$bool1 state=$str1 blocked=$bool2" + }) + } + + fun logPulseDropped(reason: String) { + buffer.log(TAG, INFO, { + str1 = reason + }, { + "Pulse dropped, why=$str1" + }) + } + + fun logPulseTouchDisabledByProx(disabled: Boolean) { + buffer.log(TAG, DEBUG, { + bool1 = disabled + }, { + "Pulse touch modified by prox, disabled=$bool1" + }) + } + + fun logSensorTriggered(@Reason reason: Int) { + buffer.log(TAG, DEBUG, { + int1 = reason + }, { + "Sensor triggered, type=${reasonToString(int1)}" + }) + } +} + +private const val TAG = "DozeLog" + +val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index 40603ab24c1e..03c25eee4f6f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -169,7 +169,7 @@ public class DozeMachine { @MainThread public void requestState(State requestedState) { Preconditions.checkArgument(requestedState != State.DOZE_REQUEST_PULSE); - requestState(requestedState, DozeEvent.PULSE_REASON_NONE); + requestState(requestedState, DozeLog.PULSE_REASON_NONE); } @MainThread @@ -271,7 +271,7 @@ public class DozeMachine { if (newState == State.DOZE_REQUEST_PULSE) { mPulseReason = pulseReason; } else if (oldState == State.DOZE_PULSE_DONE) { - mPulseReason = DozeEvent.PULSE_REASON_NONE; + mPulseReason = DozeLog.PULSE_REASON_NONE; } } @@ -368,7 +368,7 @@ public class DozeMachine { nextState = State.DOZE; } - transitionTo(nextState, DozeEvent.PULSE_REASON_NONE); + transitionTo(nextState, DozeLog.PULSE_REASON_NONE); break; default: break; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index d008e665d171..44e5d3de5ca7 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -97,14 +97,14 @@ public class DozeSensors { mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION), null /* setting */, dozeParameters.getPulseOnSigMotion(), - DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */, + DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */, false /* touchscreen */, dozeLog), mPickupSensor = new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PICK_UP_GESTURE, true /* settingDef */, config.dozePickupSensorAvailable(), - DozeEvent.REASON_SENSOR_PICKUP, false /* touchCoords */, + DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */, false /* touchscreen */, false /* ignoresSetting */, dozeLog), @@ -112,7 +112,7 @@ public class DozeSensors { findSensorWithType(config.doubleTapSensorType()), Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, true /* configured */, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, + DozeLog.REASON_SENSOR_DOUBLE_TAP, dozeParameters.doubleTapReportsTouchCoordinates(), true /* touchscreen */, dozeLog), @@ -120,7 +120,7 @@ public class DozeSensors { findSensorWithType(config.tapSensorType()), Settings.Secure.DOZE_TAP_SCREEN_GESTURE, true /* configured */, - DozeEvent.REASON_SENSOR_TAP, + DozeLog.REASON_SENSOR_TAP, false /* reports touch coordinates */, true /* touchscreen */, dozeLog), @@ -129,7 +129,7 @@ public class DozeSensors { Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, false /* settingDef */, true /* configured */, - DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, + DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, true /* reports touch coordinates */, true /* touchscreen */, dozeLog), @@ -137,7 +137,7 @@ public class DozeSensors { new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY), Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, mConfig.wakeScreenGestureAvailable() && alwaysOn, - DozeEvent.REASON_SENSOR_WAKE_UP, + DozeLog.REASON_SENSOR_WAKE_UP, false /* reports touch coordinates */, false /* touchscreen */, dozeLog), @@ -145,7 +145,7 @@ public class DozeSensors { new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN), Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, mConfig.wakeScreenGestureAvailable(), - DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, + DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, false /* reports touch coordinates */, false /* touchscreen */, mConfig.getWakeLockScreenDebounce(), @@ -525,7 +525,7 @@ public class DozeSensors { /** * Called when a sensor requests a pulse - * @param pulseReason Requesting sensor, e.g. {@link DozeEvent#REASON_SENSOR_PICKUP} + * @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP} * @param screenX the location on the screen where the sensor fired or -1 * if the sensor doesn't support reporting screen locations. * @param screenY the location on the screen where the sensor fired or -1 diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 722dc038f853..b9c056df89a1 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -127,7 +127,7 @@ public class DozeTriggers implements DozeMachine.Part { mDozeLog.tracePulseDropped("pulseOnNotificationsDisabled"); return; } - requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */, + requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */, onPulseSuppressedListener); mDozeLog.traceNotificationPulse(); } @@ -163,12 +163,12 @@ public class DozeTriggers implements DozeMachine.Part { @VisibleForTesting void onSensor(int pulseReason, float screenX, float screenY, float[] rawValues) { - boolean isDoubleTap = pulseReason == DozeEvent.REASON_SENSOR_DOUBLE_TAP; - boolean isTap = pulseReason == DozeEvent.REASON_SENSOR_TAP; - boolean isPickup = pulseReason == DozeEvent.REASON_SENSOR_PICKUP; - boolean isLongPress = pulseReason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS; - boolean isWakeDisplay = pulseReason == DozeEvent.REASON_SENSOR_WAKE_UP; - boolean isWakeLockScreen = pulseReason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN; + boolean isDoubleTap = pulseReason == DozeLog.REASON_SENSOR_DOUBLE_TAP; + boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP; + boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP; + boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS; + boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP; + boolean isWakeLockScreen = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN; boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0; if (isWakeDisplay) { @@ -281,9 +281,9 @@ public class DozeTriggers implements DozeMachine.Part { // Logs AOD open due to sensor wake up. mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) .setType(MetricsEvent.TYPE_OPEN) - .setSubtype(DozeEvent.REASON_SENSOR_WAKE_UP)); + .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP)); } - }, true /* alreadyPerformedProxCheck */, DozeEvent.REASON_SENSOR_WAKE_UP); + }, true /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP); } else { boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); @@ -292,7 +292,7 @@ public class DozeTriggers implements DozeMachine.Part { // Logs AOD close due to sensor wake up. mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) .setType(MetricsEvent.TYPE_CLOSE) - .setSubtype(DozeEvent.REASON_SENSOR_WAKE_UP)); + .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP)); } } } @@ -361,7 +361,7 @@ public class DozeTriggers implements DozeMachine.Part { // When already pulsing we're allowed to show the wallpaper directly without // requesting a new pulse. if (mMachine.getState() == DozeMachine.State.DOZE_PULSING - && reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + && reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT); return; } @@ -426,7 +426,7 @@ public class DozeTriggers implements DozeMachine.Part { public void onReceive(Context context, Intent intent) { if (PULSE_ACTION.equals(intent.getAction())) { if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent"); - requestPulse(DozeEvent.PULSE_REASON_INTENT, false, /* performedProxCheck */ + requestPulse(DozeLog.PULSE_REASON_INTENT, false, /* performedProxCheck */ null /* onPulseSupressedListener */); } if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index a6aa90916c25..1c056215f1cb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -100,7 +100,7 @@ public class DozeUi implements DozeMachine.Part { public void onPulseStarted() { try { mMachine.requestState( - reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN + reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN ? DozeMachine.State.DOZE_PULSING_BRIGHT : DozeMachine.State.DOZE_PULSING); } catch (IllegalStateException e) { diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 80d776a59235..f33c931479ba 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -40,6 +40,7 @@ import android.content.IntentFilter; import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.ConnectivityManager; @@ -100,7 +101,6 @@ import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.statusbar.BlurUtils; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; -import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.EmergencyDialerConstants; @@ -459,12 +459,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mKeyguardManager.isDeviceLocked()) : null; - boolean showControls = !mKeyguardManager.isDeviceLocked() && isControlsEnabled(mContext); - ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController, mBlurUtils, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - showControls ? mControlsUiController : null); + shouldShowControls() ? mControlsUiController : null); dialog.setCanceledOnTouchOutside(false); // Handled by the custom class. dialog.setKeyguardShowing(mKeyguardShowing); @@ -538,7 +536,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, @Override public boolean shouldBeSeparated() { - return !isControlsEnabled(mContext); + return !shouldShowControls(); } @Override @@ -1135,7 +1133,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, * A single press action maintains no state, just responds to a press * and takes an action. */ - private static abstract class SinglePressAction implements Action { + + private abstract class SinglePressAction implements Action { private final int mIconResId; private final Drawable mIcon; private final int mMessageResId; @@ -1174,7 +1173,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } protected int getActionLayoutId(Context context) { - if (isControlsEnabled(context)) { + if (shouldShowControls()) { return com.android.systemui.R.layout.global_actions_grid_item_v2; } return com.android.systemui.R.layout.global_actions_grid_item; @@ -1640,8 +1639,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); panelContainer.addView(mPanelController.getPanelContent(), panelParams); - mBackgroundDrawable = mPanelController.getBackgroundDrawable(); - mScrimAlpha = 1f; } } @@ -1669,7 +1666,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } if (mBackgroundDrawable == null) { mBackgroundDrawable = new ScrimDrawable(); - mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA; + mScrimAlpha = 0.8f; } getWindow().setBackgroundDrawable(mBackgroundDrawable); } @@ -1728,7 +1725,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, if (!(mBackgroundDrawable instanceof ScrimDrawable)) { return; } - ((ScrimDrawable) mBackgroundDrawable).setColor(colors.getMainColor(), animate); + ((ScrimDrawable) mBackgroundDrawable).setColor(Color.BLACK, animate); View decorView = getWindow().getDecorView(); if (colors.supportsDarkText()) { decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR | @@ -1900,8 +1897,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, return true; } - private static boolean isControlsEnabled(Context context) { - return Settings.Secure.getInt( - context.getContentResolver(), "systemui.controls_available", 0) == 1; + private boolean shouldShowControls() { + return isCurrentUserOwner() + && !mKeyguardManager.isDeviceLocked() + && Settings.Secure.getInt(mContext.getContentResolver(), + "systemui.controls_available", 0) == 1; } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index e66a9fadb937..2cc3d9e22a7d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -52,13 +52,13 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SystemUIAppComponentFactory; +import com.android.systemui.SystemUIFactory; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.NextAlarmController; -import com.android.systemui.statusbar.policy.NextAlarmControllerImpl; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.wakelock.SettableWakeLock; import com.android.systemui.util.wakelock.WakeLock; @@ -68,6 +68,8 @@ import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import javax.inject.Inject; + /** * Simple Slice provider that shows the current date. */ @@ -108,26 +110,31 @@ public class KeyguardSliceProvider extends SliceProvider implements private final Handler mHandler; private final Handler mMediaHandler; private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm; - private DozeParameters mDozeParameters; + @Inject + public DozeParameters mDozeParameters; @VisibleForTesting protected SettableWakeLock mMediaWakeLock; - @VisibleForTesting - protected ZenModeController mZenModeController; + @Inject + public ZenModeController mZenModeController; private String mDatePattern; private DateFormat mDateFormat; private String mLastText; private boolean mRegistered; private String mNextAlarm; - private NextAlarmController mNextAlarmController; - @VisibleForTesting - protected AlarmManager mAlarmManager; - @VisibleForTesting - protected ContentResolver mContentResolver; + @Inject + public NextAlarmController mNextAlarmController; + @Inject + public AlarmManager mAlarmManager; + @Inject + public ContentResolver mContentResolver; private AlarmManager.AlarmClockInfo mNextAlarmInfo; private PendingIntent mPendingIntent; - protected NotificationMediaManager mMediaManager; - private StatusBarStateController mStatusBarStateController; - private KeyguardBypassController mKeyguardBypassController; + @Inject + public NotificationMediaManager mMediaManager; + @Inject + public StatusBarStateController mStatusBarStateController; + @Inject + public KeyguardBypassController mKeyguardBypassController; private CharSequence mMediaTitle; private CharSequence mMediaArtist; protected boolean mDozing; @@ -188,26 +195,6 @@ public class KeyguardSliceProvider extends SliceProvider implements mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI); } - /** - * Initialize dependencies that don't exist during {@link android.content.ContentProvider} - * instantiation. - * - * @param mediaManager {@link NotificationMediaManager} singleton. - * @param statusBarStateController {@link StatusBarStateController} singleton. - */ - public void initDependencies( - NotificationMediaManager mediaManager, - StatusBarStateController statusBarStateController, - KeyguardBypassController keyguardBypassController, - DozeParameters dozeParameters) { - mMediaManager = mediaManager; - mMediaManager.addCallback(this); - mStatusBarStateController = statusBarStateController; - mStatusBarStateController.addCallback(this); - mKeyguardBypassController = keyguardBypassController; - mDozeParameters = dozeParameters; - } - @AnyThread @Override public Slice onBindSlice(Uri sliceUri) { @@ -310,25 +297,19 @@ public class KeyguardSliceProvider extends SliceProvider implements @Override public boolean onCreateSliceProvider() { - if (mContextAvailableCallback != null) { - mContextAvailableCallback.onContextAvailable(getContext()); - } + mContextAvailableCallback.onContextAvailable(getContext()); + inject(); synchronized (KeyguardSliceProvider.sInstanceLock) { KeyguardSliceProvider oldInstance = KeyguardSliceProvider.sInstance; if (oldInstance != null) { oldInstance.onDestroy(); } - - mAlarmManager = getContext().getSystemService(AlarmManager.class); - mContentResolver = getContext().getContentResolver(); - mNextAlarmController = new NextAlarmControllerImpl(getContext()); - mNextAlarmController.addCallback(this); - mZenModeController = Dependency.get(ZenModeController.class); - mZenModeController.addCallback(this); mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern); mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0); - mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), - "media"); + mMediaManager.addCallback(this); + mStatusBarStateController.addCallback(this); + mNextAlarmController.addCallback(this); + mZenModeController.addCallback(this); KeyguardSliceProvider.sInstance = this; registerClockUpdate(); updateClockLocked(); @@ -337,6 +318,13 @@ public class KeyguardSliceProvider extends SliceProvider implements } @VisibleForTesting + protected void inject() { + SystemUIFactory.getInstance().getRootComponent().inject(this); + mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), + "media"); + } + + @VisibleForTesting protected void onDestroy() { synchronized (KeyguardSliceProvider.sInstanceLock) { mNextAlarmController.removeCallback(this); diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt index d971ac58fb0b..2a0a2aa6fb38 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt @@ -43,5 +43,10 @@ interface LogMessage { var int1: Int var int2: Int var long1: Long + var long2: Long var double1: Double + var bool1: Boolean + var bool2: Boolean + var bool3: Boolean + var bool4: Boolean } diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt index 32334bc382e1..d33ac4b4a80b 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt @@ -30,7 +30,12 @@ data class LogMessageImpl( override var int1: Int, override var int2: Int, override var long1: Long, - override var double1: Double + override var long2: Long, + override var double1: Double, + override var bool1: Boolean, + override var bool2: Boolean, + override var bool3: Boolean, + override var bool4: Boolean ) : LogMessage { fun reset( @@ -49,7 +54,12 @@ data class LogMessageImpl( int1 = 0 int2 = 0 long1 = 0 + long2 = 0 double1 = 0.0 + bool1 = false + bool2 = false + bool3 = false + bool4 = false } companion object Factory { @@ -65,7 +75,12 @@ data class LogMessageImpl( 0, 0, 0, - 0.0) + 0, + 0.0, + false, + false, + false, + false) } } } diff --git a/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java index 4e15668f6a34..9ee3e6765e4a 100644 --- a/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java +++ b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java @@ -48,7 +48,7 @@ import java.util.Locale; */ public class SysuiLog<E extends Event> implements Dumpable { public static final SimpleDateFormat DATE_FORMAT = - new SimpleDateFormat("MM-dd HH:mm:ss", Locale.US); + new SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US); protected final Object mDataLock = new Object(); private final String mId; diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index b1990beb9f57..e119beff3c6f 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -42,7 +42,7 @@ public class LogModule { @Singleton @DozeLog public static LogBuffer provideDozeLogBuffer( - LogcatEchoTrackerDebug bufferFilter, + LogcatEchoTracker bufferFilter, DumpController dumpController) { LogBuffer buffer = new LogBuffer("DozeLog", 100, 10, bufferFilter); buffer.attach(dumpController); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 35b8312ba25c..0fd74547334b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -31,7 +31,6 @@ import android.metrics.LogMaker; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.provider.Settings; import android.service.notification.StatusBarNotification; import android.service.quicksettings.Tile; import android.util.AttributeSet; @@ -62,7 +61,6 @@ import com.android.systemui.qs.external.CustomTile; import com.android.systemui.settings.BrightnessController; import com.android.systemui.settings.ToggleSliderView; import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.statusbar.phone.NPVPluginManager; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener; import com.android.systemui.tuner.TunerService; @@ -120,7 +118,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne private FrameLayout mPluginFrame; private final PluginManager mPluginManager; - private NPVPluginManager mNPVPluginManager; private final LocalMediaManager.DeviceCallback mDeviceCallback = new LocalMediaManager.DeviceCallback() { @@ -201,14 +198,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne findViewById(R.id.brightness_slider), broadcastDispatcher); mDumpController = dumpController; mPluginManager = pluginManager; - if (mPluginManager != null && Settings.System.getInt( - mContext.getContentResolver(), "npv_plugin_flag", 0) == 2) { - mPluginFrame = (FrameLayout) LayoutInflater.from(mContext).inflate( - R.layout.status_bar_expanded_plugin_frame, this, false); - addView(mPluginFrame); - mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager); - } - } /** @@ -556,7 +545,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne if (mListening) { refreshAllTiles(); } - if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening); } public void setListening(boolean listening, boolean expanded) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index b682cb09b598..3fcd1c19370f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -31,7 +31,6 @@ import android.text.SpannableStringBuilder; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.util.Log; -import android.util.StatsLog; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; @@ -41,6 +40,7 @@ import android.view.Window; import android.widget.ImageView; import android.widget.TextView; +import com.android.internal.util.FrameworkStatsLog; import com.android.systemui.Dependency; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; @@ -122,7 +122,7 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic private void handleClick() { showDeviceMonitoringDialog(); DevicePolicyEventLogger - .createEvent(StatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED) + .createEvent(FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED) .write(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index 557c64b7dfb9..411980b399bd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -191,7 +191,6 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener mTile.setLabel(tile.getLabel()); mTile.setSubtitle(tile.getSubtitle()); mTile.setContentDescription(tile.getContentDescription()); - mTile.setStateDescription(tile.getStateDescription()); mTile.setState(tile.getState()); } @@ -346,12 +345,6 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener state.contentDescription = state.label; } - if (mTile.getStateDescription() != null) { - state.stateDescription = mTile.getStateDescription(); - } else { - state.stateDescription = null; - } - if (state instanceof BooleanState) { state.expandedAccessibilityClassName = Switch.class.getName(); ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index 2b53727f237e..554672d88052 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -16,7 +16,6 @@ package com.android.systemui.qs.tileimpl; import android.content.Context; import android.os.Build; -import android.provider.Settings; import android.util.Log; import android.view.ContextThemeWrapper; @@ -33,7 +32,6 @@ import com.android.systemui.qs.tiles.BluetoothTile; import com.android.systemui.qs.tiles.CastTile; import com.android.systemui.qs.tiles.CellularTile; import com.android.systemui.qs.tiles.ColorInversionTile; -import com.android.systemui.qs.tiles.ControlsTile; import com.android.systemui.qs.tiles.DataSaverTile; import com.android.systemui.qs.tiles.DndTile; import com.android.systemui.qs.tiles.FlashlightTile; @@ -60,7 +58,6 @@ public class QSFactoryImpl implements QSFactory { private final Provider<WifiTile> mWifiTileProvider; private final Provider<BluetoothTile> mBluetoothTileProvider; - private final Provider<ControlsTile> mControlsTileProvider; private final Provider<CellularTile> mCellularTileProvider; private final Provider<DndTile> mDndTileProvider; private final Provider<ColorInversionTile> mColorInversionTileProvider; @@ -85,7 +82,6 @@ public class QSFactoryImpl implements QSFactory { @Inject public QSFactoryImpl(Provider<WifiTile> wifiTileProvider, Provider<BluetoothTile> bluetoothTileProvider, - Provider<ControlsTile> controlsTileProvider, Provider<CellularTile> cellularTileProvider, Provider<DndTile> dndTileProvider, Provider<ColorInversionTile> colorInversionTileProvider, @@ -106,7 +102,6 @@ public class QSFactoryImpl implements QSFactory { Provider<ScreenRecordTile> screenRecordTileProvider) { mWifiTileProvider = wifiTileProvider; mBluetoothTileProvider = bluetoothTileProvider; - mControlsTileProvider = controlsTileProvider; mCellularTileProvider = cellularTileProvider; mDndTileProvider = dndTileProvider; mColorInversionTileProvider = colorInversionTileProvider; @@ -146,11 +141,6 @@ public class QSFactoryImpl implements QSFactory { return mWifiTileProvider.get(); case "bt": return mBluetoothTileProvider.get(); - case "controls": - if (Settings.System.getInt(mHost.getContext().getContentResolver(), - "npv_plugin_flag", 0) == 3) { - return mControlsTileProvider.get(); - } else return null; case "cell": return mCellularTileProvider.get(); case "dnd": diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index fda9e5b1f1ef..8b7f280608a5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -65,6 +65,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { private String mAccessibilityClass; private boolean mTileState; private boolean mCollapsedView; + private boolean mClicked; private boolean mShowRippleEffect = true; private final ImageView mBg; @@ -233,35 +234,13 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { setLongClickable(state.handlesLongClick); mIcon.setIcon(state, allowAnimations); setContentDescription(state.contentDescription); - final StringBuilder stateDescription = new StringBuilder(); - switch (state.state) { - case Tile.STATE_UNAVAILABLE: - stateDescription.append(mContext.getString(R.string.tile_unavailable)); - break; - case Tile.STATE_INACTIVE: - if (state instanceof QSTile.BooleanState) { - stateDescription.append(mContext.getString(R.string.switch_bar_off)); - } - break; - case Tile.STATE_ACTIVE: - if (state instanceof QSTile.BooleanState) { - stateDescription.append(mContext.getString(R.string.switch_bar_on)); - } - break; - default: - break; - } - if (!TextUtils.isEmpty(state.stateDescription)) { - stateDescription.append(", "); - stateDescription.append(state.stateDescription); - } - setStateDescription(stateDescription.toString()); mAccessibilityClass = state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName; if (state instanceof QSTile.BooleanState) { boolean newState = ((BooleanState) state).value; if (mTileState != newState) { + mClicked = false; mTileState = newState; } } @@ -318,10 +297,23 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { } @Override + public boolean performClick() { + mClicked = true; + return super.performClick(); + } + + @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); if (!TextUtils.isEmpty(mAccessibilityClass)) { event.setClassName(mAccessibilityClass); + if (Switch.class.getName().equals(mAccessibilityClass)) { + boolean b = mClicked ? !mTileState : mTileState; + String label = getResources() + .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off); + event.setContentDescription(label); + event.setChecked(b); + } } } @@ -333,6 +325,11 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { if (!TextUtils.isEmpty(mAccessibilityClass)) { info.setClassName(mAccessibilityClass); if (Switch.class.getName().equals(mAccessibilityClass)) { + boolean b = mClicked ? !mTileState : mTileState; + String label = getResources() + .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off); + info.setText(label); + info.setChecked(b); info.setCheckable(true); if (isLongClickable()) { info.addAction( diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 361b6c1b1260..9282a2e3b312 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -134,27 +134,25 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { state.label = mContext.getString(R.string.quick_settings_bluetooth_label); state.secondaryLabel = TextUtils.emptyIfNull( getSecondaryLabel(enabled, connecting, connected, state.isTransient)); - state.contentDescription = state.label; - state.stateDescription = ""; if (enabled) { if (connected) { state.icon = new BluetoothConnectedTileIcon(); if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) { state.label = mController.getConnectedDeviceName(); } - state.stateDescription = + state.contentDescription = mContext.getString(R.string.accessibility_bluetooth_name, state.label) + ", " + state.secondaryLabel; } else if (state.isTransient) { state.icon = ResourceIcon.get( com.android.internal.R.drawable.ic_bluetooth_transient_animation); - state.stateDescription = state.secondaryLabel; + state.contentDescription = state.secondaryLabel; } else { state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_bluetooth); - state.stateDescription = mContext.getString(R.string.accessibility_not_connected); + R.string.accessibility_quick_settings_bluetooth) + "," + + mContext.getString(R.string.accessibility_not_connected); } state.state = Tile.STATE_ACTIVE; } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 58de0575fa75..32b051e35604 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -183,7 +183,6 @@ public class CastTile extends QSTileImpl<BooleanState> { protected void handleUpdateState(BooleanState state, Object arg) { state.label = mContext.getString(R.string.quick_settings_cast_title); state.contentDescription = state.label; - state.stateDescription = ""; state.value = false; final List<CastDevice> devices = mController.getCastDevices(); boolean connecting = false; @@ -193,9 +192,8 @@ public class CastTile extends QSTileImpl<BooleanState> { if (device.state == CastDevice.STATE_CONNECTED) { state.value = true; state.secondaryLabel = getDeviceName(device); - state.stateDescription = state.stateDescription + "," - + mContext.getString( - R.string.accessibility_cast_name, state.label); + state.contentDescription = state.contentDescription + "," + + mContext.getString(R.string.accessibility_cast_name, state.label); connecting = false; break; } else if (device.state == CastDevice.STATE_CONNECTING) { @@ -219,8 +217,9 @@ public class CastTile extends QSTileImpl<BooleanState> { state.state = Tile.STATE_UNAVAILABLE; String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi); state.secondaryLabel = noWifi; + state.contentDescription = state.contentDescription + ", " + mContext.getString( + R.string.accessibility_quick_settings_not_available, noWifi); } - state.stateDescription = state.stateDescription + ", " + state.secondaryLabel; mDetailAdapter.updateItems(devices); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index d5f86c951407..22470c7f5af5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -194,13 +194,17 @@ public class CellularTile extends QSTileImpl<SignalState> { state.secondaryLabel = r.getString(R.string.cell_data_off); } - state.contentDescription = state.label; + + // TODO(b/77881974): Instead of switching out the description via a string check for + // we need to have two strings provided by the MobileIconGroup. + final CharSequence contentDescriptionSuffix; if (state.state == Tile.STATE_INACTIVE) { - // This information is appended later by converting the Tile.STATE_INACTIVE state. - state.stateDescription = ""; + contentDescriptionSuffix = r.getString(R.string.cell_data_off_content_description); } else { - state.stateDescription = state.secondaryLabel; + contentDescriptionSuffix = state.secondaryLabel; } + + state.contentDescription = state.label + ", " + contentDescriptionSuffix; } private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java deleted file mode 100644 index 39ae66e7607a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ControlsTile.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.tiles; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.android.systemui.R; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.NPVPlugin; -import com.android.systemui.plugins.PluginListener; -import com.android.systemui.plugins.qs.DetailAdapter; -import com.android.systemui.plugins.qs.QSTile.BooleanState; -import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.tileimpl.QSTileImpl; -import com.android.systemui.shared.plugins.PluginManager; - -import javax.inject.Inject; - - -/** - * Temporary control test for prototyping - */ -public class ControlsTile extends QSTileImpl<BooleanState> { - private ControlsDetailAdapter mDetailAdapter; - private final ActivityStarter mActivityStarter; - private PluginManager mPluginManager; - private NPVPlugin mPlugin; - private Intent mHomeAppIntent; - - @Inject - public ControlsTile(QSHost host, - ActivityStarter activityStarter, - PluginManager pluginManager) { - super(host); - mActivityStarter = activityStarter; - mPluginManager = pluginManager; - mDetailAdapter = (ControlsDetailAdapter) createDetailAdapter(); - - mHomeAppIntent = new Intent(Intent.ACTION_VIEW); - mHomeAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mHomeAppIntent.setComponent(new ComponentName("com.google.android.apps.chromecast.app", - "com.google.android.apps.chromecast.app.DiscoveryActivity")); - } - - @Override - public DetailAdapter getDetailAdapter() { - return mDetailAdapter; - } - - @Override - public BooleanState newTileState() { - return new BooleanState(); - } - - @Override - public void handleSetListening(boolean listening) { - - } - - @Override - public void setDetailListening(boolean listening) { - if (mPlugin == null) return; - - mPlugin.setListening(listening); - } - - @Override - protected void handleClick() { - showDetail(true); - } - - @Override - public Intent getLongClickIntent() { - return mHomeAppIntent; - } - - @Override - protected void handleSecondaryClick() { - showDetail(true); - } - - @Override - public CharSequence getTileLabel() { - return "Controls"; - } - - @Override - protected void handleUpdateState(BooleanState state, Object arg) { - state.icon = ResourceIcon.get(R.drawable.ic_lightbulb_outline_gm2_24px); - state.label = "Controls"; - } - - @Override - public boolean supportsDetailView() { - return getDetailAdapter() != null && mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK; - } - - @Override - public int getMetricsCategory() { - return -1; - } - - @Override - protected String composeChangeAnnouncement() { - if (mState.value) { - return "On"; - } else { - return "Off"; - } - } - - @Override - public boolean isAvailable() { - return true; - } - - @Override - protected DetailAdapter createDetailAdapter() { - mDetailAdapter = new ControlsDetailAdapter(); - return mDetailAdapter; - } - - private class ControlsDetailAdapter implements DetailAdapter { - private View mDetailView; - protected FrameLayout mHomeControlsLayout; - - public CharSequence getTitle() { - return "Controls"; - } - - public Boolean getToggleState() { - return null; - } - - public boolean getToggleEnabled() { - return false; - } - - public View createDetailView(Context context, View convertView, final ViewGroup parent) { - if (convertView != null) return convertView; - - mHomeControlsLayout = (FrameLayout) LayoutInflater.from(context).inflate( - R.layout.home_controls, parent, false); - mHomeControlsLayout.setVisibility(View.VISIBLE); - parent.addView(mHomeControlsLayout); - - mPluginManager.addPluginListener( - new PluginListener<NPVPlugin>() { - @Override - public void onPluginConnected(NPVPlugin plugin, - Context pluginContext) { - mPlugin = plugin; - mPlugin.attachToRoot(mHomeControlsLayout); - mPlugin.setListening(true); - } - - @Override - public void onPluginDisconnected(NPVPlugin plugin) { - mPlugin.setListening(false); - mHomeControlsLayout.removeAllViews(); - - } - }, NPVPlugin.class, false); - return mHomeControlsLayout; - } - - public Intent getSettingsIntent() { - return mHomeAppIntent; - } - - public void setToggleState(boolean state) { - - } - - public int getMetricsCategory() { - return -1; - } - - public boolean hasHeader() { - return false; - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 9215da4cda9a..52d1a5b3b991 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -240,8 +240,6 @@ public class DndTile extends QSTileImpl<BooleanState> { zen != Global.ZEN_MODE_OFF, mController.getConfig(), false)); state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_dnd); checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); - // Keeping the secondaryLabel in contentDescription instead of stateDescription is easier - // to understand. switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: state.contentDescription = diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index 792c36477962..dafdd89ee62c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -102,13 +102,14 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements } state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label); state.secondaryLabel = ""; - state.stateDescription = ""; if (!mFlashlightController.isAvailable()) { state.icon = mIcon; state.slash.isSlashed = true; state.secondaryLabel = mContext.getString( R.string.quick_settings_flashlight_camera_in_use); - state.stateDescription = state.secondaryLabel; + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_flashlight_unavailable) + + ", " + state.secondaryLabel; state.state = Tile.STATE_UNAVAILABLE; return; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index fd6b936d71c0..001e09406e3a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -147,7 +147,6 @@ public class HotspotTile extends QSTileImpl<BooleanState> { state.secondaryLabel = getSecondaryLabel( isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices); - state.stateDescription = state.secondaryLabel; } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index e617867eb10e..fbdca3ba1c7b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -105,8 +105,15 @@ public class LocationTile extends QSTileImpl<BooleanState> { } state.icon = mIcon; state.slash.isSlashed = !state.value; - state.label = mContext.getString(R.string.quick_settings_location_label); - state.contentDescription = state.label; + if (locationEnabled) { + state.label = mContext.getString(R.string.quick_settings_location_label); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_location_on); + } else { + state.label = mContext.getString(R.string.quick_settings_location_label); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_location_off); + } state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 6e8dcf36bacc..b7ce101cacab 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -195,7 +195,6 @@ public class WifiTile extends QSTileImpl<SignalState> { state.activityIn = cb.enabled && cb.activityIn; state.activityOut = cb.enabled && cb.activityOut; final StringBuffer minimalContentDescription = new StringBuffer(); - final StringBuffer minimalStateDescription = new StringBuffer(); final Resources r = mContext.getResources(); if (isTransient) { state.icon = ResourceIcon.get( @@ -220,14 +219,13 @@ public class WifiTile extends QSTileImpl<SignalState> { mContext.getString(R.string.quick_settings_wifi_label)).append(","); if (state.value) { if (wifiConnected) { - minimalStateDescription.append(cb.wifiSignalContentDescription); + minimalContentDescription.append(cb.wifiSignalContentDescription).append(","); minimalContentDescription.append(removeDoubleQuotes(cb.ssid)); if (!TextUtils.isEmpty(state.secondaryLabel)) { minimalContentDescription.append(",").append(state.secondaryLabel); } } } - state.stateDescription = minimalStateDescription.toString(); state.contentDescription = minimalContentDescription.toString(); state.dualLabelContentDescription = r.getString( R.string.accessibility_quick_settings_open_settings, getTileLabel()); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index e54ee51fb9d4..7853dc388bcb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -103,11 +103,14 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements state.icon = mIcon; if (state.value) { state.slash.isSlashed = false; + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_work_mode_on); } else { state.slash.isSlashed = true; + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_work_mode_off); } state.label = mContext.getString(R.string.quick_settings_work_mode_label); - state.contentDescription = state.label; state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java index e6082dddd6c7..e7e1ba8c28b4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java @@ -106,7 +106,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> { // Initialize screenshot notification smart actions provider. mSmartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, false); + SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, true); if (mSmartActionsEnabled) { mSmartActionsProvider = SystemUIFactory.getInstance() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 976531d8b49d..12298817d5a6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -79,6 +79,7 @@ public class NotificationLockscreenUserManagerImpl implements private final DeviceProvisionedController mDeviceProvisionedController; private final KeyguardStateController mKeyguardStateController; + private final Object mLock = new Object(); // Lazy private NotificationEntryManager mEntryManager; @@ -181,6 +182,7 @@ public class NotificationLockscreenUserManagerImpl implements protected final Context mContext; private final Handler mMainHandler; protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); + protected final ArrayList<UserInfo> mCurrentManagedProfiles = new ArrayList<>(); protected int mCurrentUserId = 0; protected NotificationPresenter mPresenter; @@ -280,7 +282,8 @@ public class NotificationLockscreenUserManagerImpl implements filter.addAction(Intent.ACTION_USER_UNLOCKED); filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); - mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter); + mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter, + null /* executor */, UserHandle.ALL); IntentFilter internalFilter = new IntentFilter(); internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); @@ -300,7 +303,7 @@ public class NotificationLockscreenUserManagerImpl implements } public boolean isCurrentProfile(int userId) { - synchronized (mCurrentProfiles) { + synchronized (mLock) { return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null; } } @@ -417,6 +420,20 @@ public class NotificationLockscreenUserManagerImpl implements return mUsersAllowingPrivateNotifications.get(userHandle); } + /** + * If all managed profiles (work profiles) can show private data in public (secure & locked.) + */ + public boolean allowsManagedPrivateNotificationsInPublic() { + synchronized (mLock) { + for (UserInfo profile : mCurrentManagedProfiles) { + if (!userAllowsPrivateNotificationsInPublic(profile.id)) { + return false; + } + } + } + return true; + } + private boolean adminAllowsKeyguardFeature(int userHandle, int feature) { if (userHandle == UserHandle.USER_ALL) { return true; @@ -495,11 +512,15 @@ public class NotificationLockscreenUserManagerImpl implements } private void updateCurrentProfilesCache() { - synchronized (mCurrentProfiles) { + synchronized (mLock) { mCurrentProfiles.clear(); + mCurrentManagedProfiles.clear(); if (mUserManager != null) { for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) { mCurrentProfiles.put(user.id, user); + if (UserManager.USER_TYPE_PROFILE_MANAGED.equals(user.userType)) { + mCurrentManagedProfiles.add(user); + } } } } @@ -510,10 +531,29 @@ public class NotificationLockscreenUserManagerImpl implements }); } + /** + * If any of the profiles are in public mode. + */ public boolean isAnyProfilePublicMode() { - for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { - if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { - return true; + synchronized (mLock) { + for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { + if (isLockscreenPublicMode(mCurrentProfiles.valueAt(i).id)) { + return true; + } + } + } + return false; + } + + /** + * If any managed/work profiles are in public mode. + */ + public boolean isAnyManagedProfilePublicMode() { + synchronized (mLock) { + for (int i = mCurrentManagedProfiles.size() - 1; i >= 0; i--) { + if (isLockscreenPublicMode(mCurrentManagedProfiles.get(i).id)) { + return true; + } } } return false; @@ -620,9 +660,17 @@ public class NotificationLockscreenUserManagerImpl implements pw.print(" mAllowLockscreenRemoteInput="); pw.println(mAllowLockscreenRemoteInput); pw.print(" mCurrentProfiles="); - for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { - final int userId = mCurrentProfiles.valueAt(i).id; - pw.print("" + userId + " "); + synchronized (mLock) { + for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) { + final int userId = mCurrentProfiles.valueAt(i).id; + pw.print("" + userId + " "); + } + } + pw.print(" mCurrentManagedProfiles="); + synchronized (mLock) { + for (UserInfo userInfo : mCurrentManagedProfiles) { + pw.print("" + userInfo.id + " "); + } } pw.println(); } 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 11ead8bd2576..84a293eebc95 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 @@ -35,6 +35,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.Intent; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Canvas; @@ -56,6 +57,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.MathUtils; import android.util.Pair; +import android.util.SparseArray; import android.view.ContextThemeWrapper; import android.view.InputDevice; import android.view.LayoutInflater; @@ -99,6 +101,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper.DragDownCallback; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.RemoteInputController; @@ -328,6 +331,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return true; } }; + private final UserChangedListener mLockscreenUserChangeListener = new UserChangedListener() { + @Override + public void onUserChanged(int userId) { + updateSensitiveness(false /* animated */); + } + }; private StatusBar mStatusBar; private int[] mTempInt2 = new int[2]; private boolean mGenerateChildOrderChangedEvent; @@ -561,6 +570,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated); mRoundnessManager.setOnRoundingChangedCallback(this::invalidate); addOnExpandedHeightChangedListener(mRoundnessManager::setExpanded); + mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener); setOutlineProvider(mOutlineProvider); // Blocking helper manager wants to know the expanded state, update as well. @@ -4611,7 +4621,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void setHideSensitive(boolean hideSensitive, boolean animate) { + private void updateSensitiveness(boolean animate) { + boolean hideSensitive = mLockscreenUserManager.isAnyProfilePublicMode(); if (hideSensitive != mAmbientState.isHideSensitive()) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -5306,7 +5317,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private void onStatePostChange() { boolean onKeyguard = onKeyguard(); - boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode(); if (mHeadsUpAppearanceController != null) { mHeadsUpAppearanceController.onStateChanged(); @@ -5314,7 +5324,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd SysuiStatusBarStateController state = (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class); - setHideSensitive(publicMode, state.goingToFullShade() /* animate */); + updateSensitiveness(state.goingToFullShade() /* animate */); setDimmed(onKeyguard, state.fromShadeLocked() /* animate */); setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = getActivatedChild(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index afaa593b3bb9..e7d6eba1dcb3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -22,7 +22,6 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; -import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -53,7 +52,7 @@ public class DozeScrimController implements StateListener { public void onDisplayBlanked() { if (DEBUG) { Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason=" - + DozeEvent.reasonToString(mPulseReason)); + + DozeLog.reasonToString(mPulseReason)); } if (!mDozing) { return; @@ -74,8 +73,8 @@ public class DozeScrimController implements StateListener { // Notifications should time out on their own. Pulses due to notifications should // instead be managed externally based off the notification's lifetime. // Dock also controls the time out by self. - if (mPulseReason != DozeEvent.PULSE_REASON_NOTIFICATION - && mPulseReason != DozeEvent.PULSE_REASON_DOCKING) { + if (mPulseReason != DozeLog.PULSE_REASON_NOTIFICATION + && mPulseReason != DozeLog.PULSE_REASON_DOCKING) { mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration()); mHandler.postDelayed(mPulseOutExtended, mDozeParameters.getPulseVisibleDurationExtended()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index 04efc2d7558d..56e5cb08f6d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -31,7 +31,6 @@ import android.view.View; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeReceiver; @@ -221,18 +220,18 @@ public final class DozeServiceHost implements DozeHost { @Override public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS) { + if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:LONG_PRESS"); mAssistManagerLazy.get().startAssist(new Bundle()); return; } - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { mScrimController.setWakeLockScreenSensorActive(true); } - boolean passiveAuthInterrupt = reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN + boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN && mWakeLockScreenPerformsAuth; // Set the state to pulsing, so ScrimController will know what to do once we ask it to // execute the transition. The pulse callback will then be invoked when the scrims @@ -332,7 +331,7 @@ public final class DozeServiceHost implements DozeHost { @Override public void extendPulse(int reason) { - if (reason == DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { mScrimController.setWakeLockScreenSensorActive(true); } if (mDozeScrimController.isPulsing() && mHeadsUpManagerPhone.hasNotifications()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index ad1aa8370495..b4d0d479ff39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -33,7 +33,7 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class KeyguardBypassController : Dumpable { +open class KeyguardBypassController : Dumpable { private val mKeyguardStateController: KeyguardStateController private val statusBarStateController: StatusBarStateController diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt deleted file mode 100644 index 53601babfd56..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.phone - -import android.content.Context -import android.view.View -import android.view.ViewGroup.MarginLayoutParams -import android.widget.FrameLayout -import com.android.systemui.plugins.NPVPlugin -import com.android.systemui.plugins.PluginListener -import com.android.systemui.qs.TouchAnimator -import com.android.systemui.shared.plugins.PluginManager - -/** - * Manages the NPVPlugin view and state - * - * Abstracts NPVPlugin from NPV and helps animate on expansion and respond to changes in Config. - */ -class NPVPluginManager( - var parent: FrameLayout, - val pluginManager: PluginManager -) : PluginListener<NPVPlugin> { - - private var plugin: NPVPlugin? = null - private var animator = createAnimator() - private var yOffset = 0f - - private fun createAnimator() = TouchAnimator.Builder() - .addFloat(parent, "alpha", 1f, 0f) - .addFloat(parent, "scaleY", 1f, 0f) - .build() - - init { - pluginManager.addPluginListener(NPVPlugin.ACTION, this, NPVPlugin::class.java, false) - parent.pivotY = 0f - } - - override fun onPluginConnected(plugin: NPVPlugin, pluginContext: Context) { - parent.removeAllViews() - plugin.attachToRoot(parent) - this.plugin = plugin - parent.visibility = View.VISIBLE - } - - fun changeVisibility(visibility: Int) { - parent.visibility = if (plugin != null) visibility else View.GONE - } - - fun destroy() { - plugin?.onDestroy() - pluginManager.removePluginListener(this) - } - - override fun onPluginDisconnected(plugin: NPVPlugin) { - if (this.plugin == plugin) { - this.plugin = null - parent.removeAllViews() - parent.visibility = View.GONE - } - } - - fun setListening(listening: Boolean) { - plugin?.setListening(listening) - } - - fun setExpansion(expansion: Float, headerTranslation: Float, heightDiff: Float) { - parent.setTranslationY(expansion * heightDiff + headerTranslation + yOffset) - if (!expansion.isNaN()) animator.setPosition(expansion) - } - - fun replaceFrameLayout(newParent: FrameLayout) { - newParent.visibility = parent.visibility - parent.removeAllViews() - plugin?.attachToRoot(newParent) - parent = newParent - animator = createAnimator() - } - - fun getHeight() = - if (plugin != null) { - parent.height + (parent.getLayoutParams() as MarginLayoutParams).topMargin - } else 0 - - fun setYOffset(y: Float) { - yOffset = y - parent.setTranslationY(yOffset) - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 6112ae88f634..d2186f959aba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -25,10 +25,8 @@ import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.Fragment; import android.app.StatusBarManager; -import android.content.Context; import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -40,8 +38,6 @@ import android.graphics.drawable.Drawable; import android.hardware.biometrics.BiometricSourceType; import android.os.PowerManager; import android.os.SystemClock; -import android.provider.DeviceConfig; -import android.provider.Settings; import android.util.Log; import android.util.MathUtils; import android.view.LayoutInflater; @@ -57,7 +53,6 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.LatencyTracker; @@ -73,13 +68,10 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.plugins.HomeControlsPlugin; -import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.qs.QSFragment; -import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.GestureRecorder; @@ -113,7 +105,6 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.InjectionInflationController; -import com.android.systemui.util.Utils; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -173,8 +164,6 @@ public class NotificationPanelViewController extends PanelViewController { private final ConfigurationController mConfigurationController; private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder; - private double mQqsSplitFraction; - // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is // changed. private static final int CAP_HEIGHT = 1456; @@ -258,7 +247,6 @@ public class NotificationPanelViewController extends PanelViewController { private View mQsNavbarScrim; private NotificationsQuickSettingsContainer mNotificationContainerParent; private NotificationStackScrollLayout mNotificationStackScroller; - private FrameLayout mHomeControlsLayout; private boolean mAnimateNextPositionUpdate; private int mTrackingPointer; @@ -446,9 +434,6 @@ public class NotificationPanelViewController extends PanelViewController { */ private boolean mDelayShowingKeyguardStatusBar; - private PluginManager mPluginManager; - private FrameLayout mPluginFrame; - private NPVPluginManager mNPVPluginManager; private int mOldLayoutDirection; @Inject @@ -457,7 +442,7 @@ public class NotificationPanelViewController extends PanelViewController { NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler, DynamicPrivacyController dynamicPrivacyController, KeyguardBypassController bypassController, FalsingManager falsingManager, - PluginManager pluginManager, ShadeController shadeController, + ShadeController shadeController, NotificationLockscreenUserManager notificationLockscreenUserManager, NotificationEntryManager notificationEntryManager, KeyguardStateController keyguardStateController, @@ -523,7 +508,6 @@ public class NotificationPanelViewController extends PanelViewController { }); mBottomAreaShadeAlphaAnimator.setDuration(160); mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT); - mPluginManager = pluginManager; mShadeController = shadeController; mLockscreenUserManager = notificationLockscreenUserManager; mEntryManager = notificationEntryManager; @@ -553,7 +537,6 @@ public class NotificationPanelViewController extends PanelViewController { mBigClockContainer = mView.findViewById(R.id.big_clock_container); keyguardClockSwitch.setBigClockContainer(mBigClockContainer); - mHomeControlsLayout = mView.findViewById(R.id.home_controls_layout); mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent); mNotificationStackScroller = mView.findViewById(R.id.notification_stack_scroller); mNotificationStackScroller.setOnHeightChangedListener(mOnHeightChangedListener); @@ -563,12 +546,6 @@ public class NotificationPanelViewController extends PanelViewController { mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area); mQsNavbarScrim = mView.findViewById(R.id.qs_navbar_scrim); mLastOrientation = mResources.getConfiguration().orientation; - mPluginFrame = mView.findViewById(R.id.plugin_frame); - if (Settings.System.getInt(mView.getContext().getContentResolver(), "npv_plugin_flag", 0) - == 1) { - mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager); - } - initBottomArea(); @@ -592,19 +569,6 @@ public class NotificationPanelViewController extends PanelViewController { } }); - mPluginManager.addPluginListener(new PluginListener<HomeControlsPlugin>() { - - @Override - public void onPluginConnected(HomeControlsPlugin plugin, Context pluginContext) { - plugin.sendParentGroup(mHomeControlsLayout); - } - - @Override - public void onPluginDisconnected(HomeControlsPlugin plugin) { - - } - }, HomeControlsPlugin.class, false); - mView.setRtlChangeListener(layoutDirection -> { if (layoutDirection != mOldLayoutDirection) { mAffordanceHelper.onRtlPropertiesChanged(); @@ -637,9 +601,6 @@ public class NotificationPanelViewController extends PanelViewController { com.android.internal.R.dimen.status_bar_height); mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize( R.dimen.heads_up_status_bar_padding); - mQqsSplitFraction = ((float) mResources.getInteger(R.integer.qqs_split_fraction)) / ( - mResources.getInteger(R.integer.qqs_split_fraction) + mResources.getInteger( - R.integer.qs_split_fraction)); } /** @@ -679,18 +640,6 @@ public class NotificationPanelViewController extends PanelViewController { lp.gravity = panelGravity; mNotificationStackScroller.setLayoutParams(lp); } - int sideMargin = mResources.getDimensionPixelOffset(R.dimen.notification_side_paddings); - int topMargin = sideMargin; - lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams(); - if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin - || lp.rightMargin != sideMargin || lp.topMargin != topMargin) { - lp.width = qsWidth; - lp.gravity = panelGravity; - lp.leftMargin = sideMargin; - lp.rightMargin = sideMargin; - lp.topMargin = topMargin; - mPluginFrame.setLayoutParams(lp); - } } private void reInflateViews() { @@ -732,41 +681,6 @@ public class NotificationPanelViewController extends PanelViewController { if (mOnReinflationListener != null) { mOnReinflationListener.run(); } - reinflatePluginContainer(); - } - - private void reinflatePluginContainer() { - int index = mView.indexOfChild(mPluginFrame); - mView.removeView(mPluginFrame); - mPluginFrame = (FrameLayout) mInjectionInflationController.injectable( - LayoutInflater.from(mView.getContext())).inflate( - R.layout.status_bar_expanded_plugin_frame, mView, false); - mView.addView(mPluginFrame, index); - - Resources res = mView.getResources(); - int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width); - int panelGravity = mView.getResources().getInteger( - R.integer.notification_panel_layout_gravity); - FrameLayout.LayoutParams lp; - int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings); - int topMargin = res.getDimensionPixelOffset( - com.android.internal.R.dimen.quick_qs_total_height); - if (Utils.useQsMediaPlayer(mView.getContext())) { - topMargin = res.getDimensionPixelOffset( - com.android.internal.R.dimen.quick_qs_total_height_with_media); - } - lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams(); - if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin - || lp.rightMargin != sideMargin || lp.topMargin != topMargin) { - lp.width = qsWidth; - lp.gravity = panelGravity; - lp.leftMargin = sideMargin; - lp.rightMargin = sideMargin; - lp.topMargin = topMargin; - mPluginFrame.setLayoutParams(lp); - } - - if (mNPVPluginManager != null) mNPVPluginManager.replaceFrameLayout(mPluginFrame); } private void initBottomArea() { @@ -1266,17 +1180,6 @@ public class NotificationPanelViewController extends PanelViewController { // earlier so the state is already up to date when dragging down. setListening(true); } - if (isQsSplitEnabled() && !mKeyguardShowing) { - if (mQsExpandImmediate) { - mNotificationStackScroller.setVisibility(View.GONE); - mQsFrame.setVisibility(View.VISIBLE); - mHomeControlsLayout.setVisibility(View.VISIBLE); - } else { - mNotificationStackScroller.setVisibility(View.VISIBLE); - mQsFrame.setVisibility(View.GONE); - mHomeControlsLayout.setVisibility(View.GONE); - } - } return false; } @@ -1286,17 +1189,6 @@ public class NotificationPanelViewController extends PanelViewController { || y <= mQs.getView().getY() + mQs.getView().getHeight()); } - private boolean isOnQsEndArea(float x) { - if (!isQsSplitEnabled()) return false; - if (mView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) { - return x >= mQsFrame.getX() + mQqsSplitFraction * mQsFrame.getWidth() - && x <= mQsFrame.getX() + mQsFrame.getWidth(); - } else { - return x >= mQsFrame.getX() - && x <= mQsFrame.getX() + (1 - mQqsSplitFraction) * mQsFrame.getWidth(); - } - } - private boolean isOpenQsEvent(MotionEvent event) { final int pointerCount = event.getPointerCount(); final int action = event.getActionMasked(); @@ -1317,9 +1209,7 @@ public class NotificationPanelViewController extends PanelViewController { MotionEvent.BUTTON_SECONDARY) || event.isButtonPressed( MotionEvent.BUTTON_TERTIARY)); - final boolean onHeaderRight = isOnQsEndArea(event.getX()); - - return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag || onHeaderRight; + return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag; } private void handleQsDown(MotionEvent event) { @@ -1659,10 +1549,7 @@ public class NotificationPanelViewController extends PanelViewController { mBarState != StatusBarState.KEYGUARD && (!mQsExpanded || mQsExpansionFromOverscroll)); updateEmptyShadeView(); - if (mNPVPluginManager != null) { - mNPVPluginManager.changeVisibility( - (mBarState != StatusBarState.KEYGUARD) ? View.VISIBLE : View.INVISIBLE); - } + mQsNavbarScrim.setVisibility( mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling && mQsScrimEnabled ? View.VISIBLE : View.INVISIBLE); @@ -1718,9 +1605,6 @@ public class NotificationPanelViewController extends PanelViewController { float qsExpansionFraction = getQsExpansionFraction(); mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation()); int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight(); - if (mNPVPluginManager != null) { - mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff); - } mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction); } @@ -2015,7 +1899,6 @@ public class NotificationPanelViewController extends PanelViewController { targetHeight = mQsMinExpansionHeight + t * (mQsMaxExpansionHeight - mQsMinExpansionHeight); setQsExpansion(targetHeight); - mHomeControlsLayout.setTranslationY(targetHeight); } updateExpandedHeight(expandedHeight); updateHeader(); @@ -2150,7 +2033,6 @@ public class NotificationPanelViewController extends PanelViewController { appearAmount = mNotificationStackScroller.calculateAppearFractionBypass(); } startHeight = -mQs.getQsMinExpansionHeight(); - if (mNPVPluginManager != null) startHeight -= mNPVPluginManager.getHeight(); } float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)) + mExpandOffset; @@ -2294,7 +2176,6 @@ public class NotificationPanelViewController extends PanelViewController { mKeyguardStatusBar.setListening(listening); if (mQs == null) return; mQs.setListening(listening); - if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening); } @Override @@ -3029,11 +2910,6 @@ public class NotificationPanelViewController extends PanelViewController { mOnReinflationListener = onReinflationListener; } - public static boolean isQsSplitEnabled() { - return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.QS_SPLIT_ENABLED, false); - } - public void setAlpha(float alpha) { mView.setAlpha(alpha); } @@ -3500,9 +3376,7 @@ public class NotificationPanelViewController extends PanelViewController { } @Override - public void onUiModeChanged() { - reinflatePluginContainer(); - } + public void onUiModeChanged() {} } private class StatusBarStateListener implements StateListener { @@ -3517,11 +3391,6 @@ public class NotificationPanelViewController extends PanelViewController { mBarState = statusBarState; mKeyguardShowing = keyguardShowing; - if (mKeyguardShowing && isQsSplitEnabled()) { - mNotificationStackScroller.setVisibility(View.VISIBLE); - mQsFrame.setVisibility(View.VISIBLE); - mHomeControlsLayout.setVisibility(View.GONE); - } if (oldState == StatusBarState.KEYGUARD && (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) { @@ -3544,7 +3413,6 @@ public class NotificationPanelViewController extends PanelViewController { } else { mKeyguardStatusBar.setAlpha(1f); mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE); - ((PhoneStatusBarView) mBar).maybeShowDivider(keyguardShowing); if (keyguardShowing && oldState != mBarState) { if (mQs != null) { mQs.hideImmediately(); @@ -3622,10 +3490,6 @@ public class NotificationPanelViewController extends PanelViewController { int oldMaxHeight = mQsMaxExpansionHeight; if (mQs != null) { mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight(); - if (mNPVPluginManager != null) { - mNPVPluginManager.setYOffset(mQsMinExpansionHeight); - mQsMinExpansionHeight += mNPVPluginManager.getHeight(); - } mQsMaxExpansionHeight = mQs.getDesiredHeight(); mNotificationStackScroller.setMaxTopPadding( mQsMaxExpansionHeight + mQsNotificationTopPadding); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 3af80387778b..10b68b9a518d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -16,8 +16,10 @@ package com.android.systemui.statusbar.phone; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED; import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; @@ -180,6 +182,13 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mLp.setTitle("NotificationShade"); mLp.packageName = mContext.getPackageName(); mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + + // We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in + // window manager which disables the transient show behavior. + // TODO: Clean this up once that behavior moves into the Shell. + mLp.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED; + mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; + mWindowManager.addView(mNotificationShadeView, mLp); mLpChanged.copyFrom(mLp); onThemeChanged(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index 96b4b22d0580..e8bc2f58adb4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -32,7 +32,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private final PhoneStatusBarView mView; private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mBattery, mClock, mDivider; + private View mLeftSide, mStatusIcons, mBattery, mClock; private Animator mCurrentAnimation; public PhoneStatusBarTransitions(PhoneStatusBarView view) { @@ -46,7 +46,6 @@ public final class PhoneStatusBarTransitions extends BarTransitions { mLeftSide = mView.findViewById(R.id.status_bar_left_side); mStatusIcons = mView.findViewById(R.id.statusIcons); mBattery = mView.findViewById(R.id.battery); - mDivider = mView.findViewById(R.id.divider); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } @@ -89,7 +88,6 @@ public final class PhoneStatusBarTransitions extends BarTransitions { anims.playTogether( animateTransitionTo(mLeftSide, newAlpha), animateTransitionTo(mStatusIcons, newAlpha), - animateTransitionTo(mDivider, newAlpha), animateTransitionTo(mBattery, newAlphaBC) ); if (isLightsOut(mode)) { @@ -100,8 +98,7 @@ public final class PhoneStatusBarTransitions extends BarTransitions { } else { mLeftSide.setAlpha(newAlpha); mStatusIcons.setAlpha(newAlpha); - mDivider.setAlpha(newAlpha); mBattery.setAlpha(newAlphaBC); } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index ffbbffc0d8d9..f3b0a79f9518 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -25,7 +25,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; -import android.provider.DeviceConfig; import android.util.AttributeSet; import android.util.EventLog; import android.util.Pair; @@ -40,8 +39,6 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.FrameLayout; import android.widget.LinearLayout; -import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; -import com.android.systemui.DarkReceiverImpl; import com.android.systemui.Dependency; import com.android.systemui.EventLogTags; import com.android.systemui.R; @@ -81,9 +78,6 @@ public class PhoneStatusBarView extends PanelBar { @Nullable private DisplayCutout mDisplayCutout; - private DarkReceiverImpl mSplitDivider; - private View mDividerContainer; - private QsSplitPropertyListener mPropertyListener; /** * Draw this many pixels into the left/right side of the cutout to optimally use the space */ @@ -115,10 +109,6 @@ public class PhoneStatusBarView extends PanelBar { mBattery = findViewById(R.id.battery); mCutoutSpace = findViewById(R.id.cutout_space_view); mCenterIconSpace = findViewById(R.id.centered_icon_area); - mSplitDivider = findViewById(R.id.divider); - mDividerContainer = findViewById(R.id.divider_container); - maybeShowDivider(true); - mPropertyListener = new QsSplitPropertyListener(mDividerContainer); updateResources(); } @@ -128,26 +118,16 @@ public class PhoneStatusBarView extends PanelBar { super.onAttachedToWindow(); // Always have Battery meters in the status bar observe the dark/light modes. Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery); - Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSplitDivider); - maybeShowDivider(true); if (updateOrientationAndCutout(getResources().getConfiguration().orientation)) { updateLayoutForCutout(); } - if (mPropertyListener != null) { - DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, - mContext.getMainExecutor(), mPropertyListener); - } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mBattery); - Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSplitDivider); mDisplayCutout = null; - if (mPropertyListener != null) { - DeviceConfig.removeOnPropertiesChangedListener(mPropertyListener); - } } @Override @@ -216,7 +196,6 @@ public class PhoneStatusBarView extends PanelBar { public void onPanelPeeked() { super.onPanelPeeked(); mBar.makeExpandedVisible(false); - maybeShowDivider(!mBar.mPanelExpanded); } @Override @@ -225,7 +204,6 @@ public class PhoneStatusBarView extends PanelBar { // Close the status bar in the next frame so we can show the end of the animation. post(mHideExpandedRunnable); mIsFullyOpenedPanel = false; - maybeShowDivider(!mBar.mPanelExpanded); } public void removePendingHideExpandedRunnables() { @@ -239,7 +217,6 @@ public class PhoneStatusBarView extends PanelBar { mPanel.getView().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } mIsFullyOpenedPanel = true; - maybeShowDivider(!mBar.mPanelExpanded); } @Override @@ -263,28 +240,24 @@ public class PhoneStatusBarView extends PanelBar { mBar.onTrackingStarted(); mScrimController.onTrackingStarted(); removePendingHideExpandedRunnables(); - maybeShowDivider(!mBar.mPanelExpanded); } @Override public void onClosingFinished() { super.onClosingFinished(); mBar.onClosingFinished(); - maybeShowDivider(!mBar.mPanelExpanded); } @Override public void onTrackingStopped(boolean expand) { super.onTrackingStopped(expand); mBar.onTrackingStopped(expand); - maybeShowDivider(!mBar.mPanelExpanded); } @Override public void onExpandingFinished() { super.onExpandingFinished(); mScrimController.onExpandingFinished(); - maybeShowDivider(!mBar.mPanelExpanded); } @Override @@ -416,31 +389,4 @@ public class PhoneStatusBarView extends PanelBar { protected boolean shouldPanelBeVisible() { return mHeadsUpVisible || super.shouldPanelBeVisible(); } - - void maybeShowDivider(boolean showDivider) { - int state = - showDivider && NotificationPanelViewController.isQsSplitEnabled() - ? View.VISIBLE : View.GONE; - mDividerContainer.setVisibility(state); - } - - private static class QsSplitPropertyListener implements - DeviceConfig.OnPropertiesChangedListener { - private final View mDivider; - - QsSplitPropertyListener(View divider) { - mDivider = divider; - } - - @Override - public void onPropertiesChanged(DeviceConfig.Properties properties) { - if (properties.getNamespace().equals(DeviceConfig.NAMESPACE_SYSTEMUI) - && properties.getKeyset().contains( - SystemUiDeviceConfigFlags.QS_SPLIT_ENABLED)) { - boolean splitEnabled = properties.getBoolean( - SystemUiDeviceConfigFlags.QS_SPLIT_ENABLED, false); - mDivider.setVisibility(splitEnabled ? VISIBLE : GONE); - } - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 4e8442f14dba..1726b4884aff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -144,7 +144,6 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.DismissCallbackRegistry; -import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -794,13 +793,6 @@ public class StatusBar extends SystemUI implements DemoMode, mBypassHeadsUpNotifier.setUp(mEntryManager); mBubbleController.setExpandListener(mBubbleExpandListener); mActivityIntentHelper = new ActivityIntentHelper(mContext); - KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance(); - if (sliceProvider != null) { - sliceProvider.initDependencies(mMediaManager, mStatusBarStateController, - mKeyguardBypassController, mDozeParameters); - } else { - Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies"); - } mColorExtractor.addOnColorsChangedListener(this); mStatusBarStateController.addCallback(this, 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 86a81ce3d1f1..6a046884e835 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.phone; +import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; +import static android.view.ViewRootImpl.sNewInsetsMode; +import static android.view.WindowInsets.Type.navigationBars; import static com.android.systemui.plugins.ActivityStarter.OnDismissAction; import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING; import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK; @@ -789,7 +792,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { @Override public void run() { - mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE); + if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) { + mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() + .show(navigationBars()); + } else { + mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE); + } } }; @@ -856,7 +864,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } else { mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable); - mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE); + if (sNewInsetsMode == NEW_INSETS_MODE_FULL) { + mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() + .hide(navigationBars()); + } else { + mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 3a1feaa2de14..28ba1257524d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -26,10 +26,12 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.provider.Settings.Global; +import android.telephony.AccessNetworkConstants; import android.telephony.Annotation; import android.telephony.CdmaEriInformation; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; +import android.telephony.DataSpecificRegistrationInfo; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -321,9 +323,9 @@ public class MobileSignalController extends SignalController< private int getNumLevels() { if (mInflateSignalStrengths) { - return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1; + return CellSignalStrength.getNumSignalStrengthLevels() + 1; } - return SignalStrength.NUM_SIGNAL_STRENGTH_BINS; + return CellSignalStrength.getNumSignalStrengthLevels(); } @Override @@ -616,10 +618,19 @@ public class MobileSignalController extends SignalController< notifyListenersIfNecessary(); } + private int getNrState(ServiceState serviceState) { + NetworkRegistrationInfo nri = serviceState.getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + if (nri != null) { + return nri.getNrState(); + } + return NetworkRegistrationInfo.NR_STATE_NONE; + } + private MobileIconGroup getNr5GIconGroup() { if (mServiceState == null) return null; - int nrState = mServiceState.getNrState(); + int nrState = getNrState(mServiceState); if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) { // Check if the NR 5G is using millimeter wave and the icon is config. if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) { @@ -772,12 +783,24 @@ public class MobileSignalController extends SignalController< if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) { if (isCarrierSpecificDataIcon()) { mCAPlus = true; - } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) { + } else if (mServiceState != null && isUsingCarrierAggregation(mServiceState)) { mCA = true; } } } + private boolean isUsingCarrierAggregation(ServiceState serviceState) { + NetworkRegistrationInfo nri = serviceState.getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + if (nri != null) { + DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo(); + if (dsri != null) { + return dsri.isUsingCarrierAggregation(); + } + } + return false; + } + @Override public void onDataActivity(int direction) { if (DEBUG) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 6dd113377ce7..46143ca0dd24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -41,9 +41,9 @@ import android.os.Looper; import android.os.PersistableBundle; import android.provider.Settings; import android.telephony.CarrierConfigManager; +import android.telephony.CellSignalStrength; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; -import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; @@ -56,7 +56,6 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.net.DataUsageController; import com.android.systemui.DemoMode; import com.android.systemui.Dumpable; @@ -605,7 +604,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @VisibleForTesting void doUpdateMobileControllers() { List<SubscriptionInfo> subscriptions = mSubscriptionManager - .getActiveSubscriptionInfoList(false); + .getActiveAndHiddenSubscriptionInfoList(); if (subscriptions == null) { subscriptions = Collections.emptyList(); } @@ -1035,7 +1034,7 @@ public class NetworkControllerImpl extends BroadcastReceiver if (level != null) { controller.getState().level = level.equals("null") ? -1 : Math.min(Integer.parseInt(level), - SignalStrength.NUM_SIGNAL_STRENGTH_BINS); + CellSignalStrength.getNumSignalStrengthLevels()); controller.getState().connected = controller.getState().level >= 0; } if (args.containsKey("inflate")) { diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index 47454cb5aca1..cfa2947eb862 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -129,8 +129,6 @@ public class Utils { */ public static boolean useQsMediaPlayer(Context context) { int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0); - flag |= Settings.System.getInt(context.getContentResolver(), "npv_plugin_flag", 0); - return flag > 0; } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java index eccf09633f16..ea6cf3329772 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java @@ -249,7 +249,7 @@ public class CarrierTextControllerTest extends SysuiTestCase { // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the // same answer as KeyguardUpdateMonitor. Remove when this is addressed - when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn( + when(mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList()).thenReturn( new ArrayList<>()); when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn( diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 59eb6c59a2cd..7e4ba92301aa 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -22,7 +22,6 @@ import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -438,14 +437,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test - public void testIgnoresAuth_whenLockout() { + public void testTriesToAuthenticate_whenLockout() { mKeyguardUpdateMonitor.dispatchStartedWakingUp(); mTestableLooper.processAllMessages(); when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn( KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT); mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true); - verify(mFaceManager, never()).authenticate(any(), any(), anyInt(), any(), any(), anyInt()); + verify(mFaceManager).authenticate(any(), any(), anyInt(), any(), any(), anyInt()); } @Test @@ -483,7 +482,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { List<SubscriptionInfo> list = new ArrayList<>(); list.add(TEST_SUBSCRIPTION); list.add(TEST_SUBSCRIPTION_2); - when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list); + when(mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList()).thenReturn(list); mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged( TEST_SUBSCRIPTION_2.getSubscriptionId()); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java index 0723a4ce74a4..f4cf314aa8fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java @@ -142,7 +142,7 @@ public class DozeMachineTest extends SysuiTestCase { public void testPulseDone_goesToDoze() { when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); mMachine.requestState(INITIALIZED); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -155,7 +155,7 @@ public class DozeMachineTest extends SysuiTestCase { public void testPulseDone_goesToAoD() { when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -168,7 +168,7 @@ public class DozeMachineTest extends SysuiTestCase { public void testPulseDone_afterDocked_goesToDockedAoD() { when(mDockManager.isDocked()).thenReturn(true); mMachine.requestState(INITIALIZED); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -183,7 +183,7 @@ public class DozeMachineTest extends SysuiTestCase { when(mDockManager.isDocked()).thenReturn(true); when(mDockManager.isHidden()).thenReturn(true); mMachine.requestState(INITIALIZED); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -227,7 +227,7 @@ public class DozeMachineTest extends SysuiTestCase { public void testWakeLock_heldInPulseStates() { mMachine.requestState(INITIALIZED); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertTrue(mWakeLockFake.isHeld()); mMachine.requestState(DOZE_PULSING); @@ -250,7 +250,7 @@ public class DozeMachineTest extends SysuiTestCase { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -262,9 +262,9 @@ public class DozeMachineTest extends SysuiTestCase { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSE_DONE); } @@ -273,7 +273,7 @@ public class DozeMachineTest extends SysuiTestCase { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSE_DONE); } @@ -286,7 +286,7 @@ public class DozeMachineTest extends SysuiTestCase { return null; }).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE)); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertEquals(DOZE_PULSING, mMachine.getState()); } @@ -295,9 +295,9 @@ public class DozeMachineTest extends SysuiTestCase { public void testPulseReason_getMatchesRequest() { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestPulse(DozeEvent.REASON_SENSOR_DOUBLE_TAP); + mMachine.requestPulse(DozeLog.REASON_SENSOR_DOUBLE_TAP); - assertEquals(DozeEvent.REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason()); + assertEquals(DozeLog.REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason()); } @Test @@ -309,7 +309,7 @@ public class DozeMachineTest extends SysuiTestCase { if (newState == DOZE_REQUEST_PULSE || newState == DOZE_PULSING || newState == DOZE_PULSE_DONE) { - assertEquals(DozeEvent.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason()); + assertEquals(DozeLog.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason()); } else { assertTrue("unexpected state " + newState, newState == DOZE || newState == DOZE_AOD); @@ -317,7 +317,7 @@ public class DozeMachineTest extends SysuiTestCase { return null; }).when(mPartMock).transitionTo(any(), any()); - mMachine.requestPulse(DozeEvent.PULSE_REASON_NOTIFICATION); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 775acdf58c64..ff03fbae3f3a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -115,14 +115,14 @@ public class DozeSensorsTest extends SysuiTestCase { mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class)); mTestableLooper.processAllMessages(); - verify(mCallback).onSensorPulse(eq(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN), + verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN), anyFloat(), anyFloat(), eq(null)); mDozeSensors.requestTemporaryDisable(); reset(mCallback); mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class)); mTestableLooper.processAllMessages(); - verify(mCallback, never()).onSensorPulse(eq(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN), + verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN), anyFloat(), anyFloat(), eq(null)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index bf1060905f10..debc9d6430e0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -165,10 +165,10 @@ public class DozeTriggersTest extends SysuiTestCase { @Test public void testProximitySensorNotAvailablel() { mProximitySensor.setSensorAvailable(false); - mTriggers.onSensor(DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, 100, 100, null); - mTriggers.onSensor(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, 100, 100, + mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, 100, 100, null); + mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, 100, 100, new float[]{1}); - mTriggers.onSensor(DozeEvent.REASON_SENSOR_TAP, 100, 100, null); + mTriggers.onSensor(DozeLog.REASON_SENSOR_TAP, 100, 100, null); } private void waitForSensorManager() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java index c9b6790166e3..92c1d7601106 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java @@ -51,6 +51,7 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.util.wakelock.SettableWakeLock; @@ -87,6 +88,8 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { private SettableWakeLock mMediaWakeLock; @Mock private DozeParameters mDozeParameters; + @Mock + private NextAlarmController mNextAlarmController; private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private TestableKeyguardSliceProvider mProvider; private boolean mIsZenMode; @@ -97,9 +100,9 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class); mIsZenMode = false; mProvider = new TestableKeyguardSliceProvider(); + mProvider.setContextAvailableCallback(context -> { }); mProvider.attachInfo(getContext(), null); - mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController, - mKeyguardBypassController, mDozeParameters); + reset(mContentResolver); SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST))); } @@ -254,13 +257,16 @@ public class KeyguardSliceProviderTest extends SysuiTestCase { } @Override - public boolean onCreateSliceProvider() { - super.onCreateSliceProvider(); + protected void inject() { mAlarmManager = KeyguardSliceProviderTest.this.mAlarmManager; mContentResolver = KeyguardSliceProviderTest.this.mContentResolver; mZenModeController = KeyguardSliceProviderTest.this.mZenModeController; mMediaWakeLock = KeyguardSliceProviderTest.this.mMediaWakeLock; - return true; + mDozeParameters = KeyguardSliceProviderTest.this.mDozeParameters; + mNextAlarmController = KeyguardSliceProviderTest.this.mNextAlarmController; + mStatusBarStateController = KeyguardSliceProviderTest.this.mStatusBarStateController; + mKeyguardBypassController = KeyguardSliceProviderTest.this.mKeyguardBypassController; + mMediaManager = KeyguardSliceProviderTest.this.mNotificationMediaManager; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java deleted file mode 100644 index de6c87c7ff01..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/recents/model/TaskKeyLruCacheTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.shared.recents.model; - - -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNull; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import android.test.suitebuilder.annotation.SmallTest; - -import com.android.systemui.SysuiTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -@SmallTest -@RunWith(MockitoJUnitRunner.class) -public class TaskKeyLruCacheTest extends SysuiTestCase { - private static int sCacheSize = 3; - private static int sIdTask1 = 1; - private static int sIdTask2 = 2; - private static int sIdTask3 = 3; - private static int sIdUser1 = 1; - - TaskKeyLruCache.EvictionCallback mEvictionCallback; - - TaskKeyLruCache<Integer> mCache; - private Task.TaskKey mKey1; - private Task.TaskKey mKey2; - private Task.TaskKey mKey3; - - @Before - public void setup() { - mEvictionCallback = mock(TaskKeyLruCache.EvictionCallback.class); - mCache = new TaskKeyLruCache<>(sCacheSize, mEvictionCallback); - - mKey1 = new Task.TaskKey(sIdTask1, 0, null, null, sIdUser1, System.currentTimeMillis()); - mKey2 = new Task.TaskKey(sIdTask2, 0, null, null, sIdUser1, System.currentTimeMillis()); - mKey3 = new Task.TaskKey(sIdTask3, 0, null, null, sIdUser1, System.currentTimeMillis()); - } - - @Test - public void addSingleItem_get_success() { - mCache.put(mKey1, 1); - - assertEquals(1, (int) mCache.get(mKey1)); - } - - @Test - public void addSingleItem_getUninsertedItem_returnsNull() { - mCache.put(mKey1, 1); - - assertNull(mCache.get(mKey2)); - } - - @Test - public void emptyCache_get_returnsNull() { - assertNull(mCache.get(mKey1)); - } - - @Test - public void updateItem_get_returnsSecond() { - mCache.put(mKey1, 1); - mCache.put(mKey1, 2); - - assertEquals(2, (int) mCache.get(mKey1)); - assertEquals(1, mCache.mKeys.size()); - } - - @Test - public void fillCache_put_evictsOldest() { - mCache.put(mKey1, 1); - mCache.put(mKey2, 2); - mCache.put(mKey3, 3); - Task.TaskKey key4 = new Task.TaskKey(sIdTask3 + 1, 0, - null, null, sIdUser1, System.currentTimeMillis()); - mCache.put(key4, 4); - - assertNull(mCache.get(mKey1)); - assertEquals(3, mCache.mKeys.size()); - assertEquals(mKey2, mCache.mKeys.valueAt(0)); - verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1); - } - - @Test - public void fillCache_remove_success() { - mCache.put(mKey1, 1); - mCache.put(mKey2, 2); - mCache.put(mKey3, 3); - - mCache.remove(mKey2); - - assertNull(mCache.get(mKey2)); - assertEquals(2, mCache.mKeys.size()); - verify(mEvictionCallback, times(0)).onEntryEvicted(mKey2); - } - - @Test - public void put_evictionCallback_notCalled() { - mCache.put(mKey1, 1); - verify(mEvictionCallback, times(0)).onEntryEvicted(mKey1); - } - - @Test - public void evictAll_evictionCallback_called() { - mCache.put(mKey1, 1); - mCache.evictAllCache(); - verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1); - } - - @Test - public void trimAll_evictionCallback_called() { - mCache.put(mKey1, 1); - mCache.put(mKey2, 2); - mCache.trimToSize(-1); - verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1); - verify(mEvictionCallback, times(1)).onEntryEvicted(mKey2); - - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index 3a6accea2b54..c6d57e6df028 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -95,7 +95,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; - private int mCurrentUserId; + private UserInfo mCurrentUser; + private UserInfo mSecondaryUser; + private UserInfo mWorkUser; private TestNotificationLockscreenUserManager mLockscreenUserManager; @Before @@ -103,10 +105,14 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); - mCurrentUserId = ActivityManager.getCurrentUser(); + int currentUserId = ActivityManager.getCurrentUser(); + mCurrentUser = new UserInfo(currentUserId, "", 0); + mSecondaryUser = new UserInfo(currentUserId + 1, "", 0); + mWorkUser = new UserInfo(currentUserId + 2, "" /* name */, null /* iconPath */, 0, + UserManager.USER_TYPE_PROFILE_MANAGED); - when(mUserManager.getProfiles(mCurrentUserId)).thenReturn(Lists.newArrayList( - new UserInfo(mCurrentUserId, "", 0), new UserInfo(mCurrentUserId + 1, "", 0))); + when(mUserManager.getProfiles(currentUserId)).thenReturn(Lists.newArrayList( + mCurrentUser, mSecondaryUser, mWorkUser)); mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler.createAsync(Looper.myLooper())); @@ -141,15 +147,31 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); - assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUserId)); + assertTrue(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id)); } @Test public void testLockScreenAllowPrivateNotificationsFalse() { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, mCurrentUser.id); + mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); + assertFalse(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id)); + } + + @Test + public void testLockScreenAllowsWorkPrivateNotificationsFalse() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, mWorkUser.id); + mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); + assertFalse(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic()); + } + + @Test + public void testLockScreenAllowsWorkPrivateNotificationsTrue() { + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mWorkUser.id); mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false); - assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUserId)); + assertTrue(mLockscreenUserManager.allowsManagedPrivateNotificationsInPublic()); } @Test @@ -163,16 +185,16 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { public void testActionUserSwitchedCallsOnUserSwitched() { Intent intent = new Intent() .setAction(ACTION_USER_SWITCHED) - .putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId + 1); + .putExtra(Intent.EXTRA_USER_HANDLE, mSecondaryUser.id); mLockscreenUserManager.getBaseBroadcastReceiverForTest().onReceive(mContext, intent); - verify(mPresenter, times(1)).onUserSwitched(mCurrentUserId + 1); + verify(mPresenter, times(1)).onUserSwitched(mSecondaryUser.id); } @Test public void testIsLockscreenPublicMode() { - assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUserId)); - mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUserId); - assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUserId)); + assertFalse(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id)); + mLockscreenUserManager.setLockscreenPublicMode(true, mCurrentUser.id); + assertTrue(mLockscreenUserManager.isLockscreenPublicMode(mCurrentUser.id)); } @Test 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 7602e45c1672..5bd5638b3d5a 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 @@ -54,6 +54,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -130,6 +131,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private ZenModeController mZenModeController; @Mock private NotificationSectionsManager mNotificationSectionsManager; @Mock private NotificationSection mNotificationSection; + @Mock private NotificationLockscreenUserManager mLockscreenUserManager; + private UserChangedListener mUserChangedListener; private TestableNotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; @@ -156,6 +159,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectMockDependency(ShadeController.class); when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController); + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); mEntryManager = new TestableNotificationEntryManager( mock(NotifLog.class), mock(NotificationGroupManager.class), @@ -195,10 +200,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mHeadsUpManager, mKeyguardBypassController, new FalsingManagerFake(), - mock(NotificationLockscreenUserManager.class), + mLockscreenUserManager, mock(NotificationGutsManager.class), mZenModeController, mNotificationSectionsManager); + verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture()); + mUserChangedListener = userChangedCaptor.getValue(); mStackScroller = spy(mStackScrollerInternal); mStackScroller.setShelf(notificationShelf); mStackScroller.setStatusBar(mBar); @@ -279,6 +286,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testOnStatePostChange_verifyIfProfileIsPublic() { + mUserChangedListener.onUserChanged(0); + verify(mLockscreenUserManager).isAnyProfilePublicMode(); + } + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index 3c6a69882d44..a6e29181e435 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -36,7 +36,6 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.assist.AssistManager; -import com.android.systemui.doze.DozeEvent; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -144,13 +143,13 @@ public class DozeServiceHostTest extends SysuiTestCase { @Override public void onPulseFinished() { } - }, DozeEvent.PULSE_REASON_NOTIFICATION); + }, DozeLog.PULSE_REASON_NOTIFICATION); ArgumentCaptor<DozeHost.PulseCallback> pulseCallbackArgumentCaptor = ArgumentCaptor.forClass(DozeHost.PulseCallback.class); verify(mDozeScrimController).pulse( - pulseCallbackArgumentCaptor.capture(), eq(DozeEvent.PULSE_REASON_NOTIFICATION)); + pulseCallbackArgumentCaptor.capture(), eq(DozeLog.PULSE_REASON_NOTIFICATION)); verify(mStatusBar).updateScrimController(); reset(mStatusBar); @@ -162,21 +161,21 @@ public class DozeServiceHostTest extends SysuiTestCase { @Test public void testPulseWhileDozing_notifyAuthInterrupt() { HashSet<Integer> reasonsWantingAuth = new HashSet<>( - Collections.singletonList(DozeEvent.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); + Collections.singletonList(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN)); HashSet<Integer> reasonsSkippingAuth = new HashSet<>( - Arrays.asList(DozeEvent.PULSE_REASON_INTENT, - DozeEvent.PULSE_REASON_NOTIFICATION, - DozeEvent.PULSE_REASON_SENSOR_SIGMOTION, - DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.PULSE_REASON_SENSOR_LONG_PRESS, - DozeEvent.PULSE_REASON_DOCKING, - DozeEvent.REASON_SENSOR_WAKE_UP, - DozeEvent.REASON_SENSOR_TAP)); + Arrays.asList(DozeLog.PULSE_REASON_INTENT, + DozeLog.PULSE_REASON_NOTIFICATION, + DozeLog.PULSE_REASON_SENSOR_SIGMOTION, + DozeLog.REASON_SENSOR_PICKUP, + DozeLog.REASON_SENSOR_DOUBLE_TAP, + DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, + DozeLog.PULSE_REASON_DOCKING, + DozeLog.REASON_SENSOR_WAKE_UP, + DozeLog.REASON_SENSOR_TAP)); HashSet<Integer> reasonsThatDontPulse = new HashSet<>( - Arrays.asList(DozeEvent.REASON_SENSOR_PICKUP, - DozeEvent.REASON_SENSOR_DOUBLE_TAP, - DozeEvent.REASON_SENSOR_TAP)); + Arrays.asList(DozeLog.REASON_SENSOR_PICKUP, + DozeLog.REASON_SENSOR_DOUBLE_TAP, + DozeLog.REASON_SENSOR_TAP)); doAnswer(invocation -> { DozeHost.PulseCallback callback = invocation.getArgument(0); @@ -185,7 +184,7 @@ public class DozeServiceHostTest extends SysuiTestCase { }).when(mDozeScrimController).pulse(any(), anyInt()); mDozeServiceHost.mWakeLockScreenPerformsAuth = true; - for (int i = 0; i < DozeEvent.TOTAL_REASONS; i++) { + for (int i = 0; i < DozeLog.TOTAL_REASONS; i++) { reset(mKeyguardUpdateMonitor); mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class), i); if (reasonsWantingAuth.contains(i)) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index 1f37ad8b2b1c..5fb71599e2a0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -55,7 +55,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.doze.DozeLog; import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.KeyguardAffordanceView; @@ -133,8 +132,6 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private DynamicPrivacyController mDynamicPrivacyController; @Mock - private PluginManager mPluginManager; - @Mock private ShadeController mShadeController; @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager; @@ -218,7 +215,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { mNotificationPanelViewController = new NotificationPanelViewController(mView, mInjectionInflationController, coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController, - mFalsingManager, mPluginManager, mShadeController, + mFalsingManager, mShadeController, mNotificationLockscreenUserManager, mNotificationEntryManager, mKeyguardStateController, mStatusBarStateController, mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index cc3c3ccdc316..294d546e087b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -30,6 +30,7 @@ import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -43,6 +44,7 @@ import android.os.Handler; import android.provider.Settings; import android.provider.Settings.Global; import android.telephony.CdmaEriInformation; +import android.telephony.CellSignalStrength; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -56,7 +58,6 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; -import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.graph.SignalDrawable; import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; @@ -95,6 +96,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected PhoneStateListener mPhoneStateListener; protected SignalStrength mSignalStrength; protected ServiceState mServiceState; + protected NetworkRegistrationInfo mFakeRegInfo; protected ConnectivityManager mMockCm; protected WifiManager mMockWm; protected SubscriptionManager mMockSm; @@ -158,6 +160,14 @@ public class NetworkControllerBaseTest extends SysuiTestCase { mSignalStrength = mock(SignalStrength.class); mServiceState = mock(ServiceState.class); + mFakeRegInfo = new NetworkRegistrationInfo.Builder() + .setTransportType(TRANSPORT_TYPE_WWAN) + .setDomain(DOMAIN_PS) + .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) + .build(); + doReturn(mFakeRegInfo).when(mServiceState) + .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN); + mEriInformation = new CdmaEriInformation(CdmaEriInformation.ERI_OFF, CdmaEriInformation.ERI_ICON_MODE_NORMAL); when(mMockTm.getCdmaEriInformation()).thenReturn(mEriInformation); @@ -219,7 +229,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { subs.add(subscription); } when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs); - when(mMockSm.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subs); + when(mMockSm.getActiveAndHiddenSubscriptionInfoList()).thenReturn(subs); mNetworkController.doUpdateMobileControllers(); } @@ -405,7 +415,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); - int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, + int state = SignalDrawable.getState(icon, CellSignalStrength.getNumSignalStrengthLevels(), false); assertEquals("Visibility in, quick settings", visible, iconState.visible); assertEquals("Signal icon in, quick settings", state, iconState.icon); @@ -440,7 +450,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase { IconState iconState = iconArg.getValue(); int state = icon == -1 ? 0 - : SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, !inet); + : SignalDrawable.getState(icon, CellSignalStrength.getNumSignalStrengthLevels(), + !inet); assertEquals("Signal icon in status bar", state, iconState.icon); assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue()); assertEquals("Visibility in status bar", visible, iconState.visible); @@ -483,7 +494,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { IconState iconState = iconArg.getValue(); - int numSignalStrengthBins = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; + int numSignalStrengthBins = CellSignalStrength.getNumSignalStrengthLevels(); if (mMobileSignalController.mInflateSignalStrengths) { numSignalStrengthBins++; icon++; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index f6c750db56b7..1eb59396e525 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -187,7 +187,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_LTE); updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED); mPhoneStateListener.onServiceStateChanged(ss); verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, TelephonyIcons.ICON_5G, @@ -202,7 +202,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyManager.NETWORK_TYPE_LTE); updateDataActivity(TelephonyManager.DATA_ACTIVITY_DORMANT); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED); mPhoneStateListener.onServiceStateChanged(ss); verifyDataIndicators(TelephonyIcons.ICON_5G); @@ -215,7 +215,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange(); mPhoneStateListener.onServiceStateChanged(ss); @@ -229,7 +229,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss).getNrFrequencyRange(); mPhoneStateListener.onServiceStateChanged(ss); @@ -243,7 +243,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_RESTRICTED); mPhoneStateListener.onServiceStateChanged(mServiceState); verifyDataIndicators(TelephonyIcons.ICON_LTE); @@ -259,7 +259,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { ServiceState ss = Mockito.mock(ServiceState.class); // While nrIconDisplayGracePeriodMs > 0 & is Nr5G, mIsShowingIconGracefully should be true - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -278,7 +278,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { assertTrue(mConfig.nrIconDisplayGracePeriodMs == 0); // While nrIconDisplayGracePeriodMs <= 0, mIsShowingIconGracefully should be false - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); + setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -295,7 +295,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mPhoneStateListener.onServiceStateChanged(mServiceState); ServiceState ss = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -305,7 +305,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // Enabled timer Nr5G switch to None Nr5G, showing 5G icon gracefully ServiceState ssLte = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(ssLte).getNrState(); + setNrState(ssLte, NetworkRegistrationInfo.NR_STATE_NONE); doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ssLte).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -321,14 +321,14 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setupDefaultSignal(); mNetworkController.handleConfigurationChanged(); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); + setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); verifyDataIndicators(TelephonyIcons.ICON_5G); - doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState(); + setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_NONE); doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -342,7 +342,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds(); setupDefaultSignal(); mNetworkController.handleConfigurationChanged(); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); + setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -352,7 +352,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // Disabled timer, when out of service, reset timer to display latest state updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState(); + setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_NONE); doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_DISCONNECTED, TelephonyManager.NETWORK_TYPE_UMTS); @@ -369,7 +369,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mPhoneStateListener.onServiceStateChanged(mServiceState); ServiceState ss5G = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5G).getNrState(); + setNrState(ss5G, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss5G).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -379,7 +379,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // When timeout enabled, 5G/5G+ switching should be updated immediately ServiceState ss5GPlus = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5GPlus).getNrState(); + setNrState(ss5GPlus, NetworkRegistrationInfo.NR_STATE_CONNECTED); doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss5GPlus).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -396,22 +396,21 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mNetworkController.handleConfigurationChanged(); mPhoneStateListener.onServiceStateChanged(mServiceState); - ServiceState ss5G = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5G).getNrState(); - doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss5G).getNrFrequencyRange(); + ServiceState ss = Mockito.mock(ServiceState.class); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED); + doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - mPhoneStateListener.onServiceStateChanged(ss5G); + mPhoneStateListener.onServiceStateChanged(ss); verifyDataIndicators(TelephonyIcons.ICON_5G); // State from NR_5G to NONE NR_5G with timeout, should show previous 5G icon - ServiceState ssLte = Mockito.mock(ServiceState.class); - doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(ssLte).getNrState(); - doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ssLte).getNrFrequencyRange(); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_NONE); + doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ss).getNrFrequencyRange(); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - mPhoneStateListener.onServiceStateChanged(ssLte); + mPhoneStateListener.onServiceStateChanged(ss); verifyDataIndicators(TelephonyIcons.ICON_5G); @@ -420,14 +419,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { mNetworkController.handleConfigurationChanged(); // State from NR_5G to NONE NR_STATE_RESTRICTED, showing corresponding icon - doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState(); - NetworkRegistrationInfo fakeRegInfo = new NetworkRegistrationInfo.Builder() - .setTransportType(TRANSPORT_TYPE_WWAN) - .setDomain(DOMAIN_PS) - .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE) - .build(); - doReturn(fakeRegInfo).when(mServiceState) - .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN); + setNrState(ss, NetworkRegistrationInfo.NR_STATE_RESTRICTED); mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); @@ -531,4 +523,10 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { true, DEFAULT_QS_SIGNAL_STRENGTH, dataIcon, false, false); } + + private void setNrState(ServiceState ss, int nrState) { + mFakeRegInfo.setNrState(nrState); + doReturn(mFakeRegInfo).when(ss) + .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 4406248ec9ea..f52c8c17bfa5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -136,7 +136,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testSignalStrength() { for (int testStrength = 0; - testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { + testStrength < CellSignalStrength.getNumSignalStrengthLevels(); testStrength++) { setupDefaultSignal(); setLevel(testStrength); @@ -153,7 +153,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testCdmaSignalStrength() { for (int testStrength = 0; - testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { + testStrength < CellSignalStrength.getNumSignalStrengthLevels(); testStrength++) { setupDefaultSignal(); setCdma(); setLevel(testStrength); @@ -167,7 +167,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testSignalRoaming() { for (int testStrength = 0; - testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { + testStrength < CellSignalStrength.getNumSignalStrengthLevels(); testStrength++) { setupDefaultSignal(); setGsmRoaming(true); setLevel(testStrength); @@ -494,7 +494,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Carrier network change is true, show special indicator verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), 0 /* typeIcon */); // Revert back @@ -525,7 +525,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Carrier network change is true, show special indicator, no roaming. verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), 0 /* typeIcon */, false /* roaming */); @@ -557,7 +557,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Carrier network change is true, show special indicator, no roaming. verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), 0 /* typeIcon */, false /* roaming */); @@ -565,7 +565,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Roaming should not show. verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), + SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), 0 /* typeIcon */, false /* roaming */); diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt index 35e0f88e70fa..1403bba3445a 100644 --- a/packages/Tethering/common/TetheringLib/jarjar-rules.txt +++ b/packages/Tethering/common/TetheringLib/jarjar-rules.txt @@ -1 +1,2 @@ rule android.annotation.** com.android.networkstack.tethering.annotation.@1 +rule com.android.internal.annotations.** com.android.networkstack.tethering.annotation.@1
\ No newline at end of file diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index 37ce1d57da36..53a358f29a97 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -30,6 +30,9 @@ import android.os.ResultReceiver; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -37,6 +40,7 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.Supplier; /** * This class provides the APIs to control the tethering service. @@ -50,17 +54,23 @@ import java.util.concurrent.Executor; public class TetheringManager { private static final String TAG = TetheringManager.class.getSimpleName(); private static final int DEFAULT_TIMEOUT_MS = 60_000; + private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L; - private static TetheringManager sInstance; + @GuardedBy("mConnectorWaitQueue") + @Nullable + private ITetheringConnector mConnector; + @GuardedBy("mConnectorWaitQueue") + @NonNull + private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>(); + private final Supplier<IBinder> mConnectorSupplier; - private final ITetheringConnector mConnector; private final TetheringCallbackInternal mCallback; private final Context mContext; private final ArrayMap<TetheringEventCallback, ITetheringEventCallback> mTetheringEventCallbacks = new ArrayMap<>(); - private TetheringConfigurationParcel mTetheringConfiguration; - private TetherStatesParcel mTetherStatesParcel; + private volatile TetheringConfigurationParcel mTetheringConfiguration; + private volatile TetherStatesParcel mTetherStatesParcel; /** * Broadcast Action: A tetherable connection has come or gone. @@ -162,29 +172,139 @@ public class TetheringManager { /** * Create a TetheringManager object for interacting with the tethering service. * + * @param context Context for the manager. + * @param connectorSupplier Supplier for the manager connector; may return null while the + * service is not connected. * {@hide} */ - public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) { + public TetheringManager(@NonNull final Context context, + @NonNull Supplier<IBinder> connectorSupplier) { mContext = context; - mConnector = ITetheringConnector.Stub.asInterface(service); mCallback = new TetheringCallbackInternal(); + mConnectorSupplier = connectorSupplier; final String pkgName = mContext.getOpPackageName(); + + final IBinder connector = mConnectorSupplier.get(); + // If the connector is available on start, do not start a polling thread. This introduces + // differences in the thread that sends the oneway binder calls to the service between the + // first few seconds after boot and later, but it avoids always having differences between + // the first usage of TetheringManager from a process and subsequent usages (so the + // difference is only on boot). On boot binder calls may be queued until the service comes + // up and be sent from a worker thread; later, they are always sent from the caller thread. + // Considering that it's just oneway binder calls, and ordering is preserved, this seems + // better than inconsistent behavior persisting after boot. + if (connector != null) { + mConnector = ITetheringConnector.Stub.asInterface(connector); + } else { + startPollingForConnector(); + } + Log.i(TAG, "registerTetheringEventCallback:" + pkgName); + getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName)); + } + + private void startPollingForConnector() { + new Thread(() -> { + while (true) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + // Not much to do here, the system needs to wait for the connector + } + + final IBinder connector = mConnectorSupplier.get(); + if (connector != null) { + onTetheringConnected(ITetheringConnector.Stub.asInterface(connector)); + return; + } + } + }).start(); + } + + private interface ConnectorConsumer { + void onConnectorAvailable(ITetheringConnector connector) throws RemoteException; + } + + private void onTetheringConnected(ITetheringConnector connector) { + // Process the connector wait queue in order, including any items that are added + // while processing. + // + // 1. Copy the queue to a local variable under lock. + // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands + // would block on the lock). + // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1. + // If not, set mConnector to non-null so future tasks are run immediately, not queued. + // + // For this to work, all calls to the tethering service must use getConnector(), which + // ensures that tasks are added to the queue with the lock held. + // + // Once mConnector is set to non-null, it will never be null again. If the network stack + // process crashes, no recovery is possible. + // TODO: evaluate whether it is possible to recover from network stack process crashes + // (though in most cases the system will have crashed when the network stack process + // crashes). + do { + final List<ConnectorConsumer> localWaitQueue; + synchronized (mConnectorWaitQueue) { + localWaitQueue = new ArrayList<>(mConnectorWaitQueue); + mConnectorWaitQueue.clear(); + } + + // Allow more tasks to be added at the end without blocking while draining the queue. + for (ConnectorConsumer task : localWaitQueue) { + try { + task.onConnectorAvailable(connector); + } catch (RemoteException e) { + // Most likely the network stack process crashed, which is likely to crash the + // system. Keep processing other requests but report the error loudly. + Log.wtf(TAG, "Error processing request for the tethering connector", e); + } + } + + synchronized (mConnectorWaitQueue) { + if (mConnectorWaitQueue.size() == 0) { + mConnector = connector; + return; + } + } + } while (true); + } + + /** + * Asynchronously get the ITetheringConnector to execute some operation. + * + * <p>If the connector is already available, the operation will be executed on the caller's + * thread. Otherwise it will be queued and executed on a worker thread. The operation should be + * limited to performing oneway binder calls to minimize differences due to threading. + */ + private void getConnector(ConnectorConsumer consumer) { + final ITetheringConnector connector; + synchronized (mConnectorWaitQueue) { + connector = mConnector; + if (connector == null) { + mConnectorWaitQueue.add(consumer); + return; + } + } + try { - mConnector.registerTetheringEventCallback(mCallback, pkgName); + consumer.onConnectorAvailable(connector); } catch (RemoteException e) { throw new IllegalStateException(e); } } private interface RequestHelper { - void runRequest(IIntResultListener listener); + void runRequest(ITetheringConnector connector, IIntResultListener listener); } + // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to + // return results and perform operations synchronously. + // TODO: remove once there are no callers of these legacy methods. private class RequestDispatcher { private final ConditionVariable mWaiting; - public int mRemoteResult; + public volatile int mRemoteResult; private final IIntResultListener mListener = new IIntResultListener.Stub() { @Override @@ -199,7 +319,7 @@ public class TetheringManager { } int waitForResult(final RequestHelper request) { - request.runRequest(mListener); + getConnector(c -> request.runRequest(c, mListener)); if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) { throw new IllegalStateException("Callback timeout"); } @@ -222,7 +342,7 @@ public class TetheringManager { } private class TetheringCallbackInternal extends ITetheringEventCallback.Stub { - private int mError = TETHER_ERROR_NO_ERROR; + private volatile int mError = TETHER_ERROR_NO_ERROR; private final ConditionVariable mWaitForCallback = new ConditionVariable(); @Override @@ -280,9 +400,9 @@ public class TetheringManager { Log.i(TAG, "tether caller:" + callerPkg); final RequestDispatcher dispatcher = new RequestDispatcher(); - return dispatcher.waitForResult(listener -> { + return dispatcher.waitForResult((connector, listener) -> { try { - mConnector.tether(iface, callerPkg, listener); + connector.tether(iface, callerPkg, listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -304,9 +424,9 @@ public class TetheringManager { final RequestDispatcher dispatcher = new RequestDispatcher(); - return dispatcher.waitForResult(listener -> { + return dispatcher.waitForResult((connector, listener) -> { try { - mConnector.untether(iface, callerPkg, listener); + connector.untether(iface, callerPkg, listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -330,9 +450,9 @@ public class TetheringManager { final RequestDispatcher dispatcher = new RequestDispatcher(); - return dispatcher.waitForResult(listener -> { + return dispatcher.waitForResult((connector, listener) -> { try { - mConnector.setUsbTethering(enable, callerPkg, listener); + connector.setUsbTethering(enable, callerPkg, listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -467,11 +587,7 @@ public class TetheringManager { }); } }; - try { - mConnector.startTethering(request.getParcel(), callerPkg, listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } + getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener)); } /** @@ -509,15 +625,15 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); Log.i(TAG, "stopTethering caller:" + callerPkg); - final RequestDispatcher dispatcher = new RequestDispatcher(); - - dispatcher.waitForResult(listener -> { - try { - mConnector.stopTethering(type, callerPkg, listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); + getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() { + @Override + public void onResult(int resultCode) { + // TODO: provide an API to obtain result + // This has never been possible as stopTethering has always been void and never + // taken a callback object. The only indication that callers have is if the call + // results in a TETHER_STATE_CHANGE broadcast. } - }); + })); } /** @@ -591,12 +707,8 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg); - try { - mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi, - callerPkg); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } + getConnector(c -> c.requestLatestTetheringEntitlementResult( + type, receiver, showEntitlementUi, callerPkg)); } /** @@ -832,11 +944,7 @@ public class TetheringManager { }); } }; - try { - mConnector.registerTetheringEventCallback(remoteCallback, callerPkg); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } + getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg)); mTetheringEventCallbacks.put(callback, remoteCallback); } } @@ -860,11 +968,8 @@ public class TetheringManager { if (remoteCallback == null) { throw new IllegalArgumentException("callback was not registered."); } - try { - mConnector.unregisterTetheringEventCallback(remoteCallback, callerPkg); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } + + getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg)); } } @@ -1002,9 +1107,9 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); final RequestDispatcher dispatcher = new RequestDispatcher(); - final int ret = dispatcher.waitForResult(listener -> { + final int ret = dispatcher.waitForResult((connector, listener) -> { try { - mConnector.isTetheringSupported(callerPkg, listener); + connector.isTetheringSupported(callerPkg, listener); } catch (RemoteException e) { throw new IllegalStateException(e); } @@ -1027,13 +1132,14 @@ public class TetheringManager { final String callerPkg = mContext.getOpPackageName(); Log.i(TAG, "stopAllTethering caller:" + callerPkg); - final RequestDispatcher dispatcher = new RequestDispatcher(); - dispatcher.waitForResult(listener -> { - try { - mConnector.stopAllTethering(callerPkg, listener); - } catch (RemoteException e) { - throw new IllegalStateException(e); + getConnector(c -> c.stopAllTethering(callerPkg, new IIntResultListener.Stub() { + @Override + public void onResult(int resultCode) { + // TODO: add an API parameter to send result to caller. + // This has never been possible as stopAllTethering has always been void and never + // taken a callback object. The only indication that callers have is if the call + // results in a TETHER_STATE_CHANGE broadcast. } - }); + })); } } diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp index 083dac944936..cd804b2c8514 100644 --- a/packages/WAPPushManager/Android.bp +++ b/packages/WAPPushManager/Android.bp @@ -4,7 +4,6 @@ android_app { name: "WAPPushManager", srcs: ["src/**/*.java"], platform_apis: true, - libs: ["telephony-common"], static_libs: ["android-common"], optimize: { proguard_flags_files: ["proguard.flags"], diff --git a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java index 950107301af3..fcb113e90720 100644 --- a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java +++ b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java @@ -26,7 +26,6 @@ import android.util.Log; import android.util.Pools.Pool; import android.util.Pools.SynchronizedPool; import android.view.View; -import android.view.WindowManager; import com.android.gallery3d.common.Utils; import com.android.gallery3d.glrenderer.BasicTexture; @@ -164,9 +163,7 @@ public class TiledImageRenderer { private static boolean isHighResolution(Context context) { DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) - context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); + context.getDisplay().getMetrics(metrics); return metrics.heightPixels > 2048 || metrics.widthPixels > 2048; } diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java index f878b4d11f72..6112da5cd13b 100644 --- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java +++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java @@ -37,9 +37,9 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; +import android.util.Size; import android.view.Display; import android.view.View; -import android.view.WindowManager; import android.widget.Toast; import com.android.gallery3d.common.Utils; @@ -231,18 +231,18 @@ public class WallpaperCropActivity extends Activity { return x * aspectRatio + y; } - static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) { + static protected Point getDefaultWallpaperSize(Resources res, Display display) { if (sDefaultWallpaperSize == null) { Point minDims = new Point(); Point maxDims = new Point(); - windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims); + display.getCurrentSizeRange(minDims, maxDims); int maxDim = Math.max(maxDims.x, maxDims.y); int minDim = Math.max(minDims.x, minDims.y); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { Point realSize = new Point(); - windowManager.getDefaultDisplay().getRealSize(realSize); + display.getRealSize(realSize); maxDim = Math.max(realSize.x, realSize.y); minDim = Math.min(realSize.x, realSize.y); } @@ -331,8 +331,7 @@ public class WallpaperCropActivity extends Activity { // this device int rotation = getRotationFromExif(res, resId); Point inSize = mCropView.getSourceDimensions(); - Point outSize = getDefaultWallpaperSize(getResources(), - getWindowManager()); + Point outSize = getDefaultWallpaperSize(getResources(), getDisplay()); RectF crop = getMaxCropRect( inSize.x, inSize.y, outSize.x, outSize.y, false); Runnable onEndCrop = new Runnable() { @@ -359,14 +358,11 @@ public class WallpaperCropActivity extends Activity { // Get the crop boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; - Display d = getWindowManager().getDefaultDisplay(); - - Point displaySize = new Point(); - d.getSize(displaySize); - boolean isPortrait = displaySize.x < displaySize.y; + Size windowSize = getWindowManager().getCurrentWindowMetrics().getSize(); + boolean isPortrait = windowSize.getWidth() < windowSize.getHeight(); Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(), - getWindowManager()); + getDisplay()); // Get the crop RectF cropRect = mCropView.getCrop(); diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 97f27caaad48..7151d2b86e83 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -98,7 +98,6 @@ import android.util.Xml; import android.util.proto.ProtoOutputStream; import android.view.Display; import android.view.View; -import android.view.WindowManager; import android.widget.RemoteViews; import com.android.internal.R; @@ -282,8 +281,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } private void computeMaximumWidgetBitmapMemory() { - WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); + Display display = mContext.getDisplay(); Point size = new Point(); display.getRealSize(size); // Cap memory usage at 1.5 times the size of the display diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index e28ef0f920e9..4f18f3547449 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -216,7 +216,7 @@ final class AutofillManagerServiceImpl updateRemoteAugmentedAutofillService(); final ComponentName componentName = RemoteInlineSuggestionRenderService - .getServiceComponentName(getContext()); + .getServiceComponentName(getContext(), mUserId); if (componentName != null) { mRemoteInlineSuggestionRenderService = new RemoteInlineSuggestionRenderService( getContext(), componentName, InlineSuggestionRenderService.SERVICE_INTERFACE, diff --git a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java index f9e08e683b6c..31dc23f0118d 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java @@ -20,6 +20,7 @@ import static com.android.server.autofill.Helper.sVerbose; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -86,7 +87,7 @@ final class RemoteInlineSuggestionRenderService extends } @Nullable - private static ServiceInfo getServiceInfo(Context context) { + private static ServiceInfo getServiceInfo(Context context, int userId) { final String packageName = context.getPackageManager().getServicesSystemSharedLibraryPackageName(); if (packageName == null) { @@ -96,8 +97,8 @@ final class RemoteInlineSuggestionRenderService extends final Intent intent = new Intent(InlineSuggestionRenderService.SERVICE_INTERFACE); intent.setPackage(packageName); - final ResolveInfo resolveInfo = context.getPackageManager().resolveService(intent, - PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + final ResolveInfo resolveInfo = context.getPackageManager().resolveServiceAsUser(intent, + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, userId); final ServiceInfo serviceInfo = resolveInfo == null ? null : resolveInfo.serviceInfo; if (resolveInfo == null || serviceInfo == null) { Slog.w(TAG, "No valid components found."); @@ -115,8 +116,8 @@ final class RemoteInlineSuggestionRenderService extends } @Nullable - public static ComponentName getServiceComponentName(Context context) { - final ServiceInfo serviceInfo = getServiceInfo(context); + public static ComponentName getServiceComponentName(Context context, @UserIdInt int userId) { + final ServiceInfo serviceInfo = getServiceInfo(context, userId); if (serviceInfo == null) return null; final ComponentName componentName = new ComponentName(serviceInfo.packageName, diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java b/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java index 6a1de6378a5e..205b7dda267e 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java @@ -16,7 +16,6 @@ package com.android.server.backup; -import static com.android.server.backup.BackupManagerService.DEBUG; import static com.android.server.backup.BackupManagerService.TAG; import android.util.Slog; @@ -33,10 +32,13 @@ final class UserBackupManagerFilePersistedSettings { private static final String BACKUP_ENABLE_FILE = "backup_enabled"; static boolean readBackupEnableState(int userId) { - return readBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId)); + boolean enabled = readBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId)); + Slog.d(TAG, "user:" + userId + " readBackupEnableState enabled:" + enabled); + return enabled; } static void writeBackupEnableState(int userId, boolean enable) { + Slog.d(TAG, "user:" + userId + " writeBackupEnableState enable:" + enable); writeBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId), enable); } @@ -45,15 +47,17 @@ final class UserBackupManagerFilePersistedSettings { if (enableFile.exists()) { try (FileInputStream fin = new FileInputStream(enableFile)) { int state = fin.read(); + if (state != 0 && state != 1) { + // TODO (b/148587496) handle instead of only logging + Slog.e(TAG, "Unexpected enabled state:" + state); + } return state != 0; } catch (IOException e) { // can't read the file; fall through to assume disabled Slog.e(TAG, "Cannot read enable state; assuming disabled"); } } else { - if (DEBUG) { - Slog.i(TAG, "isBackupEnabled() => false due to absent settings file"); - } + Slog.i(TAG, "isBackupEnabled() => false due to absent settings file"); } return false; } @@ -64,7 +68,11 @@ final class UserBackupManagerFilePersistedSettings { try (FileOutputStream fout = new FileOutputStream(stage)) { fout.write(enable ? 1 : 0); fout.close(); - stage.renameTo(enableFile); + boolean renamed = stage.renameTo(enableFile); + if (!renamed) { + // TODO (b/148587496) handle instead of only logging + Slog.e(TAG, "Write enable failed as could not rename staging file to actual"); + } // will be synced immediately by the try-with-resources call to close() } catch (IOException | RuntimeException e) { Slog.e( diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 8074900d2776..c8894e79ac0c 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -18,6 +18,7 @@ package com.android.server; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.content.ContentResolver; @@ -1318,8 +1319,7 @@ public final class BatteryService extends SystemService { * * @hide Should only be used internally. */ - @VisibleForTesting - static final class HealthServiceWrapper { + public static final class HealthServiceWrapper { private static final String TAG = "HealthServiceWrapper"; public static final String INSTANCE_HEALTHD = "backup"; public static final String INSTANCE_VENDOR = "default"; @@ -1341,20 +1341,28 @@ public final class BatteryService extends SystemService { * init should be called after constructor. For testing purposes, init is not called by * constructor. */ - HealthServiceWrapper() { + public HealthServiceWrapper() { } - IHealth getLastService() { + public IHealth getLastService() { return mLastService.get(); } /** + * See {@link #init(Callback, IServiceManagerSupplier, IHealthSupplier)} + */ + public void init() throws RemoteException, NoSuchElementException { + init(/* callback= */null, new HealthServiceWrapper.IServiceManagerSupplier() {}, + new HealthServiceWrapper.IHealthSupplier() {}); + } + + /** * Start monitoring registration of new IHealth services. Only instances that are in * {@code sAllInstances} and in device / framework manifest are used. This function should * only be called once. * * mCallback.onRegistration() is called synchronously (aka in init thread) before - * this method returns. + * this method returns if callback is not null. * * @throws RemoteException transaction error when talking to IServiceManager * @throws NoSuchElementException if one of the following cases: @@ -1362,18 +1370,17 @@ public final class BatteryService extends SystemService { * - none of {@code sAllInstances} are in manifests (i.e. not * available on this device), or none of these instances are available to current * process. - * @throws NullPointerException when callback is null or supplier is null + * @throws NullPointerException when supplier is null */ - void init(Callback callback, + void init(@Nullable Callback callback, IServiceManagerSupplier managerSupplier, IHealthSupplier healthSupplier) throws RemoteException, NoSuchElementException, NullPointerException { - if (callback == null || managerSupplier == null || healthSupplier == null) + if (managerSupplier == null || healthSupplier == null) { throw new NullPointerException(); - + } IServiceManager manager; - mCallback = callback; mHealthSupplier = healthSupplier; // Initialize mLastService and call callback for the first time (in init thread) @@ -1399,7 +1406,11 @@ public final class BatteryService extends SystemService { "No IHealth service instance among %s is available. Perhaps no permission?", sAllInstances.toString())); } - mCallback.onRegistration(null, newService, mInstanceName); + + if (callback != null) { + mCallback = callback; + mCallback.onRegistration(null, newService, mInstanceName); + } // Register for future service registrations traceBegin("HealthInitRegisterNotification"); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d933e9d8e9da..2982dc9fab1b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5537,20 +5537,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return nri.request.requestId == mDefaultRequest.requestId; } - // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent - // changes that would conflict throughout the automerger graph. Having this method temporarily - // helps with the process of going through with all these dependent changes across the entire - // tree. - /** - * Register a new agent. {@see #registerNetworkAgent} below. - */ - public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig) { - return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities, - currentScore, networkAgentConfig, NetworkProvider.ID_NONE); - } - /** * Register a new agent with ConnectivityService to handle a network. * @@ -5569,7 +5555,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { + NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { enforceNetworkFactoryPermission(); LinkProperties lp = new LinkProperties(linkProperties); @@ -5577,12 +5563,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, - mNetd, mDnsResolver, mNMS, providerId); + currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), + this, mNetd, mDnsResolver, mNMS, providerId); // Make sure the network capabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index f1f2d2abea3f..e342dd7977fb 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -30,7 +30,6 @@ import static android.os.PowerManager.locationPowerSaveModeToString; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -88,6 +87,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.server.location.AbstractLocationProvider; import com.android.server.location.AbstractLocationProvider.State; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.CallerIdentity; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; @@ -98,12 +98,12 @@ import com.android.server.location.LocationProviderProxy; import com.android.server.location.LocationRequestStatistics; import com.android.server.location.LocationRequestStatistics.PackageProviderKey; import com.android.server.location.LocationRequestStatistics.PackageStatistics; -import com.android.server.location.LocationSettingsStore; import com.android.server.location.LocationUsageLogger; import com.android.server.location.MockProvider; import com.android.server.location.MockableLocationProvider; import com.android.server.location.PassiveProvider; -import com.android.server.location.UserInfoStore; +import com.android.server.location.SettingsHelper; +import com.android.server.location.UserInfoHelper; import com.android.server.location.gnss.GnssManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; @@ -140,7 +140,6 @@ public class LocationManagerService extends ILocationManager.Stub { public Lifecycle(Context context) { super(context); mService = new LocationManagerService(context); - LocalServices.addService(LocationManagerInternal.class, mService.new LocalService()); } @Override @@ -181,9 +180,6 @@ public class LocationManagerService extends ILocationManager.Stub { // maximum age of a location before it is no longer considered "current" private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000; - private static final int FOREGROUND_IMPORTANCE_CUTOFF - = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - // Location Providers may sometimes deliver location updates // slightly faster that requested - provide grace period so // we don't unnecessarily filter events that are otherwise on @@ -195,21 +191,23 @@ public class LocationManagerService extends ILocationManager.Stub { private final Object mLock = new Object(); private final Context mContext; private final Handler mHandler; - private final UserInfoStore mUserInfoStore; - private final LocationSettingsStore mSettingsStore; + private final LocalService mLocalService; + private final UserInfoHelper mUserInfoHelper; + private final SettingsHelper mSettingsHelper; + private final AppForegroundHelper mAppForegroundHelper; private final LocationUsageLogger mLocationUsageLogger; + @Nullable private GnssManagerService mGnssManagerService = null; + private final PassiveLocationProviderManager mPassiveManager; private AppOpsManager mAppOps; private PackageManager mPackageManager; private PowerManager mPowerManager; - private ActivityManager mActivityManager; private GeofenceManager mGeofenceManager; private LocationFudger mLocationFudger; private GeocoderProxy mGeocodeProvider; - @Nullable private GnssManagerService mGnssManagerService; @GuardedBy("mLock") private String mExtraLocationControllerPackage; @@ -245,8 +243,13 @@ public class LocationManagerService extends ILocationManager.Stub { private LocationManagerService(Context context) { mContext = context; mHandler = FgThread.getHandler(); - mUserInfoStore = new UserInfoStore(mContext); - mSettingsStore = new LocationSettingsStore(mContext, mHandler); + mLocalService = new LocalService(); + + LocalServices.addService(LocationManagerInternal.class, mLocalService); + + mUserInfoHelper = new UserInfoHelper(mContext); + mSettingsHelper = new SettingsHelper(mContext, mHandler); + mAppForegroundHelper = new AppForegroundHelper(mContext); mLocationUsageLogger = new LocationUsageLogger(); // set up passive provider - we do this early because it has no dependencies on system @@ -272,17 +275,23 @@ public class LocationManagerService extends ILocationManager.Stub { } private void onSystemReady() { - mUserInfoStore.onSystemReady(); - mSettingsStore.onSystemReady(); + mUserInfoHelper.onSystemReady(); + mSettingsHelper.onSystemReady(); + mAppForegroundHelper.onSystemReady(); + + if (GnssManagerService.isGnssSupported()) { + mGnssManagerService = new GnssManagerService(mContext, mSettingsHelper, + mAppForegroundHelper, mLocationUsageLogger); + mGnssManagerService.onSystemReady(); + } synchronized (mLock) { mPackageManager = mContext.getPackageManager(); mAppOps = mContext.getSystemService(AppOpsManager.class); mPowerManager = mContext.getSystemService(PowerManager.class); - mActivityManager = mContext.getSystemService(ActivityManager.class); mLocationFudger = new LocationFudger(mContext, mHandler); - mGeofenceManager = new GeofenceManager(mContext, mSettingsStore); + mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper); PowerManagerInternal localPowerManager = LocalServices.getService(PowerManagerInternal.class); @@ -313,17 +322,6 @@ public class LocationManagerService extends ILocationManager.Stub { } }); }); - mActivityManager.addOnUidImportanceListener( - (uid, importance) -> { - // listener invoked on ui thread, move to our thread to reduce risk of - // blocking ui thread - mHandler.post(() -> { - synchronized (mLock) { - onUidImportanceChangedLocked(uid, importance); - } - }); - }, - FOREGROUND_IMPORTANCE_CUTOFF); localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION, state -> { @@ -337,26 +335,13 @@ public class LocationManagerService extends ILocationManager.Stub { }); mBatterySaverMode = mPowerManager.getLocationPowerSaveMode(); - mSettingsStore.addOnLocationEnabledChangedListener((userId) -> { - synchronized (mLock) { - onLocationModeChangedLocked(userId); - } - }); - mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> { - synchronized (mLock) { - onBackgroundThrottleIntervalChangedLocked(); - } - }); - mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> { - synchronized (mLock) { - onBackgroundThrottleWhitelistChangedLocked(); - } - }); - mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> { - synchronized (mLock) { - onIgnoreSettingsWhitelistChangedLocked(); - } - }); + mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged); + mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener( + this::onBackgroundThrottleIntervalChanged); + mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener( + this::onBackgroundThrottleWhitelistChanged); + mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener( + this::onIgnoreSettingsWhitelistChanged); new PackageMonitor() { @Override @@ -367,11 +352,9 @@ public class LocationManagerService extends ILocationManager.Stub { } }.register(mContext, mHandler.getLooper(), true); - mUserInfoStore.addListener((oldUserId, newUserId) -> { - synchronized (mLock) { - onUserChangedLocked(oldUserId, newUserId); - } - }); + mUserInfoHelper.addListener(this::onUserChanged); + + mAppForegroundHelper.addListener(this::onAppForegroundChanged); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); @@ -398,7 +381,7 @@ public class LocationManagerService extends ILocationManager.Stub { // switching the user from null to current here performs the bulk of the initialization // work. the user being changed will cause a reload of all user specific settings, which // causes initialization, and propagates changes until a steady state is reached - onUserChangedLocked(UserHandle.USER_NULL, mUserInfoStore.getCurrentUserId()); + onUserChanged(UserHandle.USER_NULL, mUserInfoHelper.getCurrentUserId()); } } @@ -455,20 +438,23 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onLocationModeChangedLocked(int userId) { + private void onLocationModeChanged(int userId) { + boolean enabled = mSettingsHelper.isLocationEnabled(userId); + if (D) { - Log.d(TAG, "[u" + userId + "] location enabled = " + isLocationEnabledForUser(userId)); + Log.d(TAG, "[u" + userId + "] location enabled = " + enabled); } - Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) - .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, isLocationEnabledForUser(userId)) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) - .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); + synchronized (mLock) { + Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) + .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) + .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); - for (LocationProviderManager manager : mProviderManagers) { + for (LocationProviderManager manager : mProviderManagers) { manager.onEnabledChangedLocked(userId); + } } } @@ -493,58 +479,55 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onUidImportanceChangedLocked(int uid, int importance) { - boolean foreground = LocationManagerServiceUtils.isImportanceForeground(importance); - HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); - for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { - String provider = entry.getKey(); - for (UpdateRecord record : entry.getValue()) { - if (record.mReceiver.mCallerIdentity.mUid == uid - && record.mIsForegroundUid != foreground) { - if (D) { - Log.d(TAG, "request from uid " + uid + " is now " - + LocationManagerServiceUtils.foregroundAsString( - foreground)); - } - record.updateForeground(foreground); + private void onAppForegroundChanged(int uid, boolean foreground) { + synchronized (mLock) { + HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); + for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { + String provider = entry.getKey(); + for (UpdateRecord record : entry.getValue()) { + if (record.mReceiver.mCallerIdentity.mUid == uid + && record.mIsForegroundUid != foreground) { + record.updateForeground(foreground); - if (!isThrottlingExemptLocked(record.mReceiver.mCallerIdentity)) { - affectedProviders.add(provider); + if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) { + affectedProviders.add(provider); + } } } } - } - for (String provider : affectedProviders) { - applyRequirementsLocked(provider); + for (String provider : affectedProviders) { + applyRequirementsLocked(provider); + } } } - @GuardedBy("mLock") - private void onBackgroundThrottleIntervalChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onBackgroundThrottleIntervalChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } - @GuardedBy("mLock") - private void onBackgroundThrottleWhitelistChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onBackgroundThrottleWhitelistChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } - @GuardedBy("lock") - private void onIgnoreSettingsWhitelistChangedLocked() { - for (LocationProviderManager manager : mProviderManagers) { - applyRequirementsLocked(manager); + private void onIgnoreSettingsWhitelistChanged() { + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + applyRequirementsLocked(manager); + } } } @GuardedBy("mLock") private void initializeProvidersLocked() { - if (GnssManagerService.isGnssSupported()) { - mGnssManagerService = new GnssManagerService(this, mContext, mLocationUsageLogger); + if (mGnssManagerService != null) { LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER); mProviderManagers.add(gnssManager); gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider()); @@ -627,19 +610,20 @@ public class LocationManagerService extends ILocationManager.Stub { } } - @GuardedBy("mLock") - private void onUserChangedLocked(int oldUserId, int newUserId) { + private void onUserChanged(int oldUserId, int newUserId) { if (D) { Log.d(TAG, "foreground user is changing to " + newUserId); } - for (LocationProviderManager manager : mProviderManagers) { - // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility - mSettingsStore.setLocationProviderAllowed(manager.getName(), - manager.isEnabled(newUserId), newUserId); + synchronized (mLock) { + for (LocationProviderManager manager : mProviderManagers) { + // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility + mSettingsHelper.setLocationProviderAllowed(manager.getName(), + manager.isEnabled(newUserId), newUserId); - manager.onEnabledChangedLocked(oldUserId); - manager.onEnabledChangedLocked(newUserId); + manager.onEnabledChangedLocked(oldUserId); + manager.onEnabledChangedLocked(newUserId); + } } } @@ -665,7 +649,7 @@ public class LocationManagerService extends ILocationManager.Stub { mEnabled = new SparseArray<>(1); // initialize last since this lets our reference escape - mProvider = new MockableLocationProvider(mContext, mLock, this); + mProvider = new MockableLocationProvider(mLock, this); // we can assume all users start with disabled location state since the initial state // of all providers is disabled. no need to initialize mEnabled further. @@ -778,7 +762,7 @@ public class LocationManagerService extends ILocationManager.Stub { // it would be more correct to call this for all users, but we know this can // only affect the current user since providers are disabled for non-current // users - onEnabledChangedLocked(mUserInfoStore.getCurrentUserId()); + onEnabledChangedLocked(mUserInfoHelper.getCurrentUserId()); } } @@ -787,14 +771,14 @@ public class LocationManagerService extends ILocationManager.Stub { } public boolean isEnabled() { - return isEnabled(mUserInfoStore.getCurrentUserId()); + return isEnabled(mUserInfoHelper.getCurrentUserId()); } public boolean isEnabled(int userId) { synchronized (mLock) { // normalize user id to always refer to parent since profile state is always the // same as parent state - userId = mUserInfoStore.getParentUserId(userId); + userId = mUserInfoHelper.getParentUserId(userId); return mEnabled.get(userId, Boolean.FALSE); } } @@ -808,13 +792,13 @@ public class LocationManagerService extends ILocationManager.Stub { // normalize user id to always refer to parent since profile state is always the same // as parent state - userId = mUserInfoStore.getParentUserId(userId); + userId = mUserInfoHelper.getParentUserId(userId); // if any property that contributes to "enabled" here changes state, it MUST result // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to // guarantee that it will always eventually reach the correct state. - boolean enabled = (userId == mUserInfoStore.getCurrentUserId()) - && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed; + boolean enabled = (userId == mUserInfoHelper.getCurrentUserId()) + && mSettingsHelper.isLocationEnabled(userId) && mProvider.getState().allowed; if (enabled == isEnabled(userId)) { return; @@ -829,7 +813,7 @@ public class LocationManagerService extends ILocationManager.Stub { // fused and passive provider never get public updates for legacy reasons if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) { // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility - mSettingsStore.setLocationProviderAllowed(mName, enabled, userId); + mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId); Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION) .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName) @@ -1009,7 +993,7 @@ public class LocationManagerService extends ILocationManager.Stub { if (manager == null) { continue; } - if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) { + if (!manager.isEnabled() && !isSettingsExempt(updateRecord)) { continue; } @@ -1475,13 +1459,13 @@ public class LocationManagerService extends ILocationManager.Stub { ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName()); if (records != null) { for (UpdateRecord record : records) { - if (!mUserInfoStore.isCurrentUserOrProfile( + if (!mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } // requests that ignore location settings will never provide notifications - if (isSettingsExemptLocked(record)) { + if (isSettingsExempt(record)) { continue; } @@ -1520,14 +1504,7 @@ public class LocationManagerService extends ILocationManager.Stub { // if provider is not active, it should not respond to requests if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) { - long backgroundThrottleInterval; - - long identity = Binder.clearCallingIdentity(); - try { - backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs(); - } finally { - Binder.restoreCallingIdentity(identity); - } + long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs(); ArrayList<LocationRequest> requests = new ArrayList<>(records.size()); @@ -1540,7 +1517,7 @@ public class LocationManagerService extends ILocationManager.Stub { // initialize the low power mode to true and set to false if any of the records requires providerRequest.setLowPowerMode(true); for (UpdateRecord record : records) { - if (!mUserInfoStore.isCurrentUserOrProfile( + if (!mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { continue; } @@ -1554,7 +1531,7 @@ public class LocationManagerService extends ILocationManager.Stub { final boolean isBatterySaverDisablingLocation = shouldThrottleRequests || (isForegroundOnlyMode && !record.mIsForegroundUid); if (!manager.isEnabled() || isBatterySaverDisablingLocation) { - if (isSettingsExemptLocked(record)) { + if (isSettingsExempt(record)) { providerRequest.setLocationSettingsIgnored(true); providerRequest.setLowPowerMode(false); } else { @@ -1567,7 +1544,7 @@ public class LocationManagerService extends ILocationManager.Stub { // if we're forcing location, don't apply any throttling - if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExemptLocked( + if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt( record.mReceiver.mCallerIdentity)) { if (!record.mIsForegroundUid) { interval = Math.max(interval, backgroundThrottleInterval); @@ -1599,7 +1576,7 @@ public class LocationManagerService extends ILocationManager.Stub { // TODO: overflow long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2; for (UpdateRecord record : records) { - if (mUserInfoStore.isCurrentUserOrProfile( + if (mUserInfoHelper.isCurrentUserOrProfile( UserHandle.getUserId(record.mReceiver.mCallerIdentity.mUid))) { LocationRequest locationRequest = record.mRequest; @@ -1648,41 +1625,39 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public String[] getBackgroundThrottlingWhitelist() { - return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]); + return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]); } @Override public String[] getIgnoreSettingsWhitelist() { - return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]); + return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]); } - @GuardedBy("mLock") - public boolean isThrottlingExemptLocked(CallerIdentity callerIdentity) { + private boolean isThrottlingExempt(CallerIdentity callerIdentity) { if (callerIdentity.mUid == Process.SYSTEM_UID) { return true; } - if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains( + if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( callerIdentity.mPackageName)) { return true; } - return isProviderPackage(callerIdentity.mPackageName); + return mLocalService.isProviderPackage(callerIdentity.mPackageName); } - @GuardedBy("mLock") - private boolean isSettingsExemptLocked(UpdateRecord record) { + private boolean isSettingsExempt(UpdateRecord record) { if (!record.mRealRequest.isLocationSettingsIgnored()) { return false; } - if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains( + if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains( record.mReceiver.mCallerIdentity.mPackageName)) { return true; } - return isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName); + return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.mPackageName); } @@ -1705,10 +1680,7 @@ public class LocationManagerService extends ILocationManager.Stub { mRealRequest = request; mRequest = request; mReceiver = receiver; - mIsForegroundUid = - LocationManagerServiceUtils.isImportanceForeground( - mActivityManager.getPackageImportance( - mReceiver.mCallerIdentity.mPackageName)); + mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.mUid); if (D && receiver.mCallerIdentity.mPid == Process.myPid()) { mStackTrace = new Throwable(); @@ -1753,7 +1725,7 @@ public class LocationManagerService extends ILocationManager.Stub { mReceiver.isListener(), mReceiver.isPendingIntent(), /* geofence= */ null, - mActivityManager.getPackageImportance(packageName)); + mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.mUid)); // remove from mRecordsByProvider ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); @@ -1923,7 +1895,7 @@ public class LocationManagerService extends ILocationManager.Stub { LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, packageName, request, listener != null, intent != null, /* geofence= */ null, - mActivityManager.getPackageImportance(packageName)); + mAppForegroundHelper.getImportance(uid)); Receiver receiver; if (intent != null) { @@ -1961,7 +1933,7 @@ public class LocationManagerService extends ILocationManager.Stub { Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + name + " " + request + " from " + packageName + "(" + uid + " " + (record.mIsForegroundUid ? "foreground" : "background") - + (isThrottlingExemptLocked(receiver.mCallerIdentity) + + (isThrottlingExempt(receiver.mCallerIdentity) ? " [whitelisted]" : "") + ")"); } @@ -1970,7 +1942,7 @@ public class LocationManagerService extends ILocationManager.Stub { oldRecord.disposeLocked(false); } - if (!manager.isEnabled() && !isSettingsExemptLocked(record)) { + if (!manager.isEnabled() && !isSettingsExempt(record)) { // Notify the listener that updates are currently disabled - but only if the request // does not ignore location settings receiver.callProviderEnabledLocked(name, false); @@ -2060,7 +2032,7 @@ public class LocationManagerService extends ILocationManager.Stub { final int uid = Binder.getCallingUid(); final long identity = Binder.clearCallingIdentity(); try { - if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid), + if (mSettingsHelper.isLocationPackageBlacklisted(UserHandle.getUserId(uid), packageName)) { if (D) { Log.d(TAG, "not returning last loc for blacklisted app: " @@ -2077,8 +2049,8 @@ public class LocationManagerService extends ILocationManager.Stub { if (manager == null) return null; // only the current user or location providers may get location this way - if (!mUserInfoStore.isCurrentUserOrProfile(UserHandle.getUserId(uid)) - && !isProviderPackage(packageName)) { + if (!mUserInfoHelper.isCurrentUserOrProfile(UserHandle.getUserId(uid)) + && !mLocalService.isProviderPackage(packageName)) { return null; } @@ -2102,7 +2074,7 @@ public class LocationManagerService extends ILocationManager.Stub { String op = resolutionLevelToOpStr(allowedResolutionLevel); long locationAgeMs = TimeUnit.NANOSECONDS.toMillis( SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos()); - if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs() + if (locationAgeMs > mSettingsHelper.getMaxLastLocationAgeMs() && (mAppOps.unsafeCheckOp(op, uid, packageName) == AppOpsManager.MODE_FOREGROUND)) { return null; @@ -2145,29 +2117,21 @@ public class LocationManagerService extends ILocationManager.Stub { long locationAgeMs = TimeUnit.NANOSECONDS.toMillis( SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos()); - long identity = Binder.clearCallingIdentity(); - try { - if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) { - try { - listener.onLocationChanged(lastLocation); - return true; - } catch (RemoteException e) { - Log.w(TAG, e); - return false; - } + if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) { + try { + listener.onLocationChanged(lastLocation); + return true; + } catch (RemoteException e) { + Log.w(TAG, e); + return false; } + } - // packageName already validated by getLastLocation() call above - boolean foreground = LocationManagerServiceUtils.isImportanceForeground( - mActivityManager.getPackageImportance(packageName)); - if (!foreground) { - if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) { - // not allowed to request new locations, so we can't return anything - return false; - } + if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) { + if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) { + // not allowed to request new locations, so we can't return anything + return false; } - } finally { - Binder.restoreCallingIdentity(identity); } } @@ -2252,20 +2216,19 @@ public class LocationManagerService extends ILocationManager.Stub { Log.w(TAG, "proximity alerts are currently available only to the primary user"); return; } + + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_STARTED, + LocationStatsEnums.API_REQUEST_GEOFENCE, + packageName, + request, + /* hasListener= */ false, + true, + geofence, + mAppForegroundHelper.getImportance(uid)); + long identity = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_STARTED, - LocationStatsEnums.API_REQUEST_GEOFENCE, - packageName, - request, - /* hasListener= */ false, - true, - geofence, - mActivityManager.getPackageImportance(packageName)); - } - mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier); } finally { @@ -2282,20 +2245,19 @@ public class LocationManagerService extends ILocationManager.Stub { if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_ENDED, + LocationStatsEnums.API_REQUEST_GEOFENCE, + packageName, + /* LocationRequest= */ null, + /* hasListener= */ false, + true, + geofence, + mAppForegroundHelper.getImportance(Binder.getCallingUid())); + // geo-fence manager uses the public location API, need to clear identity long identity = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_ENDED, - LocationStatsEnums.API_REQUEST_GEOFENCE, - packageName, - /* LocationRequest= */ null, - /* hasListener= */ false, - true, - geofence, - mActivityManager.getPackageImportance(packageName)); - } mGeofenceManager.removeFence(geofence, intent); } finally { Binder.restoreCallingIdentity(identity); @@ -2392,12 +2354,6 @@ public class LocationManagerService extends ILocationManager.Stub { } @Override - public boolean sendNiResponse(int notifId, int userResponse) { - return mGnssManagerService != null && mGnssManagerService.sendNiResponse(notifId, - userResponse); - } - - @Override public ProviderProperties getProviderProperties(String providerName) { LocationProviderManager manager = getLocationProviderManager(providerName); if (manager == null) { @@ -2408,20 +2364,13 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean isProviderPackage(String packageName) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG + " permission required"); - for (LocationProviderManager manager : mProviderManagers) { - if (manager.getPackages().contains(packageName)) { - return true; - } - } - return false; + mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); + return mLocalService.isProviderPackage(packageName); } @Override public List<String> getProviderPackages(String providerName) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, - Manifest.permission.READ_DEVICE_CONFIG + " permission required"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); LocationProviderManager manager = getLocationProviderManager(providerName); return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages()); } @@ -2461,28 +2410,19 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean isLocationEnabledForUser(int userId) { - // Check INTERACT_ACROSS_USERS permission if userId is not current user id. if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.INTERACT_ACROSS_USERS, - "Requires INTERACT_ACROSS_USERS permission"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, + null); } - long identity = Binder.clearCallingIdentity(); - try { - return mSettingsStore.isLocationEnabled(userId); - } finally { - Binder.restoreCallingIdentity(identity); - } + return mSettingsHelper.isLocationEnabled(userId); } @Override public boolean isProviderEnabledForUser(String providerName, int userId) { - // Check INTERACT_ACROSS_USERS permission if userId is not current user id. if (UserHandle.getCallingUserId() != userId) { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.INTERACT_ACROSS_USERS, - "Requires INTERACT_ACROSS_USERS permission"); + mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS, + null); } // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, @@ -2593,12 +2533,12 @@ public class LocationManagerService extends ILocationManager.Stub { Receiver receiver = r.mReceiver; boolean receiverDead = false; - if (!manager.isEnabled() && !isSettingsExemptLocked(r)) { + if (!manager.isEnabled() && !isSettingsExempt(r)) { continue; } int receiverUserId = UserHandle.getUserId(receiver.mCallerIdentity.mUid); - if (!mUserInfoStore.isCurrentUserOrProfile(receiverUserId) + if (!mUserInfoHelper.isCurrentUserOrProfile(receiverUserId) && !isProviderPackage(receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for background user " + receiverUserId + @@ -2607,7 +2547,7 @@ public class LocationManagerService extends ILocationManager.Stub { continue; } - if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId, + if (mSettingsHelper.isLocationPackageBlacklisted(receiverUserId, receiver.mCallerIdentity.mPackageName)) { if (D) { Log.d(TAG, "skipping loc update for blacklisted app: " + @@ -2759,7 +2699,7 @@ public class LocationManagerService extends ILocationManager.Stub { mProviderManagers.add(manager); } - manager.setMockProvider(new MockProvider(mContext, properties)); + manager.setMockProvider(new MockProvider(properties)); } } @@ -2855,12 +2795,12 @@ public class LocationManagerService extends ILocationManager.Stub { ipw.println("User Info:"); ipw.increaseIndent(); - mUserInfoStore.dump(fd, ipw, args); + mUserInfoHelper.dump(fd, ipw, args); ipw.decreaseIndent(); ipw.println("Location Settings:"); ipw.increaseIndent(); - mSettingsStore.dump(fd, ipw, args); + mSettingsHelper.dump(fd, ipw, args); ipw.decreaseIndent(); ipw.println("Battery Saver Location Mode: " @@ -2960,5 +2900,22 @@ public class LocationManagerService extends ILocationManager.Stub { } } } + + @Override + public boolean isProviderPackage(String packageName) { + for (LocationProviderManager manager : mProviderManagers) { + if (manager.getPackages().contains(packageName)) { + return true; + } + } + return false; + } + + @Override + public void sendNiResponse(int notifId, int userResponse) { + if (mGnssManagerService != null) { + mGnssManagerService.sendNiResponse(notifId, userResponse); + } + } } } diff --git a/services/core/java/com/android/server/LocationManagerServiceUtils.java b/services/core/java/com/android/server/LocationManagerServiceUtils.java index 9c8ac19cc591..372e91e41772 100644 --- a/services/core/java/com/android/server/LocationManagerServiceUtils.java +++ b/services/core/java/com/android/server/LocationManagerServiceUtils.java @@ -17,8 +17,6 @@ package com.android.server; import android.annotation.NonNull; -import android.app.ActivityManager; -import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -91,12 +89,8 @@ public class LocationManagerServiceUtils { /** * Link listener (i.e. callback) to a binder, so that it will be called upon binder's death. - * - * @param binder that calls listener upon death - * @return true if listener is successfully linked to binder, false otherwise */ - public boolean linkToListenerDeathNotificationLocked( - IBinder binder) { + public boolean linkToListenerDeathNotificationLocked(IBinder binder) { try { binder.linkToDeath(this, 0 /* flags */); return true; @@ -110,54 +104,13 @@ public class LocationManagerServiceUtils { /** * Unlink death listener (i.e. callback) from binder. - * - * @param binder that calls listener upon death - * @return true if binder is successfully unlinked from binder, false otherwise */ - public boolean unlinkFromListenerDeathNotificationLocked( - IBinder binder) { + public void unlinkFromListenerDeathNotificationLocked(IBinder binder) { try { binder.unlinkToDeath(this, 0 /* flags */); - return true; } catch (NoSuchElementException e) { - // if the death callback isn't connected (it should be...), log error, - // swallow the exception and return Log.w(TAG, "Could not unlink " + mListenerName + " death callback.", e); - return false; } } - - } - - /** - * Convert boolean foreground into "foreground" or "background" string. - * - * @param foreground boolean indicating foreground - * @return "foreground" string if true, false otherwise - */ - public static String foregroundAsString(boolean foreground) { - return foreground ? "foreground" : "background"; - } - - - /** - * Classifies importance level as foreground or not. - * - * @param importance level as int - * @return boolean indicating if importance level is foreground or greater - */ - public static boolean isImportanceForeground(int importance) { - return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; - } - - /** - * Get package importance level. - * - * @param packageName package name - * @return package importance level as int - */ - public static int getPackageImportance(String packageName, Context context) { - return ((ActivityManager) context.getSystemService( - Context.ACTIVITY_SERVICE)).getPackageImportance(packageName); } } diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java index 9b1326bc88d7..043f657b7f2c 100644 --- a/services/core/java/com/android/server/MmsServiceBroker.java +++ b/services/core/java/com/android/server/MmsServiceBroker.java @@ -128,13 +128,15 @@ public class MmsServiceBroker extends SystemService { @Override public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl, - Bundle configOverrides, PendingIntent sentIntent) throws RemoteException { + Bundle configOverrides, PendingIntent sentIntent, long messageId) + throws RemoteException { returnPendingIntentWithError(sentIntent); } @Override public void downloadMessage(int subId, String callingPkg, String locationUrl, - Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent) + Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent, + long messageId) throws RemoteException { returnPendingIntentWithError(downloadedIntent); } @@ -329,7 +331,8 @@ public class MmsServiceBroker extends SystemService { @Override public void sendMessage(int subId, String callingPkg, Uri contentUri, - String locationUrl, Bundle configOverrides, PendingIntent sentIntent) + String locationUrl, Bundle configOverrides, PendingIntent sentIntent, + long messageId) throws RemoteException { Slog.d(TAG, "sendMessage() by " + callingPkg); mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message"); @@ -343,13 +346,13 @@ public class MmsServiceBroker extends SystemService { Intent.FLAG_GRANT_READ_URI_PERMISSION, subId); getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl, - configOverrides, sentIntent); + configOverrides, sentIntent, messageId); } @Override public void downloadMessage(int subId, String callingPkg, String locationUrl, Uri contentUri, Bundle configOverrides, - PendingIntent downloadedIntent) throws RemoteException { + PendingIntent downloadedIntent, long messageId) throws RemoteException { Slog.d(TAG, "downloadMessage() by " + callingPkg); mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS, "Download MMS message"); @@ -364,7 +367,7 @@ public class MmsServiceBroker extends SystemService { subId); getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri, - configOverrides, downloadedIntent); + configOverrides, downloadedIntent, messageId); } @Override diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index a04f25b0d20c..e17dde9a766e 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -24,6 +24,7 @@ import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; +import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE; import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES; import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE; @@ -4320,21 +4321,37 @@ class StorageManagerService extends IStorageManager.Stub return true; } - public void onAppOpsChanged(int code, int uid, - @Nullable String packageName, int mode) { - if (code == OP_REQUEST_INSTALL_PACKAGES && mIsFuseEnabled) { - // When using FUSE, we basically have no other choice but to kill the app - // after the app op is either granted or rejected. - final IActivityManager am = ActivityManager.getService(); - try { - am.killApplication(packageName, - UserHandle.getAppId(uid), - UserHandle.USER_ALL, AppOpsManager.opToName(code) + " changed."); - } catch (RemoteException e) { - } + private void killAppForOpChange(int code, int uid, String packageName) { + final IActivityManager am = ActivityManager.getService(); + try { + am.killApplication(packageName, + UserHandle.getAppId(uid), + UserHandle.USER_ALL, AppOpsManager.opToName(code) + " changed."); + } catch (RemoteException e) { + } + } - return; + public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) { + if (mIsFuseEnabled) { + // 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, packageName); + return; + case OP_MANAGE_EXTERNAL_STORAGE: + if (mode != MODE_ALLOWED) { + // Only kill if op is denied, to lose external_storage gid + // Killing when op is granted to pickup the gid automatically, results + // in a bad UX, especially since the gid only gives access to unreliable + // volumes, USB OTGs that are rarely mounted. The app will get the + // external_storage gid on next organic restart. + killAppForOpChange(code, uid, packageName); + return; + } + } } + if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE || code == OP_WRITE_EXTERNAL_STORAGE || code == OP_REQUEST_INSTALL_PACKAGES)) { diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 36dd017d2c23..139a87154223 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -897,6 +897,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { updateReportSignalStrengthDecision(r.subId); + try { + if (mSignalStrength[phoneId] != null) { + r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]); + } + } catch (RemoteException ex) { + remove(r.binder); + } } if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { try { @@ -1326,9 +1333,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId + " phoneId=" + phoneId + " ss=" + signalStrength); } - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) && - idMatch(r.subId, subId, phoneId)) { + if ((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) + || r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) + && idMatch(r.subId, subId, phoneId)) { try { if (DBG) { log("notifySignalStrengthForPhoneId: callback.onSsS r=" + r @@ -1341,7 +1349,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) && - idMatch(r.subId, subId, phoneId)){ + idMatch(r.subId, subId, phoneId)) { try { int gsmSignalStrength = signalStrength.getGsmSignalStrength(); int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength); @@ -2542,6 +2550,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null); } + if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null); + } + if ((events & READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK) != 0) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null); @@ -2657,7 +2670,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { + if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0 + || (events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) { try { if (mSignalStrength[phoneId] != null) { SignalStrength signalStrength = mSignalStrength[phoneId]; diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index ffeea3d12781..982466d82d38 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -19,12 +19,8 @@ package com.android.server.am; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; -import static android.os.Process.BLUETOOTH_UID; -import static android.os.Process.NETWORK_STACK_UID; import static android.os.Process.NFC_UID; -import static android.os.Process.PHONE_UID; import static android.os.Process.ROOT_UID; -import static android.os.Process.SE_UID; import static android.os.Process.SYSTEM_UID; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK; @@ -89,7 +85,6 @@ import android.util.EventLog; import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.webkit.WebViewZygote; @@ -103,6 +98,7 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.TransferPipe; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.AppStateTracker; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -728,8 +724,9 @@ public final class ActiveServices { stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); } r.callStart = false; - StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(), - r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__START); + 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(); } @@ -768,9 +765,9 @@ public final class ActiveServices { service.delayedStop = true; return; } - StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid, + FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid, service.name.getPackageName(), service.name.getClassName(), - StatsLog.SERVICE_STATE_CHANGED__STATE__STOP); + FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP); synchronized (service.stats.getBatteryStats()) { service.stats.stopRunningLocked(); } @@ -929,8 +926,9 @@ public final class ActiveServices { } } - StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(), - r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__STOP); + 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(); } @@ -1435,9 +1433,9 @@ public final class ActiveServices { AppOpsManager.getToken(mAm.mAppOpsService), AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null, true, false, ""); - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortInstanceName, - StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER); + FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER); mAm.updateForegroundServiceUsageStats(r.name, r.userId, true); } r.postNotification(); @@ -1486,9 +1484,9 @@ public final class ActiveServices { mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null); - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortInstanceName, - StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); + FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); mAm.updateForegroundServiceUsageStats(r.name, r.userId, false); if (r.app != null) { mAm.updateLruProcessLocked(r.app, false, null); @@ -2772,8 +2770,8 @@ public final class ActiveServices { EventLogTags.writeAmCreateService( r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid); } - StatsLog.write(StatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(), - r.name.getClassName()); + FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, + r.name.getPackageName(), r.name.getClassName()); synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } @@ -3101,8 +3099,9 @@ public final class ActiveServices { mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null); - StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, - r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); + FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED, + r.appInfo.uid, r.shortInstanceName, + FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT); mAm.updateForegroundServiceUsageStats(r.name, r.userId, false); } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 8451d6baeb0a..4a65a96e57a1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -58,6 +58,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_CONTENT_PROVIDER_RETAIN_TIME = "content_provider_retain_time"; private static final String KEY_GC_TIMEOUT = "gc_timeout"; private static final String KEY_GC_MIN_INTERVAL = "gc_min_interval"; + private static final String KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + "force_bg_check_on_restricted"; private static final String KEY_FULL_PSS_MIN_INTERVAL = "full_pss_min_interval"; private static final String KEY_FULL_PSS_LOWERED_INTERVAL = "full_pss_lowered_interval"; private static final String KEY_POWER_CHECK_INTERVAL = "power_check_interval"; @@ -96,6 +98,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_GC_TIMEOUT = 5*1000; private static final long DEFAULT_GC_MIN_INTERVAL = 60*1000; private static final long DEFAULT_FULL_PSS_MIN_INTERVAL = 20*60*1000; + private static final boolean DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = true; private static final long DEFAULT_FULL_PSS_LOWERED_INTERVAL = 5*60*1000; private static final long DEFAULT_POWER_CHECK_INTERVAL = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000; private static final int DEFAULT_POWER_CHECK_MAX_CPU_1 = 25; @@ -177,6 +180,14 @@ final class ActivityManagerConstants extends ContentObserver { // The minimum amount of time between successive GC requests for a process. long GC_MIN_INTERVAL = DEFAULT_GC_MIN_INTERVAL; + /** + * Whether or not Background Check should be forced on any apps in the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket, + * regardless of target SDK version. + */ + boolean FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS; + // The minimum amount of time between successive PSS requests for a process. long FULL_PSS_MIN_INTERVAL = DEFAULT_FULL_PSS_MIN_INTERVAL; @@ -380,6 +391,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES: updateImperceptibleKillExemptions(); break; + case KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS: + updateForceRestrictedBackgroundCheck(); + break; default: break; } @@ -424,13 +438,15 @@ final class ActivityManagerConstants extends ContentObserver { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ActivityThread.currentApplication().getMainExecutor(), mOnDeviceConfigChangedListener); - updateMaxCachedProcesses(); + loadDeviceConfigConstants(); + // The following read from Settings. updateActivityStartsLoggingEnabled(); - updateBackgroundActivityStarts(); updateForegroundServiceStartsLoggingEnabled(); - updateBackgroundFgsStartsRestriction(); - updateOomAdjUpdatePolicy(); - updateImperceptibleKillExemptions(); + } + + private void loadDeviceConfigConstants() { + mOnDeviceConfigChangedListener.onPropertiesChanged( + DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER)); } public void setOverrideMaxCachedProcesses(int value) { @@ -571,6 +587,13 @@ final class ActivityManagerConstants extends ContentObserver { == OOMADJ_UPDATE_POLICY_QUICK; } + private void updateForceRestrictedBackgroundCheck() { + FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS, + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); + } + private void updateImperceptibleKillExemptions() { IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear(); IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages); @@ -658,6 +681,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(GC_TIMEOUT); pw.print(" "); pw.print(KEY_GC_MIN_INTERVAL); pw.print("="); pw.println(GC_MIN_INTERVAL); + pw.print(" "); pw.print(KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print("="); + pw.println(FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print(" "); pw.print(KEY_FULL_PSS_MIN_INTERVAL); pw.print("="); pw.println(FULL_PSS_MIN_INTERVAL); pw.print(" "); pw.print(KEY_FULL_PSS_LOWERED_INTERVAL); pw.print("="); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4c5f705433d6..08625bed061c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -184,6 +184,7 @@ import android.app.WindowConfiguration.WindowingMode; import android.app.backup.IBackupManager; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents.Event; +import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.AutofillOptions; @@ -292,7 +293,6 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; @@ -325,6 +325,7 @@ import com.android.internal.os.Zygote; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; import com.android.internal.util.function.HexFunction; @@ -3069,10 +3070,10 @@ public class ActivityManagerService extends IActivityManager.Stub "updateBatteryStats: comp=" + activity + "res=" + resumed); } final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); - StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED, uid, activity.getPackageName(), activity.getShortClassName(), - resumed ? StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND : - StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND); + resumed ? FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND : + FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND); synchronized (stats) { if (resumed) { stats.noteActivityResumedLocked(uid); @@ -3796,7 +3797,7 @@ public class ActivityManagerService extends IActivityManager.Stub // On the device which doesn't have Cgroup, log LmkStateChanged which is used as a signal // for pulling memory stats of other running processes when this process died. if (!hasMemcg()) { - StatsLog.write(StatsLog.APP_DIED, SystemClock.elapsedRealtime()); + FrameworkStatsLog.write(FrameworkStatsLog.APP_DIED, SystemClock.elapsedRealtime()); } } @@ -4442,7 +4443,7 @@ public class ActivityManagerService extends IActivityManager.Stub proc.pkgList.mPkgList); for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED, proc.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -4500,7 +4501,7 @@ public class ActivityManagerService extends IActivityManager.Stub ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList.mPkgList); for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED, proc.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -5223,12 +5224,12 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked"); } - StatsLog.write( - StatsLog.PROCESS_START_TIME, + FrameworkStatsLog.write( + FrameworkStatsLog.PROCESS_START_TIME, app.info.uid, app.pid, app.info.packageName, - StatsLog.PROCESS_START_TIME__TYPE__COLD, + FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD, app.startTime, (int) (bindApplicationTimeMillis - app.startTime), (int) (SystemClock.elapsedRealtime() - app.startTime), @@ -6051,6 +6052,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private boolean isInRestrictedBucket(int userId, String packageName, long nowElapsed) { + return UsageStatsManager.STANDBY_BUCKET_RESTRICTED + <= mUsageStatsService.getAppStandbyBucket(packageName, userId, nowElapsed); + } + // Unified app-op and target sdk check int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) { // Apps that target O+ are always subject to background check @@ -6060,7 +6066,17 @@ public class ActivityManagerService extends IActivityManager.Stub } return ActivityManager.APP_START_MODE_DELAYED_RIGID; } - // ...and legacy apps get an AppOp check + // It's a legacy app. If it's in the RESTRICTED bucket, always restrict on battery. + if (mOnBattery // Short-circuit in common case. + && mConstants.FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS + && isInRestrictedBucket( + UserHandle.getUserId(uid), packageName, SystemClock.elapsedRealtime())) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " in RESTRICTED bucket"); + } + return ActivityManager.APP_START_MODE_DELAYED; + } + // Not in the RESTRICTED bucket so policy is based on AppOp check. int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, null, false, ""); if (DEBUG_BACKGROUND_CHECK) { @@ -6860,6 +6876,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } + ProcessRecord dyingProc = null; if (cpr != null && cpr.proc != null) { providerRunning = !cpr.proc.killed; @@ -6869,14 +6886,9 @@ public class ActivityManagerService extends IActivityManager.Stub // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see // how to test this case.) if (cpr.proc.killed && cpr.proc.killedByAm) { - final long iden = Binder.clearCallingIdentity(); - try { - mProcessList.killProcAndWaitIfNecessaryLocked(cpr.proc, false, - cpr.uid == cpr.proc.uid || cpr.proc.isolated, - "getContentProviderImpl: %s (killedByAm)", startTime); - } finally { - Binder.restoreCallingIdentity(iden); - } + Slog.wtf(TAG, cpr.proc.toString() + " was killed by AM but isn't really dead"); + // Now we are going to wait for the death before starting the new process. + dyingProc = cpr.proc; } } @@ -6977,18 +6989,18 @@ public class ActivityManagerService extends IActivityManager.Stub // has been killed on us. We need to wait for a new // process to be started, and make sure its death // doesn't kill our process. - Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString() + Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); - mProcessList.killProcAndWaitIfNecessaryLocked(cpr.proc, - false, true, "getContentProviderImpl: %s", startTime); if (!lastRef) { // This wasn't the last ref our process had on - // the provider... we have now been killed, bail. + // the provider... we will be killed during cleaning up, bail. return null; } + // We'll just start a new process to host the content provider providerRunning = false; conn = null; + dyingProc = cpr.proc; } else { cpr.proc.verifiedAdj = cpr.proc.setAdj; } @@ -7064,7 +7076,7 @@ public class ActivityManagerService extends IActivityManager.Stub checkTime(startTime, "getContentProviderImpl: before getProviderByClass"); cpr = mProviderMap.getProviderByClass(comp, userId); checkTime(startTime, "getContentProviderImpl: after getProviderByClass"); - final boolean firstClass = cpr == null; + boolean firstClass = cpr == null; if (firstClass) { final long ident = Binder.clearCallingIdentity(); @@ -7095,6 +7107,13 @@ public class ActivityManagerService extends IActivityManager.Stub } finally { Binder.restoreCallingIdentity(ident); } + } else if (dyingProc == cpr.proc) { + // The old stable connection's client should be killed during proc cleaning up, + // so do not re-use the old ContentProviderRecord, otherwise the new clients + // could get killed unexpectedly. + cpr = new ContentProviderRecord(cpr); + // This is sort of "firstClass" + firstClass = true; } checkTime(startTime, "getContentProviderImpl: now have ContentProviderRecord"); @@ -8843,8 +8862,8 @@ public class ActivityManagerService extends IActivityManager.Stub UserHandle.getUserId(workSourceUid), SystemClock.elapsedRealtime()); } - StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg, - standbyBucket); + FrameworkStatsLog.write(FrameworkStatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, + sourcePkg, standbyBucket); if (DEBUG_POWER) { Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket=" @@ -8855,8 +8874,8 @@ public class ActivityManagerService extends IActivityManager.Stub standbyBucket = mUsageStatsService.getAppStandbyBucket(sourcePkg, UserHandle.getUserId(sourceUid), SystemClock.elapsedRealtime()); } - StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, null, tag, - sourcePkg, standbyBucket); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, + null, tag, sourcePkg, standbyBucket); if (DEBUG_POWER) { Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket=" @@ -9590,20 +9609,20 @@ public class ActivityManagerService extends IActivityManager.Stub crashInfo.throwFileName, crashInfo.throwLineNumber); - StatsLog.write(StatsLog.APP_CRASH_OCCURRED, + FrameworkStatsLog.write(FrameworkStatsLog.APP_CRASH_OCCURRED, Binder.getCallingUid(), eventType, processName, Binder.getCallingPid(), (r != null && r.info != null) ? r.info.packageName : "", (r != null && r.info != null) ? (r.info.isInstantApp() - ? StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__TRUE - : StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__FALSE) - : StatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__UNAVAILABLE, + ? FrameworkStatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__TRUE + : FrameworkStatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__FALSE) + : FrameworkStatsLog.APP_CRASH_OCCURRED__IS_INSTANT_APP__UNAVAILABLE, r != null ? (r.isInterestingToUserLocked() - ? StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__FOREGROUND - : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__BACKGROUND) - : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN, + ? FrameworkStatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__FOREGROUND + : FrameworkStatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__BACKGROUND) + : FrameworkStatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN, processName.equals("system_server") ? ServerProtoEnums.SYSTEM_SERVER : (r != null) ? r.getProcessClassEnum() : ServerProtoEnums.ERROR_SOURCE_UNKNOWN @@ -9747,15 +9766,21 @@ public class ActivityManagerService extends IActivityManager.Stub * @param crashInfo describing the context of the error * @return true if the process should exit immediately (WTF is fatal) */ + @Override public boolean handleApplicationWtf(final IBinder app, final String tag, boolean system, - final ApplicationErrorReport.ParcelableCrashInfo crashInfo) { + final ApplicationErrorReport.ParcelableCrashInfo crashInfo, int immediateCallerPid) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); - if (system) { - // If this is coming from the system, we could very well have low-level - // system locks held, so we want to do this all asynchronously. And we - // never want this to become fatal, so there is that too. + // If this is coming from the system, we could very well have low-level + // system locks held, so we want to do this all asynchronously. And we + // never want this to become fatal, so there is that too. + // + // Note: "callingPid == Process.myPid())" wouldn't be reliable because even if the caller + // is within the system server, if it calls Log.wtf() without clearning the calling + // identity, callingPid would still be of a remote caller. So we explicltly pass the + // process PID from the caller. + if (system || (immediateCallerPid == Process.myPid())) { mHandler.post(new Runnable() { @Override public void run() { handleApplicationWtfInner(callingUid, callingPid, app, tag, crashInfo); @@ -9788,7 +9813,7 @@ public class ActivityManagerService extends IActivityManager.Stub EventLogTags.writeAmWtf(UserHandle.getUserId(callingUid), callingPid, processName, r == null ? -1 : r.info.flags, tag, crashInfo.exceptionMessage); - StatsLog.write(StatsLog.WTF_OCCURRED, callingUid, tag, processName, + FrameworkStatsLog.write(FrameworkStatsLog.WTF_OCCURRED, callingUid, tag, processName, callingPid, (r != null) ? r.getProcessClassEnum() : 0); addErrorToDropBox("wtf", r, processName, null, null, null, tag, null, null, crashInfo); @@ -13027,7 +13052,7 @@ public class ActivityManagerService extends IActivityManager.Stub reportType, endTime-startTime, r.pkgList.mPkgList); for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED, r.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -13631,7 +13656,7 @@ public class ActivityManagerService extends IActivityManager.Stub reportType, endTime-startTime, r.pkgList.mPkgList); for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED, r.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -14198,7 +14223,7 @@ public class ActivityManagerService extends IActivityManager.Stub catPw.flush(); } dropBuilder.append(catSw.toString()); - StatsLog.write(StatsLog.LOW_MEM_REPORTED); + FrameworkStatsLog.write(FrameworkStatsLog.LOW_MEM_REPORTED); addErrorToDropBox("lowmem", null, "system_server", null, null, null, tag.toString(), dropBuilder.toString(), null, null); //Slog.i(TAG, "Sent to dropbox:"); @@ -14248,10 +14273,19 @@ public class ActivityManagerService extends IActivityManager.Stub cpr.launchingApp = null; cpr.notifyAll(); } - mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid)); + final int userId = UserHandle.getUserId(cpr.uid); + // Don't remove from provider map if it doesn't match + // could be a new content provider is starting + if (mProviderMap.getProviderByClass(cpr.name, userId) == cpr) { + mProviderMap.removeProviderByClass(cpr.name, userId); + } String names[] = cpr.info.authority.split(";"); for (int j = 0; j < names.length; j++) { - mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid)); + // Don't remove from provider map if it doesn't match + // could be a new content provider is starting + if (mProviderMap.getProviderByName(names[j], userId) == cpr) { + mProviderMap.removeProviderByName(names[j], userId); + } } } @@ -14346,6 +14380,10 @@ public class ActivityManagerService extends IActivityManager.Stub // Remove published content providers. for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); + if (cpr.proc != app) { + // If the hosting process record isn't really us, bail out + continue; + } final boolean alwaysRemove = app.bad || !allowRestart; final boolean inLaunching = removeDyingProviderLocked(app, cpr, alwaysRemove); if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) { @@ -14431,6 +14469,27 @@ public class ActivityManagerService extends IActivityManager.Stub mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid, null).sendToTarget(); + // If this is a precede instance of another process instance + allowRestart = true; + synchronized (app) { + if (app.mSuccessor != null) { + // We don't allow restart with this ProcessRecord now, + // because we have created a new one already. + allowRestart = false; + // If it's persistent, add the successor to mPersistentStartingProcesses + if (app.isPersistent() && !app.removed) { + if (mPersistentStartingProcesses.indexOf(app.mSuccessor) < 0) { + mPersistentStartingProcesses.add(app.mSuccessor); + } + } + // clean up the field so the successor's proc starter could proceed. + app.mSuccessor.mPrecedence = null; + app.mSuccessor = null; + // Notify if anyone is waiting for it. + app.notifyAll(); + } + } + // If the caller is restarting this app, then leave it in its // current lists and let the caller take care of it. if (restarting) { @@ -14460,7 +14519,7 @@ public class ActivityManagerService extends IActivityManager.Stub mAtmInternal.onCleanUpApplicationRecord(app.getWindowProcessController()); mProcessList.noteProcessDiedLocked(app); - if (restart && !app.isolated) { + if (restart && allowRestart && !app.isolated) { // We have components that still need to be running in the // process, so re-launch it. if (index < 0) { @@ -16838,7 +16897,7 @@ public class ActivityManagerService extends IActivityManager.Stub pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList); for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.PROCESS_MEMORY_STAT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED, proc.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -17198,7 +17257,7 @@ public class ActivityManagerService extends IActivityManager.Stub app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList); for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.EXCESSIVE_CPU_USAGE_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.EXCESSIVE_CPU_USAGE_REPORTED, app.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -17485,7 +17544,7 @@ public class ActivityManagerService extends IActivityManager.Stub } if (memFactor != mLastMemoryLevel) { EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel); - StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor); + FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor); } mLastMemoryLevel = memFactor; mLastNumProcesses = mProcessList.getLruSizeLocked(); diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index fa916202d553..d5fc14b1ac14 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -33,11 +33,11 @@ import android.telephony.ModemActivityInfo; import android.telephony.TelephonyManager; import android.util.IntArray; import android.util.Slog; -import android.util.StatsLog; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BatteryStatsImpl; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.function.pooled.PooledLambda; import libcore.util.EmptyArray; @@ -374,8 +374,8 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { // Clean up any UIDs if necessary. synchronized (mStats) { for (int uid : uidsToRemove) { - StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, -1, uid, - StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED); + FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, -1, uid, + FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED); mStats.removeIsolatedUidLocked(uid); } mStats.clearPendingRemovedUids(); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index a98b83b09a6a..ed6ace3335f5 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -53,7 +53,6 @@ import android.telephony.ModemActivityInfo; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; @@ -62,6 +61,7 @@ import com.android.internal.os.PowerProfile; import com.android.internal.os.RailStats; 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.server.LocalServices; @@ -347,16 +347,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub void noteProcessStart(String name, int uid) { synchronized (mStats) { mStats.noteProcessStartLocked(name, uid); - StatsLog.write(StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__STARTED); + 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); - StatsLog.write(StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED); + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, + FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED); } } @@ -369,15 +369,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub void noteProcessFinish(String name, int uid) { synchronized (mStats) { mStats.noteProcessFinishLocked(name, uid); - StatsLog.write(StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - StatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__FINISHED); + 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) { - StatsLog.write(StatsLog.UID_PROCESS_STATE_CHANGED, uid, + FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid, ActivityManager.processStateAmToProto(state)); mStats.noteUidProcessStateLocked(uid, state); @@ -453,8 +453,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteSyncStartLocked(name, uid); - StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, uid, null, name, - StatsLog.SYNC_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, + name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__ON); } } @@ -462,8 +462,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteSyncFinishLocked(name, uid); - StatsLog.write_non_chained(StatsLog.SYNC_STATE_CHANGED, uid, null, name, - StatsLog.SYNC_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, + name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__OFF); } } @@ -472,8 +472,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteJobStartLocked(name, uid); - StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uid, null, - name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED, + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED, + uid, null, name, + FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__STARTED, JobProtoEnums.STOP_REASON_UNKNOWN, standbyBucket, jobid); } } @@ -483,9 +484,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteJobFinishLocked(name, uid, stopReason); - StatsLog.write_non_chained(StatsLog.SCHEDULED_JOB_STATE_CHANGED, uid, null, - name, StatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED, - stopReason, standbyBucket, jobid); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED, + uid, null, name, + FrameworkStatsLog.SCHEDULED_JOB_STATE_CHANGED__STATE__FINISHED, stopReason, + standbyBucket, jobid); } } @@ -600,8 +602,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteStartSensorLocked(uid, sensor); - StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, uid, null, sensor, - StatsLog.SENSOR_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null, + sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON); } } @@ -609,8 +611,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteStopSensorLocked(uid, sensor); - StatsLog.write_non_chained(StatsLog.SENSOR_STATE_CHANGED, uid, null, - sensor, StatsLog.SENSOR_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null, + sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__OFF); } } @@ -646,7 +648,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); if (DBG) Slog.d(TAG, "begin noteScreenState"); synchronized (mStats) { - StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, state); + FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED, state); mStats.noteScreenStateLocked(state); } @@ -656,7 +658,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void noteScreenBrightness(int brightness) { enforceCallingPermission(); synchronized (mStats) { - StatsLog.write(StatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness); + FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness); mStats.noteScreenBrightnessLocked(brightness); } } @@ -742,8 +744,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.noteWifiOnLocked(); } - StatsLog.write(StatsLog.WIFI_ENABLED_STATE_CHANGED, - StatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED, + FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON); } public void noteWifiOff() { @@ -751,16 +753,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.noteWifiOffLocked(); } - StatsLog.write(StatsLog.WIFI_ENABLED_STATE_CHANGED, - StatsLog.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) { enforceCallingPermission(); synchronized (mStats) { mStats.noteAudioOnLocked(uid); - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null, - StatsLog.AUDIO_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null, + FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__ON); } } @@ -768,8 +770,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteAudioOffLocked(uid); - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null, - StatsLog.AUDIO_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null, + FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__OFF); } } @@ -777,8 +779,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteVideoOnLocked(uid); - StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid, null, - StatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid, + null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON); } } @@ -786,8 +788,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteVideoOffLocked(uid); - StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid, - null, StatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid, + null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF); } } @@ -795,8 +797,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteResetAudioLocked(); - StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, -1, null, - StatsLog.AUDIO_STATE_CHANGED__STATE__RESET); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, -1, null, + FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__RESET); } } @@ -804,8 +806,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteResetVideoLocked(); - StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, -1, null, - StatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, -1, + null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET); } } @@ -813,8 +815,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteFlashlightOnLocked(uid); - StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, uid, null, - StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON); } } @@ -822,8 +824,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteFlashlightOffLocked(uid); - StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, uid, null, - StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); } } @@ -832,8 +834,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (DBG) Slog.d(TAG, "begin noteStartCamera"); synchronized (mStats) { mStats.noteCameraOnLocked(uid); - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, uid, null, - StatsLog.CAMERA_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null, + FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__ON); } if (DBG) Slog.d(TAG, "end noteStartCamera"); } @@ -842,8 +844,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteCameraOffLocked(uid); - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, uid, null, - StatsLog.CAMERA_STATE_CHANGED__STATE__OFF); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null, + FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__OFF); } } @@ -851,8 +853,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteResetCameraLocked(); - StatsLog.write_non_chained(StatsLog.CAMERA_STATE_CHANGED, -1, null, - StatsLog.CAMERA_STATE_CHANGED__STATE__RESET); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, -1, null, + FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__RESET); } } @@ -860,8 +862,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub enforceCallingPermission(); synchronized (mStats) { mStats.noteResetFlashlightLocked(); - StatsLog.write_non_chained(StatsLog.FLASHLIGHT_STATE_CHANGED, -1, null, - StatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET); + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, -1, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET); } } @@ -888,8 +890,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.noteWifiRunningLocked(ws); } // TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too. - StatsLog.write(StatsLog.WIFI_RUNNING_STATE_CHANGED, - ws, StatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, + ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); } public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { @@ -897,10 +899,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.noteWifiRunningChangedLocked(oldWs, newWs); } - StatsLog.write(StatsLog.WIFI_RUNNING_STATE_CHANGED, - newWs, StatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); - StatsLog.write(StatsLog.WIFI_RUNNING_STATE_CHANGED, - oldWs, StatsLog.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) { @@ -908,8 +910,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.noteWifiStoppedLocked(ws); } - StatsLog.write(StatsLog.WIFI_RUNNING_STATE_CHANGED, - ws, StatsLog.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) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 6fca3f61e670..6697b5ab7c85 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -47,10 +47,11 @@ import android.permission.IPermissionManager; import android.util.EventLog; import android.util.Slog; import android.util.SparseIntArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import com.android.internal.util.FrameworkStatsLog; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.text.SimpleDateFormat; @@ -1255,8 +1256,8 @@ public final class BroadcastQueue { r.dispatchClockTime = System.currentTimeMillis(); if (mLogLatencyMetrics) { - StatsLog.write( - StatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED, + FrameworkStatsLog.write( + FrameworkStatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED, r.dispatchClockTime - r.enqueueClockTime); } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 6819578d9cdc..313c185a84c6 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -36,10 +36,10 @@ import android.provider.DeviceConfig.Properties; import android.text.TextUtils; import android.util.EventLog; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.ServiceThread; import java.io.FileOutputStream; @@ -849,11 +849,11 @@ public final class CachedAppOptimizer { // on every single compaction for a flag that will seldom change and the // impact of reading the wrong value here is low. if (mRandom.nextFloat() < mCompactStatsdSampleRate) { - StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction, - rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3], - rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time, - lastCompactAction, lastCompactTime, lastOomAdj, - ActivityManager.processStateAmToProto(procState), + FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPACTED, pid, name, + pendingAction, rssBefore[0], rssBefore[1], rssBefore[2], + rssBefore[3], rssAfter[0], rssAfter[1], rssAfter[2], + rssAfter[3], time, lastCompactAction, lastCompactTime, + lastOomAdj, ActivityManager.processStateAmToProto(procState), zramFreeKbBefore, zramFreeKbAfter); } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 3bd7d5c0d075..b107626e3bec 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -36,7 +36,9 @@ import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityManager.PROCESS_STATE_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_TOP; import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; +import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE; import static android.os.Process.SCHED_OTHER; import static android.os.Process.THREAD_GROUP_BACKGROUND; import static android.os.Process.THREAD_GROUP_DEFAULT; @@ -70,7 +72,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import android.app.ActivityManager; import android.app.ApplicationExitInfo; import android.app.usage.UsageEvents; -import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; import android.compat.annotation.EnabledAfter; @@ -82,6 +83,7 @@ import android.os.IBinder; import android.os.PowerManagerInternal; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; @@ -93,6 +95,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ProcessStats; +import com.android.internal.compat.IPlatformCompat; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.wm.ActivityServiceConnectionsHolder; @@ -137,8 +140,8 @@ public final class OomAdjuster { /** * In targetSdkVersion R and above, foreground service has camera and microphone while-in-use * capability only when the {@link android.R.attr#foregroundServiceType} is configured as - * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and - * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the + * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_CAMERA} and + * {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} respectively in the * manifest file. * In targetSdkVersion below R, foreground service automatically have camera and microphone * capabilities. @@ -210,6 +213,8 @@ public final class OomAdjuster { private ActiveUids mTmpUidRecords; private ArrayDeque<ProcessRecord> mTmpQueue; + private final IPlatformCompat mPlatformCompat; + OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) { this(service, processList, activeUids, createAdjusterThread()); } @@ -256,6 +261,8 @@ public final class OomAdjuster { mTmpQueue = new ArrayDeque<ProcessRecord>(mConstants.CUR_MAX_CACHED_PROCESSES << 1); mNumSlots = ((ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1) >> 1) / ProcessList.CACHED_APP_IMPORTANCE_LEVELS; + IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); + mPlatformCompat = IPlatformCompat.Stub.asInterface(b); } void initSettings() { @@ -1492,8 +1499,23 @@ public final class OomAdjuster { != 0 ? TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0; } if (s.mAllowWhileInUsePermissionInFgs) { - capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA - | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; + boolean enabled = false; + try { + enabled = mPlatformCompat.isChangeEnabled( + CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID, s.appInfo); + } catch (RemoteException e) { + } + if (enabled) { + capabilityFromFGS |= + (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA) + != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0; + capabilityFromFGS |= + (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE) + != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0; + } else { + capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA + | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; + } } } @@ -1667,7 +1689,13 @@ public final class OomAdjuster { // Go at most to BOUND_TOP, unless requested to elevate // to client's state. clientProcState = PROCESS_STATE_BOUND_TOP; - if (Compatibility.isChangeEnabled(PROCESS_CAPABILITY_CHANGE_ID)) { + boolean enabled = false; + try { + enabled = mPlatformCompat.isChangeEnabled( + PROCESS_CAPABILITY_CHANGE_ID, client.info); + } catch (RemoteException e) { + } + if (enabled) { if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) { // TOP process passes all capabilities to the service. capability = PROCESS_CAPABILITY_ALL; diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 73ca39b22de1..b19f2b37e61b 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -100,7 +100,6 @@ import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; -import android.util.StatsLog; import android.view.Display; import com.android.internal.annotations.GuardedBy; @@ -109,6 +108,7 @@ import com.android.internal.app.ProcessMap; import com.android.internal.app.procstats.ProcessStats; import com.android.internal.os.Zygote; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; import com.android.server.LocalServices; import com.android.server.ServiceThread; @@ -1473,7 +1473,7 @@ public final class ProcessList { proc.baseProcessTracker.reportCachedKill(proc.pkgList.mPkgList, proc.lastCachedPss); for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.CACHED_KILL_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED, proc.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -1495,7 +1495,7 @@ public final class ProcessList { proc.lastCachedPss); for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) { ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg); - StatsLog.write(StatsLog.CACHED_KILL_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.CACHED_KILL_REPORTED, proc.info.uid, holder.state.getName(), holder.state.getPackage(), @@ -1842,26 +1842,9 @@ public final class ProcessList { if (mService.mConstants.FLAG_PROCESS_START_ASYNC) { if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES, "Posting procStart msg for " + app.toShortString()); - mService.mProcStartHandler.post(() -> { - try { - final Process.ProcessStartResult startResult = startProcess(app.hostingRecord, - entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, - app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); - synchronized (mService) { - handleProcessStartedLocked(app, startResult, startSeq); - } - } catch (RuntimeException e) { - synchronized (mService) { - Slog.e(ActivityManagerService.TAG, "Failure starting process " - + app.processName, e); - mPendingStarts.remove(startSeq); - app.pendingStart = false; - mService.forceStopPackageLocked(app.info.packageName, - UserHandle.getAppId(app.uid), - false, false, true, false, false, app.userId, "start failure"); - } - } - }); + mService.mProcStartHandler.post(() -> handleProcessStart( + app, entryPoint, gids, runtimeFlags, mountExternal, requiredAbi, + instructionSet, invokeWith, startSeq)); return true; } else { try { @@ -1882,6 +1865,66 @@ public final class ProcessList { } } + /** + * Main handler routine to start the given process from the ProcStartHandler. + * + * <p>Note: this function doesn't hold the global AM lock intentionally.</p> + */ + private void handleProcessStart(final ProcessRecord app, final String entryPoint, + final int[] gids, final int runtimeFlags, final int mountExternal, + final String requiredAbi, final String instructionSet, + final String invokeWith, final long startSeq) { + // If there is a precede instance of the process, wait for its death with a timeout. + // Use local reference since we are not using locks here + final ProcessRecord precedence = app.mPrecedence; + if (precedence != null) { + final int pid = precedence.pid; + long now = System.currentTimeMillis(); + final long end = now + PROC_KILL_TIMEOUT; + try { + Process.waitForProcessDeath(pid, PROC_KILL_TIMEOUT); + // It's killed successfully, but we'd make sure the cleanup work is done. + synchronized (precedence) { + if (app.mPrecedence != null) { + now = System.currentTimeMillis(); + if (now < end) { + try { + precedence.wait(end - now); + } catch (InterruptedException e) { + } + } + } + if (app.mPrecedence != null) { + // The cleanup work hasn't be done yet, let's log it and continue. + Slog.w(TAG, precedence + " has died, but its cleanup isn't done"); + } + } + } catch (Exception e) { + // It's still alive... + Slog.wtf(TAG, precedence.toString() + " refused to die, but we need to launch " + + app); + } + } + try { + final Process.ProcessStartResult startResult = startProcess(app.hostingRecord, + entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, + app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); + synchronized (mService) { + handleProcessStartedLocked(app, startResult, startSeq); + } + } catch (RuntimeException e) { + synchronized (mService) { + Slog.e(ActivityManagerService.TAG, "Failure starting process " + + app.processName, e); + mPendingStarts.remove(startSeq); + app.pendingStart = false; + mService.forceStopPackageLocked(app.info.packageName, + UserHandle.getAppId(app.uid), + false, false, true, false, false, app.userId, "start failure"); + } + } + } + @GuardedBy("mService") public void killAppZygoteIfNeededLocked(AppZygote appZygote, boolean force) { final ApplicationInfo appInfo = appZygote.getAppInfo(); @@ -2136,6 +2179,7 @@ public final class ProcessList { + " app=" + app + " knownToBeDead=" + knownToBeDead + " thread=" + (app != null ? app.thread : null) + " pid=" + (app != null ? app.pid : -1)); + ProcessRecord precedence = null; if (app != null && app.pid > 0) { if ((!knownToBeDead && !app.killed) || app.thread == null) { // We already have the app running, or are waiting for it to @@ -2150,9 +2194,15 @@ public final class ProcessList { // An application record is attached to a previous process, // clean it up now. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app); - // do the killing - killProcAndWaitIfNecessaryLocked(app, true, app.uid == info.uid || app.isolated, - "startProcess: bad proc running, killing: %s", startTime); + checkSlow(startTime, "startProcess: bad proc running, killing"); + ProcessList.killProcessGroup(app.uid, app.pid); + checkSlow(startTime, "startProcess: done killing old proc"); + + Slog.wtf(TAG_PROCESSES, app.toString() + " is attached to a previous process"); + // We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup + // routine of it yet, but we'd set it as the precedence of the new process. + precedence = app; + app = null; } if (app == null) { @@ -2166,6 +2216,10 @@ public final class ProcessList { app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; + if (precedence != null) { + app.mPrecedence = precedence; + precedence.mSuccessor = app; + } checkSlow(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list @@ -2193,44 +2247,6 @@ public final class ProcessList { return success ? app : null; } - /** - * Kill (if asked to) and wait for the given process died if necessary - * @param app - The process record to kill - * @param doKill - Kill the given process record - * @param wait - Wait for the death of the given process - * @param formatString - The log message for slow operation - * @param startTime - The start timestamp of the operation - */ - @GuardedBy("mService") - void killProcAndWaitIfNecessaryLocked(final ProcessRecord app, final boolean doKill, - final boolean wait, final String formatString, final long startTime) { - - checkSlow(startTime, String.format(formatString, "before appDied")); - - if (doKill) { - // do the killing - ProcessList.killProcessGroup(app.uid, app.pid); - noteAppKill(app, ApplicationExitInfo.REASON_OTHER, - ApplicationExitInfo.SUBREASON_UNKNOWN, - String.format(formatString, "")); - } - - // wait for the death - if (wait) { - try { - Process.waitForProcessDeath(app.pid, PROC_KILL_TIMEOUT); - } catch (Exception e) { - // Maybe the process goes into zombie, use an expensive API to check again. - if (mService.isProcessAliveLocked(app)) { - Slog.w(TAG, String.format(formatString, - "waiting for app killing timed out")); - } - } - } - - checkSlow(startTime, String.format(formatString, "after appDied")); - } - @GuardedBy("mService") private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) { StringBuilder sb = null; @@ -2640,8 +2656,8 @@ public final class ProcessList { // about the process state of the isolated UID *before* it is registered with the // owning application. mService.mBatteryStatsService.addIsolatedUid(uid, info.uid); - StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid, - StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED); + FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, info.uid, uid, + FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED); } final ProcessRecord r = new ProcessRecord(mService, info, proc, uid); diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 1e2dd2deb568..fc33c25c4eaf 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -56,7 +56,6 @@ import android.util.DebugUtils; import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -66,6 +65,7 @@ import com.android.internal.app.procstats.ProcessStats; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.Zygote; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.wm.WindowProcessController; import com.android.server.wm.WindowProcessListener; @@ -320,6 +320,14 @@ class ProcessRecord implements WindowProcessListener { // set of disabled compat changes for the process (all others are enabled) long[] mDisabledCompatChanges; + // The precede instance of the process, which would exist when the previous process is killed + // but not fully dead yet; in this case, the new instance of the process should be held until + // this precede instance is fully dead. + volatile ProcessRecord mPrecedence; + // The succeeding instance of the process, which is going to be started after this process + // is killed successfully. + volatile ProcessRecord mSuccessor; + // Cached task info for OomAdjuster private static final int VALUE_INVALID = -1; private static final int VALUE_FALSE = 0; @@ -646,7 +654,7 @@ class ProcessRecord implements WindowProcessListener { origBase.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), pkgList.valueAt(ipkg).appVersion); @@ -681,7 +689,7 @@ class ProcessRecord implements WindowProcessListener { origBase.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), pkgList.valueAt(ipkg).appVersion); @@ -971,7 +979,7 @@ class ProcessRecord implements WindowProcessListener { setCurProcState(newState); setCurRawProcState(newState); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), ActivityManager.processStateAmToProto(mRepProcState), pkgList.valueAt(ipkg).appVersion); @@ -989,7 +997,7 @@ class ProcessRecord implements WindowProcessListener { baseProcessTracker.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), now, pkgList.mPkgList); for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), pkgList.valueAt(ipkg).appVersion); @@ -1075,7 +1083,7 @@ class ProcessRecord implements WindowProcessListener { void setReportedProcState(int repProcState) { mRepProcState = repProcState; for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, uid, processName, pkgList.keyAt(ipkg), ActivityManager.processStateAmToProto(mRepProcState), pkgList.valueAt(ipkg).appVersion); @@ -1606,16 +1614,16 @@ class ProcessRecord implements WindowProcessListener { Process.sendSignal(pid, Process.SIGNAL_QUIT); } - StatsLog.write(StatsLog.ANR_OCCURRED, uid, processName, + FrameworkStatsLog.write(FrameworkStatsLog.ANR_OCCURRED, uid, processName, activityShortComponentName == null ? "unknown": activityShortComponentName, annotation, (this.info != null) ? (this.info.isInstantApp() - ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE - : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE) - : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE, + ? FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE + : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE) + : FrameworkStatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE, isInterestingToUserLocked() - ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND - : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND, + ? FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND + : FrameworkStatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND, getProcessClassEnum(), (this.info != null) ? this.info.packageName : ""); final ProcessRecord parentPr = parentProcess != null diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 77e83bdfeb32..531bc5d1c7df 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -88,7 +88,6 @@ import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -2062,12 +2061,6 @@ public class AppOpsService extends IAppOpsService.Stub { } private void updatePermissionRevokedCompat(int uid, int switchCode, int mode) { - PackageManagerInternal packageManagerInternal = LocalServices.getService( - PackageManagerInternal.class); - if (packageManagerInternal.getUidTargetSdkVersion(uid) >= Build.VERSION_CODES.M) { - return; - } - PackageManager packageManager = mContext.getPackageManager(); String[] packageNames = packageManager.getPackagesForUid(uid); if (ArrayUtils.isEmpty(packageNames)) { diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java index ad20ed895805..ad7216600e61 100644 --- a/services/core/java/com/android/server/audio/RotationHelper.java +++ b/services/core/java/com/android/server/audio/RotationHelper.java @@ -80,6 +80,7 @@ class RotationHelper { static void updateOrientation() { // Even though we're responding to device orientation events, // use display rotation so audio stays in sync with video/dialogs + // TODO(b/148458001): Support multi-display int newRotation = ((WindowManager) sContext.getSystemService( Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); synchronized(sRotationLock) { diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java index 1f4563b801fe..0a30b763b8f4 100644 --- a/services/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java @@ -113,6 +113,7 @@ public class SystemBackupAgent extends BackupAgentHelper { throws IOException { // Slot in a restore helper for the older wallpaper backup schema to support restore // from devices still generating data in that format. + //TODO(b/147732386): Add multi-display support for wallpaper backup. addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, new String[] { WALLPAPER_IMAGE_KEY})); diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 8dd3242c947a..07fc9b7a7e5f 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -60,12 +60,12 @@ import android.security.KeyStore; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.SystemService; import java.util.ArrayList; @@ -707,7 +707,6 @@ public class BiometricService extends SystemService { checkPermission(); } - if (!Utils.isValidAuthenticatorConfig(authenticators)) { throw new SecurityException("Invalid authenticator configuration"); } @@ -720,19 +719,6 @@ public class BiometricService extends SystemService { try { biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName, false /* checkDevicePolicyManager */).second; - if (biometricConstantsResult != BiometricConstants.BIOMETRIC_SUCCESS - && Utils.isDeviceCredentialAllowed(bundle)) { - // If there's an issue with biometrics, but device credential is allowed and - // set up, return SUCCESS. If device credential isn't set up either, return - // ERROR_NO_DEVICE_CREDENTIAL. - if (mTrustManager.isDeviceSecure(userId)) { - biometricConstantsResult = BiometricConstants.BIOMETRIC_SUCCESS; - } else { - biometricConstantsResult = - BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL; - } - } - } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); } finally { @@ -1022,9 +1008,8 @@ public class BiometricService extends SystemService { } /** - * Checks if there are any available biometrics, and returns the modality. This method also - * returns errors through the callback (no biometric feature, hardware not detected, no - * templates enrolled, etc). This service must not start authentication if errors are sent. + * Depending on the requested authentication (credential/biometric combination), checks their + * availability. * * @param userId the user to check for * @param bundle passed from {@link BiometricPrompt} @@ -1037,24 +1022,27 @@ public class BiometricService extends SystemService { * {@link BiometricAuthenticator#TYPE_FACE} * and the error containing one of the {@link BiometricConstants} errors. * - * TODO(kchyn): Update this to handle DEVICE_CREDENTIAL better, reduce duplicate code in callers + * TODO(kchyn) should return Pair<Integer, Integer> with `first` being an actual bitfield + * taking BiometricAuthenticator#TYPE_CREDENTIAL as well. + * */ private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle, String opPackageName, boolean checkDevicePolicyManager) throws RemoteException { - if (!Utils.isBiometricAllowed(bundle) - && Utils.isDeviceCredentialAllowed(bundle) - && !mTrustManager.isDeviceSecure(userId)) { - // If only device credential is being checked, and the user doesn't have one set up - return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL); - } - // Assuming that authenticators are listed in priority-order, the rest of this function - // will attempt to find the first authenticator that's as strong or stronger than the - // requested strength, available, enrolled, and enabled. The tricky part is returning the - // correct error. Error strings that are modality-specific should also respect the + final boolean biometricRequested = Utils.isBiometricAllowed(bundle); + final boolean credentialRequested = Utils.isDeviceCredentialAllowed(bundle); + + final boolean biometricOk; + final boolean credentialOk = mTrustManager.isDeviceSecure(userId); + + // Assuming that biometric authenticators are listed in priority-order, the rest of this + // function will attempt to find the first authenticator that's as strong or stronger than + // the requested strength, available, enrolled, and enabled. The tricky part is returning + // the correct error. Error strings that are modality-specific should also respect the // priority-order. - // Find first authenticator that's strong enough, detected, enrolled, and enabled. + // Find first biometric authenticator that's strong enough, detected, enrolled, and enabled. + boolean disabledByDevicePolicy = false; boolean hasSufficientStrength = false; boolean isHardwareDetected = false; boolean hasTemplatesEnrolled = false; @@ -1065,52 +1053,96 @@ public class BiometricService extends SystemService { for (AuthenticatorWrapper authenticator : mAuthenticators) { final int actualStrength = authenticator.getActualStrength(); final int requestedStrength = Utils.getPublicBiometricStrength(bundle); - if (Utils.isAtLeastStrength(actualStrength, requestedStrength)) { - hasSufficientStrength = true; - modality = authenticator.modality; - if (authenticator.impl.isHardwareDetected(opPackageName)) { - isHardwareDetected = true; - if (firstHwAvailable == TYPE_NONE) { - // Store the first one since we want to return the error in correct - // priority order. - firstHwAvailable = modality; - } - if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) { - hasTemplatesEnrolled = true; - // If the device policy manager disables a specific biometric, skip it. - if (checkDevicePolicyManager && - isBiometricDisabledByDevicePolicy(modality, userId)) { - continue; - } - if (isEnabledForApp(modality, userId)) { - enabledForApps = true; - break; - } - } - } + + if (isBiometricDisabledByDevicePolicy(authenticator.modality, userId)) { + disabledByDevicePolicy = true; + continue; + } + disabledByDevicePolicy = false; + + if (!Utils.isAtLeastStrength(actualStrength, requestedStrength)) { + continue; + } + hasSufficientStrength = true; + + if (!authenticator.impl.isHardwareDetected(opPackageName)) { + continue; + } + isHardwareDetected = true; + + if (firstHwAvailable == TYPE_NONE) { + // Store the first one since we want to return the error in correct + // priority order. + firstHwAvailable = authenticator.modality; + } + + if (!authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) { + continue; } + hasTemplatesEnrolled = true; + + if (!isEnabledForApp(authenticator.modality, userId)) { + continue; + } + enabledForApps = true; + modality = authenticator.modality; + break; } + biometricOk = !disabledByDevicePolicy + && hasSufficientStrength && isHardwareDetected + && hasTemplatesEnrolled && enabledForApps; + Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId + " checkDevicePolicyManager=" + checkDevicePolicyManager + " isHardwareDetected=" + isHardwareDetected + " hasTemplatesEnrolled=" + hasTemplatesEnrolled - + " enabledForApps=" + enabledForApps); - - // Check error conditions - if (!hasSufficientStrength) { - return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT); - } else if (!isHardwareDetected) { - return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); - } else if (!hasTemplatesEnrolled) { - // Return the modality here so the correct error string can be sent. This error is - // preferred over !enabledForApps - return new Pair<>(firstHwAvailable, BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS); - } else if (!enabledForApps) { + + " enabledForApps=" + enabledForApps + + " disabledByDevicePolicy=" + disabledByDevicePolicy); + + if (biometricRequested && credentialRequested) { + if (credentialOk || biometricOk) { + if (!biometricOk) { + // If there's a problem with biometrics but device credential is + // allowed, only show credential UI. + bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, + Authenticators.DEVICE_CREDENTIAL); + } + return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS); + } else { + return new Pair<>(firstHwAvailable, + BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS); + } + } else if (biometricRequested) { + if (biometricOk) { + return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS); + } else if (disabledByDevicePolicy) { + return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); + } else if (!hasSufficientStrength) { + return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT); + } else if (!isHardwareDetected) { + return new Pair<>(firstHwAvailable, + BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); + } else if (!hasTemplatesEnrolled) { + return new Pair<>(firstHwAvailable, + BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS); + } else if (!enabledForApps) { + return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); + } else { + Slog.e(TAG, "Unexpected case"); + return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); + } + } else if (credentialRequested) { + if (credentialOk) { + return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_SUCCESS); + } else { + return new Pair<>(TYPE_NONE, + BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL); + } + } else { + Slog.e(TAG, "No authenticators requested"); return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE); } - - return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS); } private boolean isEnabledForApp(int modality, int userId) { @@ -1142,17 +1174,17 @@ public class BiometricService extends SystemService { + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT + ", RequireConfirmation: " + mCurrentAuthSession.mRequireConfirmation - + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED + + ", State: " + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED + ", Latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality(), mCurrentAuthSession.mUserId, mCurrentAuthSession.isCrypto(), BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, mCurrentAuthSession.mRequireConfirmation, - StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, + FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED, latency, mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId)); } else { @@ -1174,7 +1206,7 @@ public class BiometricService extends SystemService { + ", Latency: " + latency); } // Auth canceled - StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality(), mCurrentAuthSession.mUserId, mCurrentAuthSession.isCrypto(), @@ -1549,41 +1581,19 @@ public class BiometricService extends SystemService { int callingUid, int callingPid, int callingUserId) { mHandler.post(() -> { - int modality = TYPE_NONE; - int result; - try { final boolean checkDevicePolicyManager = bundle.getBoolean( BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false); final Pair<Integer, Integer> pair = checkAndGetAuthenticators(userId, bundle, opPackageName, checkDevicePolicyManager); - modality = pair.first; - result = pair.second; - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception", e); - result = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; - } + final int modality = pair.first; + final int result = pair.second; - try { - if (result == BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL) { - // If the app allowed device credential but the user hasn't set it up yet, - // return this error. - receiver.onError(modality, result, 0 /* vendorCode */); - } else if (result != BiometricConstants.BIOMETRIC_SUCCESS) { - if (Utils.isDeviceCredentialAllowed(bundle)) { - // If there's a problem with biometrics but device credential is allowed, - // only show credential UI. - bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, - Authenticators.DEVICE_CREDENTIAL); - authenticateInternal(token, sessionId, userId, receiver, opPackageName, - bundle, callingUid, callingPid, callingUserId, modality); - } else { - receiver.onError(modality, result, 0 /* vendorCode */); - } + if (result == BiometricConstants.BIOMETRIC_SUCCESS) { + authenticateInternal(token, sessionId, userId, receiver, opPackageName, + bundle, callingUid, callingPid, callingUserId, modality); } else { - // BIOMETRIC_SUCCESS, proceed to authentication - authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle, - callingUid, callingPid, callingUserId, modality); + receiver.onError(modality, result, 0 /* vendorCode */); } } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index 60f0e8e6c63d..687d9353ebd1 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -51,10 +51,10 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.SystemService; import java.util.ArrayList; @@ -371,7 +371,7 @@ public abstract class BiometricServiceBase extends SystemService + identifier.getName()); mUtils.removeBiometricForUser(getContext(), getTargetUserId(), identifier.getBiometricId()); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK); } @@ -551,7 +551,7 @@ public abstract class BiometricServiceBase extends SystemService + " failed to respond to cancel, starting client " + (mPendingClient != null ? mPendingClient.getOwnerString() : "null")); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_CANCEL_TIMED_OUT); mCurrentClient = null; @@ -673,8 +673,8 @@ public abstract class BiometricServiceBase extends SystemService 0 /*vendorCode */); }); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), - BiometricsProtoEnums.ISSUE_HAL_DEATH); + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + statsModality(), BiometricsProtoEnums.ISSUE_HAL_DEATH); } protected ClientMonitor getCurrentClient() { @@ -1249,7 +1249,7 @@ public abstract class BiometricServiceBase extends SystemService template.mIdentifier.getBiometricId(), 0 /* groupId */, template.mUserId, restricted, getContext().getPackageName()); removeInternal(client); - StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(), BiometricsProtoEnums.ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL); } else { diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java index ecf3864e3362..c03c77f41f57 100644 --- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java +++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java @@ -21,7 +21,8 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.util.Slog; -import android.util.StatsLog; + +import com.android.internal.util.FrameworkStatsLog; /** * Abstract class that adds logging functionality to the ClientMonitor classes. @@ -86,7 +87,7 @@ public abstract class LoggableMonitor { + ", AcquiredInfo: " + acquiredInfo + ", VendorCode: " + vendorCode); } - StatsLog.write(StatsLog.BIOMETRIC_ACQUIRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ACQUIRED, statsModality(), targetUserId, isCryptoOperation(), @@ -114,7 +115,7 @@ public abstract class LoggableMonitor { } else { Slog.v(TAG, "Error latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ERROR_OCCURRED, statsModality(), targetUserId, isCryptoOperation(), @@ -128,15 +129,15 @@ public abstract class LoggableMonitor { protected final void logOnAuthenticated(Context context, boolean authenticated, boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) { - int authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN; + int authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN; if (!authenticated) { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED; } else { // Authenticated if (isBiometricPrompt && requireConfirmation) { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION; } else { - authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED; + authState = FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED; } } @@ -157,7 +158,7 @@ public abstract class LoggableMonitor { Slog.v(TAG, "Authentication latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED, statsModality(), targetUserId, isCryptoOperation(), @@ -179,7 +180,7 @@ public abstract class LoggableMonitor { Slog.v(TAG, "Enroll latency: " + latency); } - StatsLog.write(StatsLog.BIOMETRIC_ENROLLED, + FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_ENROLLED, statsModality(), targetUserId, latency, diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index a0573db680b4..b512475e7971 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -962,9 +962,10 @@ public class FaceService extends BiometricServiceBase { @Override public void onLockoutChanged(long duration) { Slog.d(TAG, "onLockoutChanged: " + duration); + if (duration == 0) { mCurrentUserLockoutMode = AuthenticationClient.LOCKOUT_NONE; - } else if (duration == Long.MAX_VALUE) { + } else if (duration == -1 || duration == Long.MAX_VALUE) { mCurrentUserLockoutMode = AuthenticationClient.LOCKOUT_PERMANENT; } else { mCurrentUserLockoutMode = AuthenticationClient.LOCKOUT_TIMED; diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 8d261762a19b..7f7c9c4c7c1d 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -35,6 +35,7 @@ import com.android.internal.compat.IOverrideValidator; import com.android.internal.compat.OverrideAllowedState; import com.android.server.compat.config.Change; import com.android.server.compat.config.XmlParser; +import com.android.server.pm.ApexManager; import org.xmlpull.v1.XmlPullParserException; @@ -45,6 +46,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.xml.datatype.DatatypeConfigurationException; @@ -369,12 +371,18 @@ final class CompatConfig { Environment.getRootDirectory(), "etc", "compatconfig")); config.initConfigFromLib(Environment.buildPath( Environment.getRootDirectory(), "system_ext", "etc", "compatconfig")); + + List<ApexManager.ActiveApexInfo> apexes = ApexManager.getInstance().getActiveApexInfos(); + for (ApexManager.ActiveApexInfo apex : apexes) { + config.initConfigFromLib(Environment.buildPath( + apex.apexDirectory, "etc", "compatconfig")); + } return config; } void initConfigFromLib(File libraryDir) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { - Slog.e(TAG, "No directory " + libraryDir + ", skipping"); + Slog.d(TAG, "No directory " + libraryDir + ", skipping"); return; } for (File f : libraryDir.listFiles()) { diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index 4d5af9ac5d5c..bb8b12e86e16 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -16,11 +16,6 @@ package com.android.server.compat; -import static android.Manifest.permission.LOG_COMPAT_CHANGE; -import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG; -import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; - import android.app.ActivityManager; import android.app.IActivityManager; import android.content.Context; @@ -73,14 +68,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChange(long changeId, ApplicationInfo appInfo) { - checkCompatChangeLogPermission(); reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public void reportChangeByPackageName(long changeId, String packageName, int userId) { - checkCompatChangeLogPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return; @@ -90,13 +83,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void reportChangeByUid(long changeId, int uid) { - checkCompatChangeLogPermission(); reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED); } @Override public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) { - checkCompatChangeReadPermission(); if (mCompatConfig.isChangeEnabled(changeId, appInfo)) { reportChange(changeId, appInfo.uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED); @@ -109,7 +100,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) { - checkCompatChangeReadPermission(); ApplicationInfo appInfo = getApplicationInfo(packageName, userId); if (appInfo == null) { return true; @@ -119,7 +109,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public boolean isChangeEnabledByUid(long changeId, int uid) { - checkCompatChangeReadPermission(); String[] packages = mContext.getPackageManager().getPackagesForUid(uid); if (packages == null || packages.length == 0) { return true; @@ -152,7 +141,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverrides(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); killPackage(packageName); } @@ -160,13 +148,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.addOverrides(overrides, packageName); } @Override public void clearOverrides(String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); killPackage(packageName); } @@ -174,14 +160,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public void clearOverridesForTest(String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); mCompatConfig.removePackageOverrides(packageName); } @Override public boolean clearOverride(long changeId, String packageName) throws RemoteException, SecurityException { - checkCompatChangeOverridePermission(); boolean existed = mCompatConfig.removeOverride(changeId, packageName); killPackage(packageName); return existed; @@ -189,13 +173,11 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) { - checkCompatChangeReadPermission(); return mCompatConfig.getAppConfig(appInfo); } @Override public CompatibilityChangeInfo[] listAllChanges() { - checkCompatChangeReadPermission(); return mCompatConfig.dumpChanges(); } @@ -234,7 +216,6 @@ public class PlatformCompat extends IPlatformCompat.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - checkCompatChangeReadPermission(); if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return; mCompatConfig.dumpConfig(pw); } @@ -292,25 +273,4 @@ public class PlatformCompat extends IPlatformCompat.Stub { Binder.restoreCallingIdentity(identity); } } - - private void checkCompatChangeLogPermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot log compat change usage"); - } - } - - private void checkCompatChangeReadPermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot read compat change"); - } - } - - private void checkCompatChangeOverridePermission() throws SecurityException { - if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG) - != PERMISSION_GRANTED) { - throw new SecurityException("Cannot override compat change"); - } - } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index d66aec576137..3cfe9160494f 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -483,7 +483,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } - int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE); + int score = mNetworkScore.getLegacyScore(); if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 2c415570d5fa..25c761ab80ec 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -188,14 +188,14 @@ public class NetworkNotificationManager { int icon = getIcon(transportType, notifyType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); } else { title = r.getString(R.string.other_networks_no_internet); } @@ -203,19 +203,19 @@ public class NetworkNotificationManager { } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.network_partial_connectivity, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); @@ -236,7 +236,7 @@ public class NetworkNotificationManager { break; } } else if (notifyType == NotificationType.LOGGED_IN) { - title = WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()); + title = WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID()); details = r.getString(R.string.captive_portal_logged_in_detailed); } else if (notifyType == NotificationType.NETWORK_SWITCH) { String fromTransport = getTransportName(transportType); diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java index 0fdf2daf1c8d..49f0d35d2e78 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java @@ -109,7 +109,8 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { mWindowManager = (WindowManager)context.getSystemService( Context.WINDOW_SERVICE); - mDefaultDisplay = mWindowManager.getDefaultDisplay(); + // TODO(b/148458868): Support multi-display + mDefaultDisplay = mContext.getDisplay(); updateDefaultDisplayInfo(); resize(width, height, densityDpi, false /* doLayout */); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index 9c421524d723..9f76e1ed113d 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -34,6 +34,16 @@ import java.util.List; */ public abstract class InputMethodManagerInternal { /** + * Listener for input method list changed events. + */ + public interface InputMethodListListener { + /** + * Called with the list of the installed IMEs when it's updated. + */ + void onInputMethodListUpdated(List<InputMethodInfo> info, @UserIdInt int userId); + } + + /** * Called by the power manager to tell the input method manager whether it * should start watching for wake events. */ @@ -85,6 +95,11 @@ public abstract class InputMethodManagerInternal { public abstract boolean switchToInputMethod(String imeId, @UserIdInt int userId); /** + * Registers a new {@link InputMethodListListener}. + */ + public abstract void registerInputMethodListListener(InputMethodListListener listener); + + /** * Fake implementation of {@link InputMethodManagerInternal}. All the methods do nothing. */ private static final InputMethodManagerInternal NOP = @@ -117,6 +132,10 @@ public abstract class InputMethodManagerInternal { public boolean switchToInputMethod(String imeId, int userId) { return false; } + + @Override + public void registerInputMethodListListener(InputMethodListListener listener) { + } }; /** diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 15698e9795ec..47622f38f3f2 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -154,6 +154,7 @@ import com.android.internal.view.InputBindResult; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings; import com.android.server.statusbar.StatusBarManagerService; @@ -172,6 +173,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; /** @@ -214,6 +216,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000; static final int MSG_SYSTEM_UNLOCK_USER = 5000; + static final int MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED = 5010; static final int MSG_INLINE_SUGGESTIONS_REQUEST = 6000; @@ -689,6 +692,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final String mSlotIme; /** + * Registered {@link InputMethodListListeners}. + * This variable can be accessed from both of MainThread and BinderThread. + */ + private final CopyOnWriteArrayList<InputMethodListListener> mInputMethodListListeners = + new CopyOnWriteArrayList<>(); + + /** * Internal state snapshot when {@link #MSG_START_INPUT} message is about to be posted to the * internal message queue. Any subsequent state change inside {@link InputMethodManagerService} * will not affect those tasks that are already posted. @@ -3946,10 +3956,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case MSG_HARD_KEYBOARD_SWITCH_CHANGED: mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1); return true; - case MSG_SYSTEM_UNLOCK_USER: + case MSG_SYSTEM_UNLOCK_USER: { final int userId = msg.arg1; onUnlockUser(userId); return true; + } + case MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED: { + final int userId = msg.arg1; + final List<InputMethodInfo> imes = (List<InputMethodInfo>) msg.obj; + mInputMethodListListeners.forEach( + listener -> listener.onInputMethodListUpdated(imes, userId)); + return true; + } // --------------------------------------------------------------- case MSG_INLINE_SUGGESTIONS_REQUEST: @@ -4142,6 +4160,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // TODO: Make sure that mSwitchingController and mSettings are sharing the // the same enabled IMEs list. mSwitchingController.resetCircularListLocked(mContext); + + // Notify InputMethodListListeners of the new installed InputMethods. + final List<InputMethodInfo> inputMethodList = new ArrayList<>(mMethodList); + mHandler.obtainMessage(MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED, + mSettings.getCurrentUserId(), 0 /* unused */, inputMethodList).sendToTarget(); } // ---------------------------------------------------------------------- @@ -4606,6 +4629,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean switchToInputMethod(String imeId, int userId) { return mService.switchToInputMethod(imeId, userId); } + + @Override + public void registerInputMethodListListener(InputMethodListListener listener) { + mService.mInputMethodListListeners.addIfAbsent(listener); + } } @BinderThread diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index d09c478e320f..54af69432ee0 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -207,6 +207,12 @@ public final class MultiClientInputMethodManagerService { reportNotSupported(); return false; } + + @Override + public void registerInputMethodListListener( + InputMethodListListener listener) { + reportNotSupported(); + } }); } diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java index 5afa48a2b34d..997f21c9b6a3 100644 --- a/services/core/java/com/android/server/location/AbstractLocationProvider.java +++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java @@ -21,6 +21,7 @@ import android.content.Context; import android.location.Location; import android.os.Binder; import android.os.Bundle; +import android.util.ArraySet; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; @@ -120,7 +121,8 @@ public abstract class AbstractLocationProvider { if (providerPackageNames.equals(this.providerPackageNames)) { return this; } else { - return new State(allowed, properties, providerPackageNames); + return new State(allowed, properties, + Collections.unmodifiableSet(new ArraySet<>(providerPackageNames))); } } @@ -175,7 +177,6 @@ public abstract class AbstractLocationProvider { } } - protected final Context mContext; protected final Executor mExecutor; // we use a lock-free implementation to update state to ensure atomicity between updating the @@ -184,13 +185,11 @@ public abstract class AbstractLocationProvider { // before it was set, and should not miss any updates that occur after it was set). private final AtomicReference<InternalState> mInternalState; - protected AbstractLocationProvider(Context context, Executor executor) { - this(context, executor, Collections.singleton(context.getPackageName())); + protected AbstractLocationProvider(Executor executor, Context context) { + this(executor, Collections.singleton(context.getPackageName())); } - protected AbstractLocationProvider(Context context, Executor executor, - Set<String> packageNames) { - mContext = context; + protected AbstractLocationProvider(Executor executor, Set<String> packageNames) { mExecutor = executor; mInternalState = new AtomicReference<>( new InternalState(null, State.EMPTY_STATE.withProviderPackageNames(packageNames))); @@ -200,7 +199,7 @@ public abstract class AbstractLocationProvider { * Sets the listener and returns the state at the moment the listener was set. The listener can * expect to receive all state updates from after this point. */ - State setListener(@Nullable Listener listener) { + protected State setListener(@Nullable Listener listener) { return mInternalState.updateAndGet( internalState -> internalState.withListener(listener)).state; } @@ -208,14 +207,14 @@ public abstract class AbstractLocationProvider { /** * Retrieves the state of the provider. */ - State getState() { + public State getState() { return mInternalState.get().state; } /** * Sets the state of the provider to the new state. */ - void setState(State newState) { + protected void setState(State newState) { InternalState oldInternalState = mInternalState.getAndUpdate( internalState -> internalState.withState(newState)); if (newState.equals(oldInternalState.state)) { @@ -355,7 +354,7 @@ public abstract class AbstractLocationProvider { /** * Always invoked on the provider executor. */ - protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {} + protected abstract void onExtraCommand(int uid, int pid, String command, Bundle extras); /** * Requests a provider to enable itself for the given user id. @@ -368,7 +367,7 @@ public abstract class AbstractLocationProvider { /** * Always invoked on the provider executor. */ - protected void onRequestSetAllowed(boolean allowed) {} + protected abstract void onRequestSetAllowed(boolean allowed); /** * Dumps debug or log information. May be invoked from any thread. diff --git a/services/core/java/com/android/server/location/AppForegroundHelper.java b/services/core/java/com/android/server/location/AppForegroundHelper.java new file mode 100644 index 000000000000..8ddfc652d333 --- /dev/null +++ b/services/core/java/com/android/server/location/AppForegroundHelper.java @@ -0,0 +1,131 @@ +/* + * 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.location; + +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.RunningAppProcessInfo.Importance; + +import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Context; +import android.os.Binder; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; +import com.android.server.FgThread; + +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Provides accessors and listeners for all application foreground status. An application is + * considered foreground if it's uid's importance level is at or more important than + * {@link android.app.ActivityManager.RunningAppProcessInfo#IMPORTANCE_FOREGROUND_SERVICE}. + */ +public class AppForegroundHelper { + + /** + * Listener for application foreground state changes. + */ + public interface AppForegroundListener { + /** + * Called when an application's foreground state changes. + */ + void onAppForegroundChanged(int uid, boolean foreground); + } + + // importance constants decrement with increasing importance - this is our limit for an + // importance level we consider foreground. + private static final int FOREGROUND_IMPORTANCE_CUTOFF = IMPORTANCE_FOREGROUND_SERVICE; + + private static boolean isForeground(@Importance int importance) { + return importance <= FOREGROUND_IMPORTANCE_CUTOFF; + } + + private final Context mContext; + private final CopyOnWriteArrayList<AppForegroundListener> mListeners; + + @GuardedBy("this") + @Nullable private ActivityManager mActivityManager; + + public AppForegroundHelper(Context context) { + mContext = context; + mListeners = new CopyOnWriteArrayList<>(); + } + + /** Called when system is ready. */ + public synchronized void onSystemReady() { + if (mActivityManager != null) { + return; + } + + mActivityManager = Objects.requireNonNull(mContext.getSystemService(ActivityManager.class)); + mActivityManager.addOnUidImportanceListener(this::onAppForegroundChanged, + FOREGROUND_IMPORTANCE_CUTOFF); + } + + /** + * Adds a listener for app foreground changed events. Callbacks occur on an unspecified thread. + */ + public void addListener(AppForegroundListener listener) { + mListeners.add(listener); + } + + /** + * Removes a listener for app foreground changed events. + */ + public void removeListener(AppForegroundListener listener) { + mListeners.remove(listener); + } + + private void onAppForegroundChanged(int uid, @Importance int importance) { + // invoked on ui thread, move to fg thread so we don't block the ui thread + boolean foreground = isForeground(importance); + FgThread.getHandler().post(() -> { + for (AppForegroundListener listener : mListeners) { + listener.onAppForegroundChanged(uid, foreground); + } + }); + } + + /** + * Whether the given uid is currently foreground. + */ + public boolean isAppForeground(int uid) { + return isForeground(getImportance(uid)); + } + + /** + * Retrieves the current importance of the given uid. + * + * @deprecated Prefer {@link #isAppForeground(int)}. + */ + @Deprecated + @Importance + public int getImportance(int uid) { + synchronized (this) { + Preconditions.checkState(mActivityManager != null); + } + + long identity = Binder.clearCallingIdentity(); + try { + return mActivityManager.getUidImportance(uid); + } finally { + Binder.restoreCallingIdentity(identity); + } + } +} diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java index 81c06d7125f9..4e9c06761e54 100644 --- a/services/core/java/com/android/server/location/GeofenceManager.java +++ b/services/core/java/com/android/server/location/GeofenceManager.java @@ -77,7 +77,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish private final AppOpsManager mAppOps; private final PowerManager.WakeLock mWakeLock; - private final LocationSettingsStore mSettingsStore; + private final SettingsHelper mSettingsStore; private final Object mLock = new Object(); @@ -111,7 +111,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish */ private boolean mPendingUpdate; - public GeofenceManager(Context context, LocationSettingsStore settingsStore) { + public GeofenceManager(Context context, SettingsHelper settingsStore) { mContext = context; mHandler = new GeofenceHandler(FgThread.getHandler().getLooper()); diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java index 86a84e312899..b3546dc79572 100644 --- a/services/core/java/com/android/server/location/GnssConfiguration.java +++ b/services/core/java/com/android/server/location/GnssConfiguration.java @@ -23,7 +23,8 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; -import android.util.StatsLog; + +import com.android.internal.util.FrameworkStatsLog; import libcore.io.IoUtils; @@ -283,7 +284,7 @@ class GnssConfiguration { } private void logConfigurations() { - StatsLog.write(StatsLog.GNSS_CONFIGURATION_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.GNSS_CONFIGURATION_REPORTED, getSuplHost(), getSuplPort(0), getC2KHost(), diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 306e1e3afcd7..bcac4730cb8b 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -43,7 +43,6 @@ import android.os.BatteryStats; import android.os.Binder; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; @@ -64,7 +63,6 @@ import android.telephony.TelephonyManager; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; import android.util.Log; -import android.util.StatsLog; import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; @@ -75,7 +73,9 @@ import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import com.android.internal.location.gnssmetrics.GnssMetrics; +import com.android.internal.util.FrameworkStatsLog; import com.android.server.DeviceIdleInternal; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; @@ -408,7 +408,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // Available only on GNSS HAL 2.0 implementations and later. private GnssVisibilityControl mGnssVisibilityControl; - // Handler for processing events + private final Context mContext; private Handler mHandler; private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler; @@ -624,12 +624,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } - public GnssLocationProvider(Context context, Handler handler) { - super(context, new HandlerExecutor(handler)); + public GnssLocationProvider(Context context) { + super(FgThread.getExecutor(), context); ensureInitialized(); - mLooper = handler.getLooper(); + mContext = context; + mLooper = FgThread.getHandler().getLooper(); // Create a wake lock mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -1212,6 +1213,11 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } } + @Override + protected void onRequestSetAllowed(boolean allowed) { + // do nothing - the gnss provider is always allowed + } + private void deleteAidingData(Bundle extras) { int flags; @@ -1825,8 +1831,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements } native_send_ni_response(notificationId, userResponse); - StatsLog.write(StatsLog.GNSS_NI_EVENT_REPORTED, - StatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_RESPONSE, + FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED, + FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_RESPONSE, notificationId, /* niType= */ 0, /* needNotify= */ false, @@ -1891,8 +1897,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements notification.textEncoding = textEncoding; mNIHandler.handleNiNotification(notification); - StatsLog.write(StatsLog.GNSS_NI_EVENT_REPORTED, - StatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_REQUEST, + FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED, + FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_REQUEST, notification.notificationId, notification.niType, notification.needNotify, diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java index dd522b95a938..2b5fc7989d8b 100644 --- a/services/core/java/com/android/server/location/GnssVisibilityControl.java +++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java @@ -36,11 +36,11 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; -import android.util.StatsLog; import com.android.internal.R; import com.android.internal.location.GpsNetInitiatedHandler; import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.util.FrameworkStatsLog; import java.util.Arrays; import java.util.List; @@ -650,7 +650,7 @@ class GnssVisibilityControl { } private void logEvent(NfwNotification notification, boolean isPermissionMismatched) { - StatsLog.write(StatsLog.GNSS_NFW_NOTIFICATION_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NFW_NOTIFICATION_REPORTED, notification.mProxyAppPackageName, notification.mProtocolStack, notification.mOtherProtocolStackName, diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 1dee7a809c7e..19fb6694bbb5 100644 --- a/services/core/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java @@ -134,6 +134,7 @@ public class LocationProviderProxy extends AbstractLocationProvider { // also used to synchronized any state changes (setEnabled, setProperties, setState, etc) private final Object mLock = new Object(); + private final Context mContext; private final ServiceWatcher mServiceWatcher; @GuardedBy("mLock") @@ -143,10 +144,11 @@ public class LocationProviderProxy extends AbstractLocationProvider { private LocationProviderProxy(Context context, String action, int enableOverlayResId, int nonOverlayPackageResId) { - // safe to use direct executor since none of our callbacks call back into any code above - // this provider - they simply forward to the proxy service - super(context, DIRECT_EXECUTOR); + // safe to use direct executor even though this class has internal locks - all of our + // callbacks go to oneway binder transactions which cannot possibly be re-entrant + super(DIRECT_EXECUTOR, Collections.emptySet()); + mContext = context; mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), action, this::onBind, this::onUnbind, enableOverlayResId, nonOverlayPackageResId); diff --git a/services/core/java/com/android/server/location/LocationUsageLogger.java b/services/core/java/com/android/server/location/LocationUsageLogger.java index 755438b1a413..93e19df01cf3 100644 --- a/services/core/java/com/android/server/location/LocationUsageLogger.java +++ b/services/core/java/com/android/server/location/LocationUsageLogger.java @@ -24,9 +24,9 @@ import android.location.LocationManager; import android.location.LocationRequest; import android.stats.location.LocationStatsEnums; import android.util.Log; -import android.util.StatsLog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.FrameworkStatsLog; import java.time.Instant; @@ -61,8 +61,8 @@ public class LocationUsageLogger { boolean isLocationRequestNull = locationRequest == null; boolean isGeofenceNull = geofence == null; - StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, - apiInUse, packageName, + FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, + usageType, apiInUse, packageName, isLocationRequestNull ? LocationStatsEnums.PROVIDER_UNKNOWN : bucketizeProvider(locationRequest.getProvider()), @@ -101,7 +101,8 @@ public class LocationUsageLogger { return; } - StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, apiInUse, + FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, + usageType, apiInUse, /* package_name= */ null, bucketizeProvider(providerName), LocationStatsEnums.QUALITY_UNKNOWN, diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java index bcec8b12b371..b45b66017062 100644 --- a/services/core/java/com/android/server/location/MockProvider.java +++ b/services/core/java/com/android/server/location/MockProvider.java @@ -16,15 +16,18 @@ package com.android.server.location; +import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; + import android.annotation.Nullable; -import android.content.Context; import android.location.Location; +import android.os.Bundle; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Collections; /** * A mock location provider used by LocationManagerService to implement test providers. @@ -35,10 +38,9 @@ public class MockProvider extends AbstractLocationProvider { @Nullable private Location mLocation; - public MockProvider(Context context, ProviderProperties properties) { - // using a direct executor is only acceptable because this class is so simple it is trivial - // to verify that it does not acquire any locks or re-enter LMS from callbacks - super(context, Runnable::run); + public MockProvider(ProviderProperties properties) { + // using a direct executor is ok because this class has no locks that could deadlock + super(DIRECT_EXECUTOR, Collections.emptySet()); setProperties(properties); } @@ -59,6 +61,9 @@ public class MockProvider extends AbstractLocationProvider { public void onSetRequest(ProviderRequest request) {} @Override + protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {} + + @Override protected void onRequestSetAllowed(boolean allowed) { setAllowed(allowed); } diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java index 5b4f008a581b..b0e133061fc6 100644 --- a/services/core/java/com/android/server/location/MockableLocationProvider.java +++ b/services/core/java/com/android/server/location/MockableLocationProvider.java @@ -16,8 +16,9 @@ package com.android.server.location; +import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; + import android.annotation.Nullable; -import android.content.Context; import android.location.Location; import android.os.Bundle; @@ -68,10 +69,10 @@ public class MockableLocationProvider extends AbstractLocationProvider { * The client should expect that it may being to receive callbacks as soon as this constructor * is invoked. */ - public MockableLocationProvider(Context context, Object ownerLock, Listener listener) { + public MockableLocationProvider(Object ownerLock, Listener listener) { // using a direct executor is acceptable because all inbound calls are delegated to the // actual provider implementations which will use their own executors - super(context, Runnable::run, Collections.emptySet()); + super(DIRECT_EXECUTOR, Collections.emptySet()); mOwnerLock = ownerLock; mRequest = ProviderRequest.EMPTY_REQUEST; @@ -190,11 +191,6 @@ public class MockableLocationProvider extends AbstractLocationProvider { } } - @Override - public State getState() { - return super.getState(); - } - /** * Returns the current location request. */ @@ -204,6 +200,7 @@ public class MockableLocationProvider extends AbstractLocationProvider { } } + @Override protected void onSetRequest(ProviderRequest request) { synchronized (mOwnerLock) { if (request == mRequest) { @@ -218,6 +215,7 @@ public class MockableLocationProvider extends AbstractLocationProvider { } } + @Override protected void onExtraCommand(int uid, int pid, String command, Bundle extras) { synchronized (mOwnerLock) { if (mProvider != null) { @@ -226,6 +224,15 @@ public class MockableLocationProvider extends AbstractLocationProvider { } } + @Override + protected void onRequestSetAllowed(boolean allowed) { + synchronized (mOwnerLock) { + if (mProvider != null) { + mProvider.onRequestSetAllowed(allowed); + } + } + } + /** * Dumps the current provider implementation. */ diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java index ef157a39fa28..54dffff8b1df 100644 --- a/services/core/java/com/android/server/location/PassiveProvider.java +++ b/services/core/java/com/android/server/location/PassiveProvider.java @@ -16,9 +16,12 @@ package com.android.server.location; +import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; + import android.content.Context; import android.location.Criteria; import android.location.Location; +import android.os.Bundle; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; @@ -49,9 +52,8 @@ public class PassiveProvider extends AbstractLocationProvider { private volatile boolean mReportLocation; public PassiveProvider(Context context) { - // using a direct executor is only acceptable because this class is so simple it is trivial - // to verify that it does not acquire any locks or re-enter LMS from callbacks - super(context, Runnable::run); + // using a direct executor is ok because this class has no locks that could deadlock + super(DIRECT_EXECUTOR, context); mReportLocation = false; @@ -59,15 +61,26 @@ public class PassiveProvider extends AbstractLocationProvider { setAllowed(true); } + /** + * Pass a location into the passive provider. + */ + public void updateLocation(Location location) { + if (mReportLocation) { + reportLocation(location); + } + } + @Override public void onSetRequest(ProviderRequest request) { mReportLocation = request.reportLocation; } - public void updateLocation(Location location) { - if (mReportLocation) { - reportLocation(location); - } + @Override + protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {} + + @Override + protected void onRequestSetAllowed(boolean allowed) { + // do nothing - the passive provider is always allowed } @Override diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/SettingsHelper.java index 0e8720ebb08f..9163490fa777 100644 --- a/services/core/java/com/android/server/location/LocationSettingsStore.java +++ b/services/core/java/com/android/server/location/SettingsHelper.java @@ -54,7 +54,7 @@ import java.util.function.Supplier; /** * Provides accessors and listeners for all location related settings. */ -public class LocationSettingsStore { +public class SettingsHelper { /** * Listener for user-specific settings changes. @@ -99,7 +99,7 @@ public class LocationSettingsStore { private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist; // TODO: get rid of handler - public LocationSettingsStore(Context context, Handler handler) { + public SettingsHelper(Context context, Handler handler) { mContext = context; mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler); @@ -118,7 +118,7 @@ public class LocationSettingsStore { } /** Called when system is ready. */ - public synchronized void onSystemReady() { + public void onSystemReady() { mLocationMode.register(); mBackgroundThrottleIntervalMs.register(); mLocationPackageBlacklist.register(); @@ -135,7 +135,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the location enabled setting. + * Add a listener for changes to the location enabled setting. Callbacks occur on an unspecified + * thread. */ public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) { mLocationMode.addListener(listener); @@ -156,7 +157,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the background throttle interval. + * Add a listener for changes to the background throttle interval. Callbacks occur on an + * unspecified thread. */ public void addOnBackgroundThrottleIntervalChangedListener( GlobalSettingChangedListener listener) { @@ -204,7 +206,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the background throttle package whitelist. + * Add a listener for changes to the background throttle package whitelist. Callbacks occur on + * an unspecified thread. */ public void addOnBackgroundThrottlePackageWhitelistChangedListener( GlobalSettingChangedListener listener) { @@ -227,7 +230,8 @@ public class LocationSettingsStore { } /** - * Add a listener for changes to the ignore settings package whitelist. + * Add a listener for changes to the ignore settings package whitelist. Callbacks occur on an + * unspecified thread. */ public void addOnIgnoreSettingsPackageWhitelistChangedListener( GlobalSettingChangedListener listener) { @@ -340,6 +344,8 @@ public class LocationSettingsStore { private abstract static class ObservingSetting extends ContentObserver { private final CopyOnWriteArrayList<UserSettingChangedListener> mListeners; + + @GuardedBy("this") private boolean mRegistered; private ObservingSetting(Handler handler) { @@ -347,11 +353,11 @@ public class LocationSettingsStore { mListeners = new CopyOnWriteArrayList<>(); } - protected boolean isRegistered() { + protected synchronized boolean isRegistered() { return mRegistered; } - protected void register(Context context, Uri uri) { + protected synchronized void register(Context context, Uri uri) { if (mRegistered) { return; } @@ -393,8 +399,13 @@ public class LocationSettingsStore { } public int getValueForUser(int defaultValue, int userId) { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName, - defaultValue, userId); + long identity = Binder.clearCallingIdentity(); + try { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName, + defaultValue, userId); + } finally { + Binder.restoreCallingIdentity(identity); + } } } @@ -417,7 +428,7 @@ public class LocationSettingsStore { mCachedUserId = UserHandle.USER_NULL; } - public synchronized void register() { + public void register() { register(mContext, Settings.Secure.getUriFor(mSettingName)); } @@ -426,12 +437,17 @@ public class LocationSettingsStore { List<String> value = mCachedValue; if (userId != mCachedUserId) { - String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), - mSettingName, userId); - if (TextUtils.isEmpty(setting)) { - value = Collections.emptyList(); - } else { - value = Arrays.asList(setting.split(",")); + long identity = Binder.clearCallingIdentity(); + try { + String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), + mSettingName, userId); + if (TextUtils.isEmpty(setting)) { + value = Collections.emptyList(); + } else { + value = Arrays.asList(setting.split(",")); + } + } finally { + Binder.restoreCallingIdentity(identity); } if (isRegistered()) { @@ -473,8 +489,13 @@ public class LocationSettingsStore { } public long getValue(long defaultValue) { - return Settings.Global.getLong(mContext.getContentResolver(), mSettingName, - defaultValue); + long identity = Binder.clearCallingIdentity(); + try { + return Settings.Global.getLong(mContext.getContentResolver(), mSettingName, + defaultValue); + } finally { + Binder.restoreCallingIdentity(identity); + } } } @@ -499,18 +520,23 @@ public class LocationSettingsStore { mValid = false; } - public synchronized void register() { + public void register() { register(mContext, Settings.Global.getUriFor(mSettingName)); } public synchronized Set<String> getValue() { ArraySet<String> value = mCachedValue; if (!mValid) { - value = new ArraySet<>(mBaseValuesSupplier.get()); - String setting = Settings.Global.getString(mContext.getContentResolver(), - mSettingName); - if (!TextUtils.isEmpty(setting)) { - value.addAll(Arrays.asList(setting.split(","))); + long identity = Binder.clearCallingIdentity(); + try { + value = new ArraySet<>(mBaseValuesSupplier.get()); + String setting = Settings.Global.getString(mContext.getContentResolver(), + mSettingName); + if (!TextUtils.isEmpty(setting)) { + value.addAll(Arrays.asList(setting.split(","))); + } + } finally { + Binder.restoreCallingIdentity(identity); } if (isRegistered()) { diff --git a/services/core/java/com/android/server/location/UserInfoStore.java b/services/core/java/com/android/server/location/UserInfoHelper.java index f282ed26a831..94f3a88cb859 100644 --- a/services/core/java/com/android/server/location/UserInfoStore.java +++ b/services/core/java/com/android/server/location/UserInfoHelper.java @@ -42,7 +42,7 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * Provides accessors and listeners for all user info. */ -public class UserInfoStore { +public class UserInfoHelper { /** * Listener for current user changes. @@ -58,20 +58,16 @@ public class UserInfoStore { private final CopyOnWriteArrayList<UserChangedListener> mListeners; @GuardedBy("this") - @Nullable - private UserManager mUserManager; + @Nullable private UserManager mUserManager; - @GuardedBy("this") - @UserIdInt - private int mCurrentUserId; + @UserIdInt private volatile int mCurrentUserId; @GuardedBy("this") - @UserIdInt - private int mCachedParentUserId; + @UserIdInt private int mCachedParentUserId; @GuardedBy("this") private int[] mCachedProfileUserIds; - public UserInfoStore(Context context) { + public UserInfoHelper(Context context) { mContext = context; mListeners = new CopyOnWriteArrayList<>(); @@ -120,7 +116,7 @@ public class UserInfoStore { } /** - * Adds a listener for user changed events. + * Adds a listener for user changed events. Callbacks occur on an unspecified thread. */ public void addListener(UserChangedListener listener) { mListeners.add(listener); @@ -134,16 +130,13 @@ public class UserInfoStore { } private void onUserChanged(@UserIdInt int newUserId) { - int oldUserId; - synchronized (this) { - if (newUserId == mCurrentUserId) { - return; - } - - oldUserId = mCurrentUserId; - mCurrentUserId = newUserId; + if (newUserId == mCurrentUserId) { + return; } + int oldUserId = mCurrentUserId; + mCurrentUserId = newUserId; + for (UserChangedListener listener : mListeners) { listener.onUserChanged(oldUserId, newUserId); } @@ -161,7 +154,7 @@ public class UserInfoStore { * Returns the user id of the current user. */ @UserIdInt - public synchronized int getCurrentUserId() { + public int getCurrentUserId() { return mCurrentUserId; } @@ -169,9 +162,10 @@ public class UserInfoStore { * Returns true if the given user id is either the current user or a profile of the current * user. */ - public synchronized boolean isCurrentUserOrProfile(@UserIdInt int userId) { - return userId == mCurrentUserId || ArrayUtils.contains( - getProfileUserIdsForParentUser(mCurrentUserId), userId); + public boolean isCurrentUserOrProfile(@UserIdInt int userId) { + int currentUserId = mCurrentUserId; + return userId == currentUserId || ArrayUtils.contains( + getProfileUserIdsForParentUser(currentUserId), userId); } /** @@ -179,50 +173,44 @@ public class UserInfoStore { * is a parent or has no profiles. */ @UserIdInt - public synchronized int getParentUserId(@UserIdInt int userId) { - int parentUserId; - if (userId == mCachedParentUserId || ArrayUtils.contains(mCachedProfileUserIds, userId)) { - parentUserId = mCachedParentUserId; - } else { + public int getParentUserId(@UserIdInt int userId) { + synchronized (this) { + if (userId == mCachedParentUserId || ArrayUtils.contains(mCachedProfileUserIds, + userId)) { + return mCachedParentUserId; + } + Preconditions.checkState(mUserManager != null); + } - long identity = Binder.clearCallingIdentity(); - try { - UserInfo userInfo = mUserManager.getProfileParent(userId); - if (userInfo != null) { - parentUserId = userInfo.id; - } else { - // getProfileParent() returns null if the userId is already the parent... - parentUserId = userId; - } + int parentUserId; - // force profiles into cache - getProfileUserIdsForParentUser(parentUserId); - } finally { - Binder.restoreCallingIdentity(identity); - } + long identity = Binder.clearCallingIdentity(); + try { + UserInfo userInfo = mUserManager.getProfileParent(userId); + parentUserId = userInfo != null ? userInfo.id : userId; + } finally { + Binder.restoreCallingIdentity(identity); } + // force profiles into cache + getProfileUserIdsForParentUser(parentUserId); return parentUserId; } @GuardedBy("this") - private int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { - Preconditions.checkState(mUserManager != null); - - // only assert on debug builds as this is a more expensive check - if (Build.IS_DEBUGGABLE) { - long identity = Binder.clearCallingIdentity(); - try { - Preconditions.checkArgument(mUserManager.getProfileParent(parentUserId) == null); - } finally { - Binder.restoreCallingIdentity(identity); - } - } - + private synchronized int[] getProfileUserIdsForParentUser(@UserIdInt int parentUserId) { if (parentUserId != mCachedParentUserId) { long identity = Binder.clearCallingIdentity(); try { + Preconditions.checkState(mUserManager != null); + + // more expensive check - check that argument really is a parent user id + if (Build.IS_DEBUGGABLE) { + Preconditions.checkArgument( + mUserManager.getProfileParent(parentUserId) == null); + } + mCachedParentUserId = parentUserId; mCachedProfileUserIds = mUserManager.getProfileIdsWithDisabled(parentUserId); } finally { @@ -236,8 +224,9 @@ public class UserInfoStore { /** * Dump info for debugging. */ - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("Current User: " + mCurrentUserId + " " + Arrays.toString( - getProfileUserIdsForParentUser(mCurrentUserId))); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + int currentUserId = mCurrentUserId; + pw.println("Current User: " + currentUserId + " " + Arrays.toString( + getProfileUserIdsForParentUser(currentUserId))); } } 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 1eb2c525ff22..2bab9fa67eb0 100644 --- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java +++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java @@ -16,10 +16,11 @@ package com.android.server.location.gnss; +import static android.app.AppOpsManager.OP_FINE_LOCATION; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.location.GnssCapabilities; @@ -31,8 +32,8 @@ import android.location.IGnssStatusListener; import android.location.IGpsGeofenceHardware; import android.location.INetInitiatedListener; import android.location.Location; +import android.location.LocationManagerInternal; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Process; @@ -43,13 +44,12 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.FgThread; -import com.android.server.LocationManagerService; -import com.android.server.LocationManagerServiceUtils; +import com.android.internal.util.Preconditions; +import com.android.server.LocalServices; import com.android.server.LocationManagerServiceUtils.LinkedListener; import com.android.server.LocationManagerServiceUtils.LinkedListenerBase; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.CallerIdentity; import com.android.server.location.GnssBatchingProvider; import com.android.server.location.GnssCapabilitiesProvider; @@ -60,6 +60,7 @@ import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssStatusListenerHelper; import com.android.server.location.LocationUsageLogger; import com.android.server.location.RemoteListenerHelper; +import com.android.server.location.SettingsHelper; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -70,10 +71,18 @@ import java.util.function.Function; /** Manages Gnss providers and related Gnss functions for LocationManagerService. */ public class GnssManagerService { + private static final String TAG = "GnssManagerService"; - private static final boolean D = Log.isLoggable(TAG, Log.DEBUG); - // Providers + public static boolean isGnssSupported() { + return GnssLocationProvider.isSupported(); + } + + private final Context mContext; + private final SettingsHelper mSettingsHelper; + private final AppForegroundHelper mAppForegroundHelper; + private final LocationUsageLogger mLocationUsageLogger; + private final GnssLocationProvider mGnssLocationProvider; private final GnssStatusListenerHelper mGnssStatusProvider; private final GnssMeasurementsProvider mGnssMeasurementsProvider; @@ -83,58 +92,59 @@ public class GnssManagerService { private final GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider; private final GnssCapabilitiesProvider mGnssCapabilitiesProvider; private final GnssBatchingProvider mGnssBatchingProvider; - private final INetInitiatedListener mNetInitiatedListener; private final IGpsGeofenceHardware mGpsGeofenceProxy; - private final LocationManagerService mLocationManagerService; - private final LocationUsageLogger mLocationUsageLogger; @GuardedBy("mGnssMeasurementsListeners") - private final ArrayMap<IBinder, - LinkedListener<IGnssMeasurementsListener>> + private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>> mGnssMeasurementsListeners = new ArrayMap<>(); @GuardedBy("mGnssNavigationMessageListeners") - private final ArrayMap< - IBinder, LinkedListener<IGnssNavigationMessageListener>> + private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>> mGnssNavigationMessageListeners = new ArrayMap<>(); @GuardedBy("mGnssStatusListeners") private final ArrayMap<IBinder, LinkedListener<IGnssStatusListener>> mGnssStatusListeners = new ArrayMap<>(); + @GuardedBy("this") + @Nullable private LocationManagerInternal mLocationManagerInternal; + @GuardedBy("this") + @Nullable private AppOpsManager mAppOpsManager; + + private final Object mGnssBatchingLock = new Object(); + @GuardedBy("mGnssBatchingLock") - private IBatchedLocationCallback mGnssBatchingCallback; + @Nullable private IBatchedLocationCallback mGnssBatchingCallback; @GuardedBy("mGnssBatchingLock") - private LinkedListener<IBatchedLocationCallback> - mGnssBatchingDeathCallback; + @Nullable private LinkedListener<IBatchedLocationCallback> mGnssBatchingDeathCallback; @GuardedBy("mGnssBatchingLock") private boolean mGnssBatchingInProgress = false; - private final Object mGnssBatchingLock = new Object(); - private final Context mContext; - private final Handler mHandler; - - public GnssManagerService(LocationManagerService locationManagerService, - Context context, LocationUsageLogger locationUsageLogger) { - this(locationManagerService, context, - new GnssLocationProvider(context, FgThread.getHandler()), locationUsageLogger); + public GnssManagerService(Context context, SettingsHelper settingsHelper, + AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger) { + this(context, settingsHelper, appForegroundHelper, locationUsageLogger, null); } // Can use this constructor to inject GnssLocationProvider for testing @VisibleForTesting - public GnssManagerService(LocationManagerService locationManagerService, - Context context, - GnssLocationProvider gnssLocationProvider, - LocationUsageLogger locationUsageLogger) { + GnssManagerService(Context context, SettingsHelper settingsHelper, + AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger, + GnssLocationProvider gnssLocationProvider) { + Preconditions.checkState(isGnssSupported()); + mContext = context; - mHandler = FgThread.getHandler(); + mSettingsHelper = settingsHelper; + mAppForegroundHelper = appForegroundHelper; + mLocationUsageLogger = locationUsageLogger; - mGnssLocationProvider = - gnssLocationProvider; + if (gnssLocationProvider == null) { + gnssLocationProvider = new GnssLocationProvider(mContext); + } + mGnssLocationProvider = gnssLocationProvider; mGnssStatusProvider = mGnssLocationProvider.getGnssStatusProvider(); mGnssMeasurementsProvider = mGnssLocationProvider.getGnssMeasurementsProvider(); mGnssMeasurementCorrectionsProvider = @@ -144,108 +154,73 @@ public class GnssManagerService { mGnssMetricsProvider = mGnssLocationProvider.getGnssMetricsProvider(); mGnssCapabilitiesProvider = mGnssLocationProvider.getGnssCapabilitiesProvider(); mGnssBatchingProvider = mGnssLocationProvider.getGnssBatchingProvider(); - mNetInitiatedListener = mGnssLocationProvider.getNetInitiatedListener(); mGpsGeofenceProxy = mGnssLocationProvider.getGpsGeofenceProxy(); - mLocationManagerService = locationManagerService; - mLocationUsageLogger = locationUsageLogger; - - registerUidListener(); } - public static boolean isGnssSupported() { - return GnssLocationProvider.isSupported(); - } + /** Called when system is ready. */ + public synchronized void onSystemReady() { + if (mLocationManagerInternal != null) { + return; + } - private boolean hasGnssPermissions(String packageName) { - mContext.enforceCallingPermission( - Manifest.permission.ACCESS_FINE_LOCATION, - "Fine location permission not granted."); + mSettingsHelper.onSystemReady(); + mAppForegroundHelper.onSystemReady(); - int uid = Binder.getCallingUid(); - long identity = Binder.clearCallingIdentity(); - try { - return mContext.getSystemService( - AppOpsManager.class).checkOp(AppOpsManager.OP_FINE_LOCATION, uid, packageName) - == AppOpsManager.MODE_ALLOWED; - } finally { - Binder.restoreCallingIdentity(identity); - } + mLocationManagerInternal = LocalServices.getService(LocationManagerInternal.class); + mAppOpsManager = mContext.getSystemService(AppOpsManager.class); + + mAppForegroundHelper.addListener(this::onAppForegroundChanged); } + /** Retrieve the GnssLocationProvider. */ public GnssLocationProvider getGnssLocationProvider() { return mGnssLocationProvider; } + /** Retrieve the IGpsGeofenceHardware. */ public IGpsGeofenceHardware getGpsGeofenceProxy() { return mGpsGeofenceProxy; } /** * Get year of GNSS hardware. - * - * @return year of GNSS hardware as an int if possible, otherwise zero */ public int getGnssYearOfHardware() { - if (mGnssSystemInfoProvider != null) { - return mGnssSystemInfoProvider.getGnssYearOfHardware(); - } else { - return 0; - } + return mGnssSystemInfoProvider.getGnssYearOfHardware(); } /** * Get model name of GNSS hardware. - * - * @return GNSS hardware model name as a string if possible, otherwise null */ + @Nullable public String getGnssHardwareModelName() { - if (mGnssSystemInfoProvider != null) { - return mGnssSystemInfoProvider.getGnssHardwareModelName(); - } else { - return null; - } + return mGnssSystemInfoProvider.getGnssHardwareModelName(); } /** - * Get GNSS hardware capabilities. The capabilities are described in {@link - * android.location.GnssCapabilities} and their integer values correspond to the - * bit positions in the returned {@code long} value. - * - * @param packageName name of requesting package - * @return capabilities supported by the GNSS chipset + * Get GNSS hardware capabilities. The capabilities returned are a bitfield as described in + * {@link android.location.GnssCapabilities}. */ public long getGnssCapabilities(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to obtain GNSS chipset capabilities."); - if (!hasGnssPermissions(packageName) || mGnssCapabilitiesProvider == null) { + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); + + if (!checkLocationAppOp(packageName)) { return GnssCapabilities.INVALID_CAPABILITIES; } + return mGnssCapabilitiesProvider.getGnssCapabilities(); } /** * Get size of GNSS batch (GNSS location results are batched together for power savings). - * Requires LOCATION_HARDWARE and GNSS permissions. - * - * @param packageName name of requesting package - * @return size of the GNSS batch collection */ public int getGnssBatchSize(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "getGnssBatchSize called without GNSS permissions"); - return 0; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not get GNSS batch size. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return 0; } @@ -257,27 +232,12 @@ public class GnssManagerService { /** * Starts GNSS batch collection. GNSS positions are collected in a batch before being delivered * as a collection. - * - * @param periodNanos duration over which to collect GPS positions before delivering as a - * batch - * @param wakeOnFifoFull specifying whether to wake on full queue - * @param packageName name of requesting package - * @return true of batch started successfully, false otherwise */ public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "startGnssBatch called without GNSS permissions"); - return false; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not start GNSS batching. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } @@ -285,7 +245,6 @@ public class GnssManagerService { if (mGnssBatchingInProgress) { // Current design does not expect multiple starts to be called repeatedly Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch"); - // Try to clean up anyway, and continue stopGnssBatch(); } @@ -296,26 +255,13 @@ public class GnssManagerService { /** * Adds a GNSS batching callback for delivering GNSS location batch results. - * - * @param callback called when batching operation is complete to deliver GPS positions - * @param packageName name of requesting package - * @return true if callback is successfully added, false otherwise */ public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, @Nullable String featureId, @NonNull String listenerIdentity) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "addGnssBatchingCallback called without GNSS permissions"); - return false; - } - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not add GNSS batching callback. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } @@ -333,11 +279,9 @@ public class GnssManagerService { stopGnssBatch(); removeGnssBatchingCallback(); }); - if (!mGnssBatchingDeathCallback.linkToListenerDeathNotificationLocked( - callback.asBinder())) { - return false; - } - return true; + + return mGnssBatchingDeathCallback.linkToListenerDeathNotificationLocked( + callback.asBinder()); } } @@ -347,27 +291,14 @@ public class GnssManagerService { * @param packageName name of requesting package */ public void flushGnssBatch(String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); - - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "flushGnssBatch called without GNSS permissions"); - return; - } + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not flush GNSS batch. GNSS batching provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return; } synchronized (mGnssBatchingLock) { - if (!mGnssBatchingInProgress) { - Log.w(TAG, "flushGnssBatch called with no batch in progress"); - } mGnssBatchingProvider.flush(); } } @@ -376,17 +307,7 @@ public class GnssManagerService { * Removes GNSS batching callback. */ public void removeGnssBatchingCallback() { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); - - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not add GNSS batching callback. GNSS batching provider " - + "not available."); - return; - } + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); synchronized (mGnssBatchingLock) { mGnssBatchingDeathCallback.unlinkFromListenerDeathNotificationLocked( @@ -398,44 +319,17 @@ public class GnssManagerService { /** * Stop GNSS batch collection. - * - * @return true if GNSS batch successfully stopped, false otherwise */ public boolean stopGnssBatch() { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to access hardware batching"); + mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); - if (mGnssBatchingProvider == null) { - Log.e( - TAG, - "Can not stop GNSS batch. GNSS batching provider " - + "not available."); - return false; - } synchronized (mGnssBatchingLock) { mGnssBatchingInProgress = false; return mGnssBatchingProvider.stop(); } } - private void registerUidListener() { - mContext.getSystemService( - ActivityManager.class).addOnUidImportanceListener( - (uid, importance) -> { - // listener invoked on ui thread, move to our thread to reduce risk - // of blocking ui thread - mHandler.post( - () -> { - onForegroundChanged(uid, - LocationManagerServiceUtils.isImportanceForeground( - importance)); - }); - }, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); - } - - private void onForegroundChanged(int uid, boolean foreground) { + private void onAppForegroundChanged(int uid, boolean foreground) { synchronized (mGnssMeasurementsListeners) { updateListenersOnForegroundChangedLocked( mGnssMeasurementsListeners, @@ -463,8 +357,7 @@ public class GnssManagerService { } private <TListener extends IInterface> void updateListenersOnForegroundChangedLocked( - ArrayMap<IBinder, ? extends LinkedListenerBase> - gnssDataListeners, + Map<IBinder, ? extends LinkedListenerBase> gnssDataListeners, RemoteListenerHelper<TListener> gnssDataProvider, Function<IBinder, TListener> mapBinderToListener, int uid, @@ -477,18 +370,8 @@ public class GnssManagerService { continue; } - if (D) { - Log.d( - TAG, - linkedListener.getListenerName() - + " from uid " - + uid - + " is now " - + LocationManagerServiceUtils.foregroundAsString(foreground)); - } - TListener listener = mapBinderToListener.apply(entry.getKey()); - if (foreground || mLocationManagerService.isThrottlingExemptLocked(callerIdentity)) { + if (foreground || isThrottlingExempt(callerIdentity)) { gnssDataProvider.addListener(listener, callerIdentity); } else { gnssDataProvider.removeListener(listener); @@ -502,67 +385,49 @@ public class GnssManagerService { @Nullable String featureId, @NonNull String listenerIdentifier, RemoteListenerHelper<TListener> gnssDataProvider, - ArrayMap<IBinder, - LinkedListener<TListener>> gnssDataListeners, + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners, Consumer<TListener> binderDeathCallback) { - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "addGnssDataListenerLocked called without GNSS permissions"); - return false; - } + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); - if (gnssDataProvider == null) { - Log.e( - TAG, - "Can not add GNSS data listener. GNSS data provider " - + "not available."); + if (!checkLocationAppOp(packageName)) { return false; } - CallerIdentity callerIdentity = - new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), packageName, - featureId, listenerIdentifier); - LinkedListener<TListener> linkedListener = - new LocationManagerServiceUtils.LinkedListener<>( - listener, listenerIdentifier, callerIdentity, binderDeathCallback); + CallerIdentity callerIdentity = new CallerIdentity(Binder.getCallingUid(), + Binder.getCallingPid(), packageName, featureId, listenerIdentifier); + LinkedListener<TListener> linkedListener = new LinkedListener<>(listener, + listenerIdentifier, callerIdentity, binderDeathCallback); IBinder binder = listener.asBinder(); if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) { return false; } gnssDataListeners.put(binder, linkedListener); - long identity = Binder.clearCallingIdentity(); - try { - if (gnssDataProvider == mGnssMeasurementsProvider - || gnssDataProvider == mGnssStatusProvider) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_STARTED, - gnssDataProvider == mGnssMeasurementsProvider - ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER - : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, - packageName, - /* LocationRequest= */ null, - /* hasListener= */ true, - /* hasIntent= */ false, - /* geofence= */ null, - LocationManagerServiceUtils.getPackageImportance(packageName, - mContext)); - } - if (mLocationManagerService.isThrottlingExemptLocked(callerIdentity) - || LocationManagerServiceUtils.isImportanceForeground( - LocationManagerServiceUtils.getPackageImportance(packageName, mContext))) { - gnssDataProvider.addListener(listener, callerIdentity); - } - return true; - } finally { - Binder.restoreCallingIdentity(identity); + if (gnssDataProvider == mGnssMeasurementsProvider + || gnssDataProvider == mGnssStatusProvider) { + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_STARTED, + gnssDataProvider == mGnssMeasurementsProvider + ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER + : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, + packageName, + /* LocationRequest= */ null, + /* hasListener= */ true, + /* hasIntent= */ false, + /* geofence= */ null, + mAppForegroundHelper.getImportance(callerIdentity.mUid)); } + if (mAppForegroundHelper.isAppForeground(callerIdentity.mUid) + || isThrottlingExempt(callerIdentity)) { + gnssDataProvider.addListener(listener, callerIdentity); + } + return true; } - private <TListener extends IInterface> void removeGnssDataListener( + private <TListener extends IInterface> void removeGnssDataListenerLocked( TListener listener, RemoteListenerHelper<TListener> gnssDataProvider, - ArrayMap<IBinder, - LinkedListener<TListener>> gnssDataListeners) { + ArrayMap<IBinder, LinkedListener<TListener>> gnssDataListeners) { if (gnssDataProvider == null) { Log.e( TAG, @@ -577,25 +442,19 @@ public class GnssManagerService { if (linkedListener == null) { return; } - long identity = Binder.clearCallingIdentity(); - try { - if (gnssDataProvider == mGnssMeasurementsProvider - || gnssDataProvider == mGnssStatusProvider) { - mLocationUsageLogger.logLocationApiUsage( - LocationStatsEnums.USAGE_ENDED, - gnssDataProvider == mGnssMeasurementsProvider - ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER - : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, - linkedListener.getCallerIdentity().mPackageName, - /* LocationRequest= */ null, - /* hasListener= */ true, - /* hasIntent= */ false, - /* geofence= */ null, - LocationManagerServiceUtils.getPackageImportance( - linkedListener.getCallerIdentity().mPackageName, mContext)); - } - } finally { - Binder.restoreCallingIdentity(identity); + if (gnssDataProvider == mGnssMeasurementsProvider + || gnssDataProvider == mGnssStatusProvider) { + mLocationUsageLogger.logLocationApiUsage( + LocationStatsEnums.USAGE_ENDED, + gnssDataProvider == mGnssMeasurementsProvider + ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER + : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, + linkedListener.getCallerIdentity().mPackageName, + /* LocationRequest= */ null, + /* hasListener= */ true, + /* hasIntent= */ false, + /* geofence= */ null, + mAppForegroundHelper.getImportance(Binder.getCallingUid())); } linkedListener.unlinkFromListenerDeathNotificationLocked(binder); gnssDataProvider.removeListener(listener); @@ -603,10 +462,6 @@ public class GnssManagerService { /** * Registers listener for GNSS status changes. - * - * @param listener called when GNSS status changes - * @param packageName name of requesting package - * @return true if listener is successfully registered, false otherwise */ public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String featureId) { @@ -624,21 +479,15 @@ public class GnssManagerService { /** * Unregisters listener for GNSS status changes. - * - * @param listener called when GNSS status changes */ public void unregisterGnssStatusCallback(IGnssStatusListener listener) { synchronized (mGnssStatusListeners) { - removeGnssDataListener(listener, mGnssStatusProvider, mGnssStatusListeners); + removeGnssDataListenerLocked(listener, mGnssStatusProvider, mGnssStatusListeners); } } /** * Adds a GNSS measurements listener. - * - * @param listener called when GNSS measurements are received - * @param packageName name of requesting package - * @return true if listener is successfully added, false otherwise */ public boolean addGnssMeasurementsListener( IGnssMeasurementsListener listener, String packageName, @Nullable String featureId, @@ -657,47 +506,32 @@ public class GnssManagerService { /** * Injects GNSS measurement corrections. - * - * @param measurementCorrections GNSS measurement corrections - * @param packageName name of requesting package */ public void injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections, String packageName) { - mContext.enforceCallingPermission( - android.Manifest.permission.LOCATION_HARDWARE, - "Location Hardware permission not granted to inject GNSS measurement corrections."); - if (!hasGnssPermissions(packageName)) { - Log.e(TAG, "Can not inject GNSS corrections due to no permission."); - return; - } - if (mGnssMeasurementCorrectionsProvider == null) { - Log.e( - TAG, - "Can not inject GNSS corrections. GNSS measurement corrections provider " - + "not available."); + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); + mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); + + if (!checkLocationAppOp(packageName)) { return; } + mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections( measurementCorrections); } /** * Removes a GNSS measurements listener. - * - * @param listener called when GNSS measurements are received */ public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { synchronized (mGnssMeasurementsListeners) { - removeGnssDataListener(listener, mGnssMeasurementsProvider, mGnssMeasurementsListeners); + removeGnssDataListenerLocked(listener, mGnssMeasurementsProvider, + mGnssMeasurementsListeners); } } /** * Adds a GNSS navigation message listener. - * - * @param listener called when navigation message is received - * @param packageName name of requesting package - * @return true if listener is successfully added, false otherwise */ public boolean addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName, @@ -716,12 +550,10 @@ public class GnssManagerService { /** * Removes a GNSS navigation message listener. - * - * @param listener called when navigation message is received */ public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { synchronized (mGnssNavigationMessageListeners) { - removeGnssDataListener( + removeGnssDataListenerLocked( listener, mGnssNavigationMessageProvider, mGnssNavigationMessageListeners); } } @@ -729,43 +561,62 @@ public class GnssManagerService { /** * Send Ni Response, indicating a location request initiated by a network carrier. */ - public boolean sendNiResponse(int notifId, int userResponse) { - if (Binder.getCallingUid() != Process.myUid()) { - throw new SecurityException( - "calling sendNiResponse from outside of the system is not allowed"); - } + public void sendNiResponse(int notifId, int userResponse) { try { - return mNetInitiatedListener.sendNiResponse(notifId, userResponse); + mNetInitiatedListener.sendNiResponse(notifId, userResponse); } catch (RemoteException e) { Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); - return false; } } /** * Report location results to GNSS batching listener. - * - * @param locations batch of locations to report to GNSS batching callback */ public void onReportLocation(List<Location> locations) { - if (mGnssBatchingCallback == null) { - Log.e(TAG, "reportLocationBatch() called without active Callback"); + IBatchedLocationCallback gnssBatchingCallback; + synchronized (mGnssBatchingLock) { + gnssBatchingCallback = mGnssBatchingCallback; + } + + if (gnssBatchingCallback == null) { return; } try { - mGnssBatchingCallback.onLocationBatch(locations); + gnssBatchingCallback.onLocationBatch(locations); } catch (RemoteException e) { Log.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e); } } + private boolean isThrottlingExempt(CallerIdentity callerIdentity) { + if (callerIdentity.mUid == Process.SYSTEM_UID) { + return true; + } + + if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( + callerIdentity.mPackageName)) { + return true; + } + + synchronized (this) { + Preconditions.checkState(mLocationManagerInternal != null); + } + return mLocationManagerInternal.isProviderPackage(callerIdentity.mPackageName); + } + + private boolean checkLocationAppOp(String packageName) { + synchronized (this) { + Preconditions.checkState(mAppOpsManager != null); + } + return mAppOpsManager.checkOp(OP_FINE_LOCATION, Binder.getCallingUid(), packageName) + == AppOpsManager.MODE_ALLOWED; + } + /** - * Dump for debugging. + * Dump info for debugging. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); if (args.length > 0 && args[0].equals("--gnssmetrics")) { @@ -778,11 +629,8 @@ public class GnssManagerService { ipw.println("GnssMeasurement Listeners:"); ipw.increaseIndent(); synchronized (mGnssMeasurementsListeners) { - for (LinkedListenerBase listener : - mGnssMeasurementsListeners - .values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssMeasurementsListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); @@ -790,10 +638,8 @@ public class GnssManagerService { ipw.println("GnssNavigationMessage Listeners:"); ipw.increaseIndent(); synchronized (mGnssNavigationMessageListeners) { - for (LinkedListenerBase listener : - mGnssNavigationMessageListeners.values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssNavigationMessageListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); @@ -801,10 +647,8 @@ public class GnssManagerService { ipw.println("GnssStatus Listeners:"); ipw.increaseIndent(); synchronized (mGnssStatusListeners) { - for (LinkedListenerBase listener : - mGnssStatusListeners.values()) { - ipw.println(listener + ": " + mLocationManagerService.isThrottlingExemptLocked( - listener.getCallerIdentity())); + for (LinkedListenerBase listener : mGnssStatusListeners.values()) { + ipw.println(listener); } } ipw.decreaseIndent(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 80f6a941bfa0..7104790d0a7c 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -90,10 +90,10 @@ import static android.service.notification.NotificationListenerService.REASON_UN import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED; import static android.service.notification.NotificationListenerService.TRIM_FULL; import static android.service.notification.NotificationListenerService.TRIM_LIGHT; -import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING; -import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; +import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING; +import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE; import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER; import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER; import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER; @@ -219,7 +219,6 @@ import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; -import android.util.StatsLog; import android.util.Xml; import android.util.proto.ProtoOutputStream; import android.view.accessibility.AccessibilityEvent; @@ -232,6 +231,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.IPlatformCompat; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; +import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -243,6 +243,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; @@ -380,6 +381,8 @@ public class NotificationManagerService extends SystemService { private static final String SCHEME_TIMEOUT = "timeout"; private static final String EXTRA_KEY = "key"; + private static final int NOTIFICATION_INSTANCE_ID_MAX = (1 << 13); + /** * Apps that post custom toasts in the background will have those blocked. Apps can * still post toasts created with @@ -519,6 +522,7 @@ public class NotificationManagerService extends SystemService { private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable(); private NotificationRecordLogger mNotificationRecordLogger; + private InstanceIdSequence mNotificationInstanceIdSequence; private static class Archive { final int mBufferSize; @@ -1718,18 +1722,22 @@ public class NotificationManagerService extends SystemService { } public NotificationManagerService(Context context) { - this(context, new NotificationRecordLoggerImpl()); + this(context, + new NotificationRecordLoggerImpl(), + new InstanceIdSequence(NOTIFICATION_INSTANCE_ID_MAX)); } @VisibleForTesting public NotificationManagerService(Context context, - NotificationRecordLogger notificationRecordLogger) { + NotificationRecordLogger notificationRecordLogger, + InstanceIdSequence notificationInstanceIdSequence) { super(context); mNotificationRecordLogger = notificationRecordLogger; + mNotificationInstanceIdSequence = notificationInstanceIdSequence; Notification.processWhitelistToken = WHITELIST_TOKEN; } - // TODO - replace these methods with a single VisibleForTesting constructor + // TODO - replace these methods with new fields in the VisibleForTesting constructor @VisibleForTesting void setAudioManager(AudioManager audioMananger) { mAudioManager = audioMananger; @@ -5780,14 +5788,14 @@ public class NotificationManagerService extends SystemService { ? intent.resolveActivityInfo(context.getPackageManager(), 0) : null; if (info == null) { - StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, + FrameworkStatsLog.write(FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING); Log.w(TAG, "Unable to send as bubble -- couldn't find activity info for intent: " + intent); return false; } if (!ActivityInfo.isResizeableMode(info.resizeMode)) { - StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, + FrameworkStatsLog.write(FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName, BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE); Log.w(TAG, "Unable to send as bubble -- activity is not resizable for intent: " + intent); @@ -6291,6 +6299,14 @@ public class NotificationManagerService extends SystemService { NotificationRecord old = mNotificationsByKey.get(key); final StatusBarNotification n = r.sbn; final Notification notification = n.getNotification(); + + // Make sure the SBN has an instance ID for statsd logging. + if (old == null || old.sbn.getInstanceId() == null) { + n.setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); + } else { + n.setInstanceId(old.sbn.getInstanceId()); + } + int index = indexOfNotificationLocked(n.getKey()); if (index < 0) { mNotificationList.add(r); diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java index 03929e883852..9bbc39249e2e 100644 --- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java +++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java @@ -138,5 +138,9 @@ public interface NotificationRecordLogger { String assistant = r.getAdjustmentIssuer(); return (assistant == null) ? 0 : assistant.hashCode(); } + + int getInstanceId() { + return (r.sbn.getInstanceId() == null ? 0 : r.sbn.getInstanceId().getId()); + } } } diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java index d637ad5e368b..00b4c2b060ac 100644 --- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java +++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java @@ -35,7 +35,7 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger { /* int32 event_id = 1 */ p.getUiEvent().getId(), /* int32 uid = 2 */ r.getUid(), /* string package_name = 3 */ r.sbn.getPackageName(), - /* int32 instance_id = 4 */ 0, // TODO generate and fill instance ids + /* int32 instance_id = 4 */ p.getInstanceId(), /* int32 notification_id = 5 */ r.sbn.getId(), /* string notification_tag = 6 */ r.sbn.getTag(), /* string channel_id = 7 */ r.sbn.getChannelIdLogTag(), diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index c6d2b334bd71..4ff37a2040dd 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -95,15 +95,17 @@ public abstract class ApexManager { * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerFlattenedApex} * depending on whether this device supports APEX, i.e. {@link ApexProperties#updatable()} * evaluates to {@code true}. + * @hide */ - static ApexManager getInstance() { + public static ApexManager getInstance() { return sApexManagerSingleton.get(); } /** * Minimal information about APEX mount points and the original APEX package they refer to. + * @hide */ - static class ActiveApexInfo { + public static class ActiveApexInfo { @Nullable public final String apexModuleName; public final File apexDirectory; public final File preInstalledApexPath; @@ -130,8 +132,10 @@ public abstract class ApexManager { /** * Returns {@link ActiveApexInfo} records relative to all active APEX packages. + * + * @hide */ - abstract List<ActiveApexInfo> getActiveApexInfos(); + public abstract List<ActiveApexInfo> getActiveApexInfos(); abstract void systemReady(Context context); @@ -272,6 +276,21 @@ public abstract class ApexManager { public abstract String getApexModuleNameForPackageName(String apexPackageName); /** + * Copies the CE apex data directory for the given {@code userId} to a backup location, for use + * in case of rollback. + * + * @return long inode for the snapshot directory if the snapshot was successful, or -1 if not + */ + public abstract long snapshotCeData(int userId, int rollbackId, String apexPackageName); + + /** + * Restores the snapshot of the CE apex data directory for the given {@code userId}. + * + * @return boolean true if the restore was successful + */ + public abstract boolean restoreCeData(int userId, int rollbackId, String apexPackageName); + + /** * Dumps various state information to the provided {@link PrintWriter} object. * * @param pw the {@link PrintWriter} object to send information to. @@ -347,7 +366,7 @@ public abstract class ApexManager { } @Override - List<ActiveApexInfo> getActiveApexInfos() { + public List<ActiveApexInfo> getActiveApexInfos() { synchronized (mLock) { if (mActiveApexInfosCache == null) { try { @@ -662,6 +681,45 @@ public abstract class ApexManager { } } + @Override + public long snapshotCeData(int userId, int rollbackId, String apexPackageName) { + populatePackageNameToApexModuleNameIfNeeded(); + String apexModuleName; + synchronized (mLock) { + apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); + } + if (apexModuleName == null) { + Slog.e(TAG, "Invalid apex package name: " + apexPackageName); + return -1; + } + try { + return mApexService.snapshotCeData(userId, rollbackId, apexModuleName); + } catch (Exception e) { + Slog.e(TAG, e.getMessage(), e); + return -1; + } + } + + @Override + public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) { + populatePackageNameToApexModuleNameIfNeeded(); + String apexModuleName; + synchronized (mLock) { + apexModuleName = mPackageNameToApexModuleName.get(apexPackageName); + } + if (apexModuleName == null) { + Slog.e(TAG, "Invalid apex package name: " + apexPackageName); + return false; + } + try { + mApexService.restoreCeData(userId, rollbackId, apexModuleName); + return true; + } catch (Exception e) { + Slog.e(TAG, e.getMessage(), e); + return false; + } + } + /** * Dump information about the packages contained in a particular cache * @param packagesCache the cache to print information about. @@ -744,7 +802,7 @@ public abstract class ApexManager { */ private static final class ApexManagerFlattenedApex extends ApexManager { @Override - List<ActiveApexInfo> getActiveApexInfos() { + public List<ActiveApexInfo> getActiveApexInfos() { // There is no apexd running in case of flattened apex // We look up the /apex directory and identify the active APEX modules from there. // As "preinstalled" path, we just report /system since in the case of flattened APEX @@ -865,6 +923,16 @@ public abstract class ApexManager { } @Override + public long snapshotCeData(int userId, int rollbackId, String apexPackageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) { + throw new UnsupportedOperationException(); + } + + @Override void dump(PrintWriter pw, String packageName) { // No-op } diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 5c17bec0db47..89f24d86192c 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -68,9 +68,8 @@ public class AppsFilter { // Logs all filtering instead of enforcing private static final boolean DEBUG_ALLOW_ALL = false; - - @SuppressWarnings("ConstantExpression") - private static final boolean DEBUG_LOGGING = false | DEBUG_ALLOW_ALL; + private static final boolean DEBUG_LOGGING = false; + private static final boolean FEATURE_ENABLED_BY_DEFAULT = false; /** * This contains a list of app UIDs that are implicitly queryable because another app explicitly @@ -136,7 +135,7 @@ public class AppsFilter { private static class FeatureConfigImpl implements FeatureConfig { private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled"; private final PackageManagerService.Injector mInjector; - private volatile boolean mFeatureEnabled = false; + private volatile boolean mFeatureEnabled = FEATURE_ENABLED_BY_DEFAULT; private FeatureConfigImpl(PackageManagerService.Injector injector) { mInjector = injector; @@ -145,14 +144,15 @@ public class AppsFilter { @Override public void onSystemReady() { mFeatureEnabled = DeviceConfig.getBoolean( - NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, false); + NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME, + FEATURE_ENABLED_BY_DEFAULT); DeviceConfig.addOnPropertiesChangedListener( NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(), properties -> { if (properties.getKeyset().contains(FILTERING_ENABLED_NAME)) { synchronized (FeatureConfigImpl.this) { mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME, - false); + FEATURE_ENABLED_BY_DEFAULT); } } }); @@ -613,6 +613,7 @@ public class AppsFilter { } finally { Trace.endSection(); } + if (callingPkgSetting != null) { if (callingPkgInstruments(callingPkgSetting, targetPkgSetting, targetName)) { return false; @@ -626,28 +627,34 @@ public class AppsFilter { } } - if (callingSharedPkgSettings != null) { - int size = callingSharedPkgSettings.size(); - for (int index = 0; index < size; index++) { - PackageSetting pkgSetting = callingSharedPkgSettings.valueAt(index); - if (mOverlayReferenceMapper.isValidActor(targetName, pkgSetting.name)) { + try { + Trace.beginSection("mOverlayReferenceMapper"); + if (callingSharedPkgSettings != null) { + int size = callingSharedPkgSettings.size(); + for (int index = 0; index < size; index++) { + PackageSetting pkgSetting = callingSharedPkgSettings.valueAt(index); + if (mOverlayReferenceMapper.isValidActor(targetName, pkgSetting.name)) { + if (DEBUG_LOGGING) { + log(callingPkgSetting, targetPkgSetting, + "matches shared user of package that acts on target of " + + "overlay"); + } + return false; + } + } + } else { + if (mOverlayReferenceMapper.isValidActor(targetName, callingPkgSetting.name)) { if (DEBUG_LOGGING) { - log(callingPkgSetting, targetPkgSetting, - "matches shared user of package that acts on target of " - + "overlay"); + log(callingPkgSetting, targetPkgSetting, "acts on target of overlay"); } return false; } } - } else { - if (mOverlayReferenceMapper.isValidActor(targetName, callingPkgSetting.name)) { - if (DEBUG_LOGGING) { - log(callingPkgSetting, targetPkgSetting, "acts on target of overlay"); - } - return false; - } + } finally { + Trace.endSection(); } + return true; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 43ed25f944c6..38da8ab26962 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -147,17 +147,15 @@ import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String TAG = "PackageInstallerSession"; private static final boolean LOGD = true; private static final String REMOVE_MARKER_EXTENSION = ".removed"; - private static final int MSG_COMMIT = 1; - private static final int MSG_ON_PACKAGE_INSTALLED = 2; - private static final int MSG_SEAL = 3; - private static final int MSG_STREAM_AND_VALIDATE = 4; + private static final int MSG_STREAM_VALIDATE_AND_COMMIT = 1; + private static final int MSG_INSTALL = 2; + private static final int MSG_ON_PACKAGE_INSTALLED = 3; /** XML constants used for persisting a session */ static final String TAG_SESSION = "session"; @@ -415,14 +413,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public boolean handleMessage(Message msg) { switch (msg.what) { - case MSG_SEAL: - handleSeal((IntentSender) msg.obj); + case MSG_STREAM_VALIDATE_AND_COMMIT: + handleStreamValidateAndCommit(); break; - case MSG_STREAM_AND_VALIDATE: - handleStreamAndValidate(); - break; - case MSG_COMMIT: - handleCommit(); + case MSG_INSTALL: + handleInstall(); break; case MSG_ON_PACKAGE_INSTALLED: final SomeArgs args = (SomeArgs) msg.obj; @@ -740,22 +735,33 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } return result; } - return mFiles.stream().map(fileInfo -> fileInfo.name).toArray(String[]::new); + + String[] result = new String[mFiles.size()]; + for (int i = 0, size = mFiles.size(); i < size; ++i) { + result[i] = mFiles.get(i).name; + } + return result; } - private static File[] filterFiles(File parent, String[] names, FileFilter filter) { - return Arrays.stream(names).map(name -> new File(parent, name)).filter( - file -> filter.accept(file)).toArray(File[]::new); + private static ArrayList<File> filterFiles(File parent, String[] names, FileFilter filter) { + ArrayList<File> result = new ArrayList<>(names.length); + for (String name : names) { + File file = new File(parent, name); + if (filter.accept(file)) { + result.add(file); + } + } + return result; } @GuardedBy("mLock") - private File[] getAddedApksLocked() { + private List<File> getAddedApksLocked() { String[] names = getNamesLocked(); return filterFiles(stageDir, names, sAddedApkFilter); } @GuardedBy("mLock") - private File[] getRemovedFilesLocked() { + private List<File> getRemovedFilesLocked() { String[] names = getNamesLocked(); return filterFiles(stageDir, names, sRemovedFilter); } @@ -1011,24 +1017,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { + mParentSessionId + " and may not be committed directly."); } - assertCanBeCommitted(forTransfer); - - if (isMultiPackage()) { - for (int i = mChildSessionIds.size() - 1; i >= 0; --i) { - final int childSessionId = mChildSessionIds.keyAt(i); - mSessionProvider.getSession(childSessionId).assertCanBeCommitted(forTransfer); - } - } - - if (mIncrementalFileStorages != null) { - mIncrementalFileStorages.finishSetUp(); - } - - mHandler.obtainMessage(MSG_SEAL, statusReceiver).sendToTarget(); - } - - private void handleSeal(@NonNull IntentSender statusReceiver) { - if (!markAsSealed(statusReceiver)) { + if (!markAsSealed(statusReceiver, forTransfer)) { return; } if (isMultiPackage()) { @@ -1042,7 +1031,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // seal all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mSessionProvider.getSession(childSessionId) - .markAsSealed(childIntentSender)) { + .markAsSealed(childIntentSender, forTransfer)) { sealFailed = true; } } @@ -1051,20 +1040,24 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - dispatchStreamAndValidate(); + if (mIncrementalFileStorages != null) { + mIncrementalFileStorages.finishSetUp(); + } + + dispatchStreamValidateAndCommit(); } - private void dispatchStreamAndValidate() { - mHandler.obtainMessage(MSG_STREAM_AND_VALIDATE).sendToTarget(); + private void dispatchStreamValidateAndCommit() { + mHandler.obtainMessage(MSG_STREAM_VALIDATE_AND_COMMIT).sendToTarget(); } - private void handleStreamAndValidate() { + private void handleStreamValidateAndCommit() { // TODO(b/136132412): update with new APIs if (mIncrementalFileStorages != null) { mIncrementalFileStorages.startLoading(); } - boolean commitFailed = !markAsCommitted(); + boolean success = streamValidateAndCommit(); if (isMultiPackage()) { for (int i = mChildSessionIds.size() - 1; i >= 0; --i) { @@ -1072,26 +1065,27 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // commit all children, regardless if any of them fail; we'll throw/return // as appropriate once all children have been processed if (!mSessionProvider.getSession(childSessionId) - .markAsCommitted()) { - commitFailed = true; + .streamValidateAndCommit()) { + success = false; } } } - if (commitFailed) { + if (!success) { return; } - mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); + mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); } private final class FileSystemConnector extends IPackageInstallerSessionFileSystemConnector.Stub { - final Set<String> mAddedFiles; + final Set<String> mAddedFiles = new ArraySet<>(); FileSystemConnector(List<InstallationFile> addedFiles) { - mAddedFiles = addedFiles.stream().map(file -> file.getName()).collect( - Collectors.toSet()); + for (InstallationFile file : addedFiles) { + mAddedFiles.add(file.getName()); + } } @Override @@ -1201,9 +1195,16 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } /** - * Sanity checks to make sure it's ok to commit the session. + * If this was not already called, the session will be sealed. + * + * This method may be called multiple times to update the status receiver validate caller + * permissions. */ - private void assertCanBeCommitted(boolean forTransfer) { + private boolean markAsSealed(@NonNull IntentSender statusReceiver, boolean forTransfer) { + Objects.requireNonNull(statusReceiver); + + List<PackageInstallerSession> childSessions = getChildSessions(); + synchronized (mLock) { assertCallerIsOwnerOrRootLocked(); assertPreparedAndNotDestroyedLocked("commit"); @@ -1226,21 +1227,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new IllegalArgumentException("Session has been transferred"); } } - } - } - - /** - * If this was not already called, the session will be sealed. - * - * This method may be called multiple times to update the status receiver validate caller - * permissions. - */ - private boolean markAsSealed(@NonNull IntentSender statusReceiver) { - Objects.requireNonNull(statusReceiver); - List<PackageInstallerSession> childSessions = getChildSessions(); - - synchronized (mLock) { mRemoteStatusReceiver = statusReceiver; // After updating the observer, we can skip re-sealing. @@ -1263,10 +1250,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return true; } - private boolean markAsCommitted() { + private boolean streamValidateAndCommit() { synchronized (mLock) { - Objects.requireNonNull(mRemoteStatusReceiver); - if (mCommitted) { return true; } @@ -1519,7 +1504,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mCallback.onSessionSealedBlocking(this); } - private void handleCommit() { + private void handleInstall() { if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) { DevicePolicyEventLogger .createEvent(DevicePolicyEnums.INSTALL_PACKAGE) @@ -1548,7 +1533,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { synchronized (mLock) { - commitNonStagedLocked(childSessions); + installNonStagedLocked(childSessions); } } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); @@ -1559,25 +1544,25 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } @GuardedBy("mLock") - private void commitNonStagedLocked(List<PackageInstallerSession> childSessions) + private void installNonStagedLocked(List<PackageInstallerSession> childSessions) throws PackageManagerException { - final PackageManagerService.ActiveInstallSession committingSession = + final PackageManagerService.ActiveInstallSession installingSession = makeSessionActiveLocked(); - if (committingSession == null) { + if (installingSession == null) { return; } if (isMultiPackage()) { - List<PackageManagerService.ActiveInstallSession> activeChildSessions = + List<PackageManagerService.ActiveInstallSession> installingChildSessions = new ArrayList<>(childSessions.size()); boolean success = true; PackageManagerException failure = null; for (int i = 0; i < childSessions.size(); ++i) { final PackageInstallerSession session = childSessions.get(i); try { - final PackageManagerService.ActiveInstallSession activeSession = + final PackageManagerService.ActiveInstallSession installingChildSession = session.makeSessionActiveLocked(); - if (activeSession != null) { - activeChildSessions.add(activeSession); + if (installingChildSession != null) { + installingChildSessions.add(installingChildSession); } } catch (PackageManagerException e) { failure = e; @@ -1591,9 +1576,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { failure.error, failure.getLocalizedMessage(), null); return; } - mPm.installStage(activeChildSessions); + mPm.installStage(installingChildSessions); } else { - mPm.installStage(committingSession); + mPm.installStage(installingSession); } } @@ -1767,8 +1752,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private void validateApexInstallLocked() throws PackageManagerException { - final File[] addedFiles = getAddedApksLocked(); - if (ArrayUtils.isEmpty(addedFiles)) { + final List<File> addedFiles = getAddedApksLocked(); + if (addedFiles.isEmpty()) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged"); } @@ -1777,7 +1762,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Too many files for apex install"); } - File addedFile = addedFiles[0]; // there is only one file + File addedFile = addedFiles.get(0); // there is only one file // Ensure file name has proper suffix final String sourceName = addedFile.getName(); @@ -1844,9 +1829,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { && params.mode == SessionParams.MODE_INHERIT_EXISTING && VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath()); - final File[] removedFiles = getRemovedFilesLocked(); + final List<File> removedFiles = getRemovedFilesLocked(); final List<String> removeSplitList = new ArrayList<>(); - if (!ArrayUtils.isEmpty(removedFiles)) { + if (!removedFiles.isEmpty()) { for (File removedFile : removedFiles) { final String fileName = removedFile.getName(); final String splitName = fileName.substring( @@ -1855,8 +1840,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - final File[] addedFiles = getAddedApksLocked(); - if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) { + final List<File> addedFiles = getAddedApksLocked(); + if (addedFiles.isEmpty() && removeSplitList.size() == 0) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged"); } @@ -2306,7 +2291,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // Mark and kick off another install pass synchronized (mLock) { mPermissionsManuallyAccepted = true; - mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); + mHandler.obtainMessage(MSG_INSTALL).sendToTarget(); } } else { destroyInternal(); @@ -2475,16 +2460,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return true; } - final List<InstallationFile> addedFiles = mFiles.stream().filter( - file -> sAddedFilter.accept(new File(file.name))).map( - file -> new InstallationFile( - file.name, file.lengthBytes, file.metadata)).collect( - Collectors.toList()); - final List<String> removedFiles = mFiles.stream().filter( - file -> sRemovedFilter.accept(new File(file.name))).map( - file -> file.name.substring( - 0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect( - Collectors.toList()); + final List<InstallationFile> addedFiles = new ArrayList<>(mFiles.size()); + for (FileInfo file : mFiles) { + if (sAddedFilter.accept(new File(this.stageDir, file.name))) { + addedFiles.add(new InstallationFile( + file.name, file.lengthBytes, file.metadata)); + } + } + final List<String> removedFiles = new ArrayList<>(mFiles.size()); + for (FileInfo file : mFiles) { + if (sRemovedFilter.accept(new File(this.stageDir, file.name))) { + String name = file.name.substring( + 0, file.name.length() - REMOVE_MARKER_EXTENSION.length()); + removedFiles.add(name); + } + } if (mIncrementalFileStorages != null) { for (InstallationFile file : addedFiles) { @@ -2536,9 +2526,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mDataLoaderFinished = true; if (hasParentSessionId()) { mSessionProvider.getSession( - mParentSessionId).dispatchStreamAndValidate(); + mParentSessionId).dispatchStreamValidateAndCommit(); } else { - dispatchStreamAndValidate(); + dispatchStreamValidateAndCommit(); } dataLoader.destroy(); break; @@ -3127,8 +3117,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } if (grantedRuntimePermissions.size() > 0) { - params.grantedRuntimePermissions = grantedRuntimePermissions - .stream().toArray(String[]::new); + params.grantedRuntimePermissions = (String[]) grantedRuntimePermissions.toArray(); } if (whitelistedRestrictedPermissions.size() > 0) { @@ -3137,14 +3126,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { int[] childSessionIdsArray; if (childSessionIds.size() > 0) { - childSessionIdsArray = childSessionIds.stream().mapToInt(i -> i).toArray(); + childSessionIdsArray = new int[childSessionIds.size()]; + for (int i = 0, size = childSessionIds.size(); i < size; ++i) { + childSessionIdsArray[i] = childSessionIds.get(i); + } } else { childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY; } FileInfo[] fileInfosArray = null; if (!files.isEmpty()) { - fileInfosArray = files.stream().toArray(FileInfo[]::new); + fileInfosArray = (FileInfo[]) files.toArray(); } InstallSource installSource = InstallSource.create(installInitiatingPackageName, diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 57a82c6512e8..93a0506f673d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -19707,9 +19707,7 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null) { return null; } - if (getPackageInfo(packageName, MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE - | MATCH_DIRECT_BOOT_UNAWARE | MATCH_DISABLED_COMPONENTS, - UserHandle.getCallingUserId()) == null) { + if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) { return null; } return packageName; diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index ae28019a5dea..89354537526c 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -344,12 +344,12 @@ public class StagingManager { } /** + * Perform snapshot and restore as required both for APEXes themselves and for apks in APEX. * Apks inside apex are not installed using apk-install flow. They are scanned from the system * directory directly by PackageManager, as such, RollbackManager need to handle their data * separately here. */ - private void snapshotAndRestoreApkInApexUserData(PackageInstallerSession session) { - // We want to process apks inside apex. So current session needs to contain apex. + private void snapshotAndRestoreForApexSession(PackageInstallerSession session) { if (!sessionContainsApex(session)) { return; } @@ -382,19 +382,37 @@ public class StagingManager { apexSessions.add(session); } - // For each apex, process the apks inside it + final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class); + final int[] allUsers = um.getUserIds(); + IRollbackManager rm = IRollbackManager.Stub.asInterface( + ServiceManager.getService(Context.ROLLBACK_SERVICE)); + for (PackageInstallerSession apexSession : apexSessions) { - List<String> apksInApex = mApexManager.getApksInApex(apexSession.getPackageName()); + String packageName = apexSession.getPackageName(); + // Perform any snapshots or restores for the APEX itself + snapshotAndRestoreApexUserData(packageName, allUsers, rm); + + // Process the apks inside the APEX + List<String> apksInApex = mApexManager.getApksInApex(packageName); for (String apk: apksInApex) { - snapshotAndRestoreApkInApexUserData(apk); + snapshotAndRestoreApkInApexUserData(apk, allUsers, rm); } } } - private void snapshotAndRestoreApkInApexUserData(String packageName) { - IRollbackManager rm = IRollbackManager.Stub.asInterface( - ServiceManager.getService(Context.ROLLBACK_SERVICE)); + private void snapshotAndRestoreApexUserData( + String packageName, int[] allUsers, IRollbackManager rm) { + try { + // appId, ceDataInode, and seInfo are not needed for APEXes + rm.snapshotAndRestoreUserData(packageName, allUsers, 0, 0, + null, 0 /*token*/); + } catch (RemoteException re) { + Slog.e(TAG, "Error snapshotting/restoring user data: " + re); + } + } + private void snapshotAndRestoreApkInApexUserData( + String packageName, int[] allUsers, IRollbackManager rm) { PackageManagerInternal mPmi = LocalServices.getService(PackageManagerInternal.class); AndroidPackage pkg = mPmi.getPackage(packageName); if (pkg == null) { @@ -403,13 +421,11 @@ public class StagingManager { return; } final String seInfo = pkg.getSeInfo(); - final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class); - final int[] allUsers = um.getUserIds(); int appId = -1; long ceDataInode = -1; final PackageSetting ps = (PackageSetting) mPmi.getPackageSetting(packageName); - if (ps != null && rm != null) { + if (ps != null) { appId = ps.appId; ceDataInode = ps.getCeDataInode(UserHandle.USER_SYSTEM); // NOTE: We ignore the user specified in the InstallParam because we know this is @@ -498,7 +514,7 @@ public class StagingManager { abortCheckpoint(); return; } - snapshotAndRestoreApkInApexUserData(session); + snapshotAndRestoreForApexSession(session); Slog.i(TAG, "APEX packages in session " + session.sessionId + " were successfully activated. Proceeding with APK packages, if any"); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 7c76656e1e6f..03cb283ce447 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -54,6 +54,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; @@ -2088,11 +2089,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_VOICE_INTERACTION: case TYPE_ACCESSIBILITY_OVERLAY: case TYPE_QS_DIALOG: + case TYPE_NAVIGATION_BAR_PANEL: // The window manager will check these. return ADD_OKAY; } - return mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) - == PERMISSION_GRANTED ? ADD_OKAY : ADD_PERMISSION_DENIED; + + return (mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW) + == PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED; } // Things get a little more interesting for alert windows... diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index f3a60185bfb6..81ec46634e8a 100644 --- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java +++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java @@ -18,12 +18,14 @@ package com.android.server.policy; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; +import static android.Manifest.permission.WRITE_MEDIA_STORAGE; import static android.app.AppOpsManager.OP_LEGACY_STORAGE; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT; import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static java.lang.Integer.min; @@ -114,6 +116,7 @@ public abstract class SoftRestrictedPermissionPolicy { boolean shouldApplyRestriction; final int targetSDK; final boolean hasRequestedLegacyExternalStorage; + final boolean hasWriteMediaStorageGrantedForUid; if (appInfo != null) { PackageManager pm = context.getPackageManager(); @@ -123,11 +126,14 @@ public abstract class SoftRestrictedPermissionPolicy { targetSDK = getMinimumTargetSDK(context, appInfo, user); hasRequestedLegacyExternalStorage = hasUidRequestedLegacyExternalStorage( appInfo.uid, context); + hasWriteMediaStorageGrantedForUid = hasWriteMediaStorageGrantedForUid( + appInfo.uid, context); } else { isWhiteListed = false; shouldApplyRestriction = false; targetSDK = 0; hasRequestedLegacyExternalStorage = false; + hasWriteMediaStorageGrantedForUid = false; } // We have a check in PermissionPolicyService.PermissionToOpSynchroniser.setUidMode @@ -145,8 +151,9 @@ public abstract class SoftRestrictedPermissionPolicy { } @Override public boolean mayAllowExtraAppOp() { - return !shouldApplyRestriction && hasRequestedLegacyExternalStorage - && targetSDK <= Build.VERSION_CODES.Q; + return !shouldApplyRestriction && targetSDK <= Build.VERSION_CODES.Q + && (hasRequestedLegacyExternalStorage + || hasWriteMediaStorageGrantedForUid); } @Override public boolean mayDenyExtraAppOpIfGranted() { @@ -201,6 +208,22 @@ public abstract class SoftRestrictedPermissionPolicy { return false; } + private static boolean hasWriteMediaStorageGrantedForUid(int uid, @NonNull Context context) { + PackageManager packageManager = context.getPackageManager(); + String[] packageNames = packageManager.getPackagesForUid(uid); + if (packageNames == null) { + return false; + } + + for (String packageName : packageNames) { + if (packageManager.checkPermission(WRITE_MEDIA_STORAGE, packageName) + == PERMISSION_GRANTED) { + return true; + } + } + return false; + } + /** * @return If the permission can be granted */ diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java index e6e6e23bf714..e77839c4e5b5 100644 --- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java @@ -26,6 +26,7 @@ import android.util.SparseLongArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.pm.ApexManager; import com.android.server.pm.Installer; import com.android.server.pm.Installer.InstallerException; @@ -42,9 +43,17 @@ public class AppDataRollbackHelper { private static final String TAG = "RollbackManager"; private final Installer mInstaller; + private final ApexManager mApexManager; public AppDataRollbackHelper(Installer installer) { mInstaller = installer; + mApexManager = ApexManager.getInstance(); + } + + @VisibleForTesting + AppDataRollbackHelper(Installer installer, ApexManager apexManager) { + mInstaller = installer; + mApexManager = apexManager; } /** @@ -55,7 +64,7 @@ public class AppDataRollbackHelper { @GuardedBy("rollback.mLock") // TODO(b/136241838): Move into Rollback and synchronize there. public void snapshotAppData( - int snapshotId, PackageRollbackInfo packageRollbackInfo, int[] userIds) { + int rollbackId, PackageRollbackInfo packageRollbackInfo, int[] userIds) { for (int user : userIds) { final int storageFlags; if (isUserCredentialLocked(user)) { @@ -68,16 +77,7 @@ public class AppDataRollbackHelper { storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE; } - try { - long ceSnapshotInode = mInstaller.snapshotAppData( - packageRollbackInfo.getPackageName(), user, snapshotId, storageFlags); - if ((storageFlags & Installer.FLAG_STORAGE_CE) != 0) { - packageRollbackInfo.putCeSnapshotInode(user, ceSnapshotInode); - } - } catch (InstallerException ie) { - Slog.e(TAG, "Unable to create app data snapshot for: " - + packageRollbackInfo.getPackageName() + ", userId: " + user, ie); - } + doSnapshot(packageRollbackInfo, user, rollbackId, storageFlags); } } @@ -119,26 +119,82 @@ public class AppDataRollbackHelper { } } - try { + doRestoreOrWipe(packageRollbackInfo, userId, rollbackId, appId, seInfo, storageFlags); + + return changedRollback; + } + + private boolean doSnapshot( + PackageRollbackInfo packageRollbackInfo, int userId, int rollbackId, int flags) { + if (packageRollbackInfo.isApex()) { + // For APEX, only snapshot CE here + if ((flags & Installer.FLAG_STORAGE_CE) != 0) { + long ceSnapshotInode = mApexManager.snapshotCeData( + userId, rollbackId, packageRollbackInfo.getPackageName()); + if (ceSnapshotInode > 0) { + packageRollbackInfo.putCeSnapshotInode(userId, ceSnapshotInode); + } else { + return false; + } + } + } else { + // APK + try { + long ceSnapshotInode = mInstaller.snapshotAppData( + packageRollbackInfo.getPackageName(), userId, rollbackId, flags); + if ((flags & Installer.FLAG_STORAGE_CE) != 0) { + packageRollbackInfo.putCeSnapshotInode(userId, ceSnapshotInode); + } + } catch (InstallerException ie) { + Slog.e(TAG, "Unable to create app data snapshot for: " + + packageRollbackInfo.getPackageName() + ", userId: " + userId, ie); + return false; + } + } + return true; + } + + private boolean doRestoreOrWipe(PackageRollbackInfo packageRollbackInfo, int userId, + int rollbackId, int appId, String seInfo, int flags) { + if (packageRollbackInfo.isApex()) { switch (packageRollbackInfo.getRollbackDataPolicy()) { case PackageManager.RollbackDataPolicy.WIPE: - mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(), - userId, storageFlags, 0); + // TODO: Implement WIPE for apex CE data break; case PackageManager.RollbackDataPolicy.RESTORE: - mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, - seInfo, userId, rollbackId, storageFlags); + // For APEX, only restore of CE may be done here. + if ((flags & Installer.FLAG_STORAGE_CE) != 0) { + mApexManager.restoreCeData( + userId, rollbackId, packageRollbackInfo.getPackageName()); + } break; default: break; } - } catch (InstallerException ie) { - Slog.e(TAG, "Unable to restore/wipe app data: " - + packageRollbackInfo.getPackageName() + " policy=" - + packageRollbackInfo.getRollbackDataPolicy(), ie); - } + } else { + // APK + try { + switch (packageRollbackInfo.getRollbackDataPolicy()) { + case PackageManager.RollbackDataPolicy.WIPE: + mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(), + userId, flags, 0); + break; + case PackageManager.RollbackDataPolicy.RESTORE: - return changedRollback; + mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), + appId, seInfo, userId, rollbackId, flags); + break; + default: + break; + } + } catch (InstallerException ie) { + Slog.e(TAG, "Unable to restore/wipe app data: " + + packageRollbackInfo.getPackageName() + " policy=" + + packageRollbackInfo.getRollbackDataPolicy(), ie); + return false; + } + } + return true; } /** @@ -204,40 +260,15 @@ public class AppDataRollbackHelper { if (hasPendingBackup) { int idx = pendingBackupUsers.indexOf(userId); - try { - long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(), - userId, rollback.info.getRollbackId(), - Installer.FLAG_STORAGE_CE); - info.putCeSnapshotInode(userId, ceSnapshotInode); + if (doSnapshot( + info, userId, rollback.info.getRollbackId(), Installer.FLAG_STORAGE_CE)) { pendingBackupUsers.remove(idx); - } catch (InstallerException ie) { - Slog.e(TAG, - "Unable to create app data snapshot for: " - + info.getPackageName() + ", userId: " + userId, ie); } } - if (hasPendingRestore) { - try { - switch (info.getRollbackDataPolicy()) { - case PackageManager.RollbackDataPolicy.WIPE: - mInstaller.clearAppData(null, info.getPackageName(), userId, - Installer.FLAG_STORAGE_CE, 0); - break; - case PackageManager.RollbackDataPolicy.RESTORE: - mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId, - ri.seInfo, userId, rollback.info.getRollbackId(), - Installer.FLAG_STORAGE_CE); - break; - default: - break; - } - info.removeRestoreInfo(ri); - } catch (InstallerException ie) { - Slog.e(TAG, "Unable to restore/wipe app data for: " - + info.getPackageName() + " policy=" - + info.getRollbackDataPolicy(), ie); - } + if (hasPendingRestore && doRestoreOrWipe(info, userId, rollback.info.getRollbackId(), + ri.appId, ri.seInfo, Installer.FLAG_STORAGE_CE)) { + info.removeRestoreInfo(ri); } } return foundBackupOrRestore; diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 951f1a4663f1..8893213d4a71 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -16,19 +16,13 @@ package com.android.server.rollback; -import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH; -import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING; -import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK; -import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH; import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; @@ -75,8 +69,6 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve private static final String TAG = "RollbackPackageHealthObserver"; private static final String NAME = "rollback-observer"; - private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT"; - private final Context mContext; private final Handler mHandler; private final File mLastStagedRollbackIdsFile; @@ -162,67 +154,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve Iterator<Integer> rollbackIterator = rollbackIds.iterator(); while (rollbackIterator.hasNext()) { int rollbackId = rollbackIterator.next(); - logRollbackStatusOnBoot(rollbackId, rollbackManager.getRecentlyCommittedRollbacks()); - } - } - - private void logRollbackStatusOnBoot(int rollbackId, - List<RollbackInfo> recentlyCommittedRollbacks) { - PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller(); - - RollbackInfo rollback = null; - for (RollbackInfo info : recentlyCommittedRollbacks) { - if (rollbackId == info.getRollbackId()) { - rollback = info; - break; - } - } - - if (rollback == null) { - Slog.e(TAG, "rollback info not found for last staged rollback: " + rollbackId); - return; - } - - // Identify the logging parent for this rollback. When all configurations are correct, each - // package in the rollback refers to the same logging parent, except for the logging parent - // itself. If a logging parent is missing for a package, we use the package itself for - // logging. This might result in over-logging, but we prefer this over no logging. - final Set<String> loggingPackageNames = new ArraySet<>(); - for (PackageRollbackInfo packageRollback : rollback.getPackages()) { - final String loggingParentName = getLoggingParentName(packageRollback.getPackageName()); - if (loggingParentName != null) { - loggingPackageNames.add(loggingParentName); - } else { - loggingPackageNames.add(packageRollback.getPackageName()); - } - } - - // Use the version of the logging parent that was installed before - // we rolled back for logging purposes. - final List<VersionedPackage> oldLoggingPackages = new ArrayList<>(); - for (PackageRollbackInfo packageRollback : rollback.getPackages()) { - if (loggingPackageNames.contains(packageRollback.getPackageName())) { - oldLoggingPackages.add(packageRollback.getVersionRolledBackFrom()); - } - } - - int sessionId = rollback.getCommittedSessionId(); - PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId); - if (sessionInfo == null) { - Slog.e(TAG, "On boot completed, could not load session id " + sessionId); - return; - } - - for (VersionedPackage oldLoggingPackage : oldLoggingPackages) { - if (sessionInfo.isStagedSessionApplied()) { - logEvent(oldLoggingPackage, - StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, - WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); - } else if (sessionInfo.isStagedSessionFailed()) { - logEvent(oldLoggingPackage, - StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, - WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); - } + WatchdogRollbackLogger.logRollbackStatusOnBoot( + mContext, rollbackId, rollbackManager.getRecentlyCommittedRollbacks()); } } @@ -255,22 +188,6 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve return null; } - @Nullable - private String getLoggingParentName(String packageName) { - PackageManager packageManager = mContext.getPackageManager(); - try { - ApplicationInfo ai = packageManager.getApplicationInfo(packageName, - PackageManager.GET_META_DATA); - if (ai.metaData == null) { - return null; - } - return ai.metaData.getString(LOGGING_PARENT_KEY); - } catch (Exception e) { - Slog.w(TAG, "Unable to discover logging parent package: " + packageName, e); - return null; - } - } - private BroadcastReceiver listenForStagedSessionReady(RollbackManager rollbackManager, int rollbackId, @Nullable VersionedPackage logPackage) { BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() { @@ -306,14 +223,14 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve // successful or not. If logPackage is null, then there is nothing to log. saveStagedRollbackId(rollbackId); } - logEvent(logPackage, + WatchdogRollbackLogger.logEvent(logPackage, StatsLog .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED, WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); } else if (sessionInfo.isStagedSessionFailed() && markStagedSessionHandled(rollbackId)) { - logEvent(logPackage, + WatchdogRollbackLogger.logEvent(logPackage, StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); @@ -383,47 +300,6 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } } - private static String rollbackTypeToString(int type) { - switch (type) { - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE: - return "ROLLBACK_INITIATE"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS: - return "ROLLBACK_SUCCESS"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE: - return "ROLLBACK_FAILURE"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED: - return "ROLLBACK_BOOT_TRIGGERED"; - default: - return "UNKNOWN"; - } - } - - private static String rollbackReasonToString(int reason) { - switch (reason) { - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH: - return "REASON_NATIVE_CRASH"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK: - return "REASON_EXPLICIT_HEALTH_CHECK"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH: - return "REASON_APP_CRASH"; - case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING: - return "REASON_APP_NOT_RESPONDING"; - default: - return "UNKNOWN"; - } - } - - private static void logEvent(@Nullable VersionedPackage logPackage, int type, - int rollbackReason, @NonNull String failingPackageName) { - Slog.i(TAG, "Watchdog event occurred with type: " + rollbackTypeToString(type) - + " logPackage: " + logPackage - + " rollbackReason: " + rollbackReasonToString(rollbackReason) - + " failedPackageName: " + failingPackageName); - if (logPackage != null) { - StatsLog.logWatchdogRollbackOccurred(type, logPackage.getPackageName(), - logPackage.getLongVersionCode(), rollbackReason, failingPackageName); - } - } /** * Returns true if the package name is the name of a module. @@ -446,7 +322,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve private void rollbackPackage(RollbackInfo rollback, VersionedPackage failedPackage, @FailureReasons int rollbackReason) { final RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class); - int reasonToLog = mapFailureReasonToMetric(rollbackReason); + int reasonToLog = WatchdogRollbackLogger.mapFailureReasonToMetric(rollbackReason); final String failedPackageToLog; if (rollbackReason == PackageWatchdog.FAILURE_REASON_NATIVE_CRASH) { failedPackageToLog = SystemProperties.get( @@ -456,20 +332,11 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } VersionedPackage logPackageTemp = null; if (isModule(failedPackage.getPackageName())) { - String logPackageName = getLoggingParentName(failedPackage.getPackageName()); - if (logPackageName == null) { - logPackageName = failedPackage.getPackageName(); - } - try { - logPackageTemp = new VersionedPackage(logPackageName, mContext.getPackageManager() - .getPackageInfo(logPackageName, 0 /* flags */).getLongVersionCode()); - } catch (PackageManager.NameNotFoundException e) { - logPackageTemp = null; - } + logPackageTemp = WatchdogRollbackLogger.getLogPackage(mContext, failedPackage); } final VersionedPackage logPackage = logPackageTemp; - logEvent(logPackage, + WatchdogRollbackLogger.logEvent(logPackage, StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE, reasonToLog, failedPackageToLog); final LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> { @@ -487,7 +354,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve handleStagedSessionChange(rollbackManager, rollbackId, listener, logPackage); } else { - logEvent(logPackage, + WatchdogRollbackLogger.logEvent(logPackage, StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, reasonToLog, failedPackageToLog); } @@ -495,7 +362,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve if (rollback.isStaged()) { markStagedSessionHandled(rollback.getRollbackId()); } - logEvent(logPackage, + WatchdogRollbackLogger.logEvent(logPackage, StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, reasonToLog, failedPackageToLog); } @@ -527,21 +394,4 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH); } } - - - private int mapFailureReasonToMetric(@FailureReasons int failureReason) { - switch (failureReason) { - case PackageWatchdog.FAILURE_REASON_NATIVE_CRASH: - return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH; - case PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK: - return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK; - case PackageWatchdog.FAILURE_REASON_APP_CRASH: - return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH; - case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING: - return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING; - default: - return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN; - } - } - } diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java new file mode 100644 index 000000000000..3c923e7d2e31 --- /dev/null +++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java @@ -0,0 +1,216 @@ +/* + * 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.rollback; + +import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH; +import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING; +import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK; +import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH; +import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.content.pm.VersionedPackage; +import android.content.rollback.PackageRollbackInfo; +import android.content.rollback.RollbackInfo; +import android.util.ArraySet; +import android.util.Slog; +import android.util.StatsLog; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.PackageWatchdog; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * This class handles the logic for logging Watchdog-triggered rollback events. + */ +public final class WatchdogRollbackLogger { + private static final String TAG = "WatchdogRollbackLogger"; + + private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT"; + + private WatchdogRollbackLogger() { + } + + @Nullable + private static String getLoggingParentName(Context context, @NonNull String packageName) { + PackageManager packageManager = context.getPackageManager(); + try { + ApplicationInfo ai = packageManager.getApplicationInfo(packageName, + PackageManager.GET_META_DATA); + if (ai.metaData == null) { + return null; + } + return ai.metaData.getString(LOGGING_PARENT_KEY); + } catch (Exception e) { + Slog.w(TAG, "Unable to discover logging parent package: " + packageName, e); + return null; + } + } + + @VisibleForTesting + static VersionedPackage getLogPackage(Context context, + @NonNull VersionedPackage failingPackage) { + String logPackageName; + VersionedPackage loggingParent; + logPackageName = getLoggingParentName(context, failingPackage.getPackageName()); + if (logPackageName == null) { + return failingPackage; + } + try { + loggingParent = new VersionedPackage(logPackageName, context.getPackageManager() + .getPackageInfo(logPackageName, 0 /* flags */).getLongVersionCode()); + } catch (PackageManager.NameNotFoundException e) { + return failingPackage; + } + return loggingParent; + } + + static void logRollbackStatusOnBoot(Context context, int rollbackId, + List<RollbackInfo> recentlyCommittedRollbacks) { + PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); + + RollbackInfo rollback = null; + for (RollbackInfo info : recentlyCommittedRollbacks) { + if (rollbackId == info.getRollbackId()) { + rollback = info; + break; + } + } + + if (rollback == null) { + Slog.e(TAG, "rollback info not found for last staged rollback: " + rollbackId); + return; + } + + // Identify the logging parent for this rollback. When all configurations are correct, each + // package in the rollback refers to the same logging parent, except for the logging parent + // itself. If a logging parent is missing for a package, we use the package itself for + // logging. This might result in over-logging, but we prefer this over no logging. + final Set<String> loggingPackageNames = new ArraySet<>(); + for (PackageRollbackInfo packageRollback : rollback.getPackages()) { + final String loggingParentName = getLoggingParentName(context, + packageRollback.getPackageName()); + if (loggingParentName != null) { + loggingPackageNames.add(loggingParentName); + } else { + loggingPackageNames.add(packageRollback.getPackageName()); + } + } + + // Use the version of the logging parent that was installed before + // we rolled back for logging purposes. + final List<VersionedPackage> oldLoggingPackages = new ArrayList<>(); + for (PackageRollbackInfo packageRollback : rollback.getPackages()) { + if (loggingPackageNames.contains(packageRollback.getPackageName())) { + oldLoggingPackages.add(packageRollback.getVersionRolledBackFrom()); + } + } + + int sessionId = rollback.getCommittedSessionId(); + PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId); + if (sessionInfo == null) { + Slog.e(TAG, "On boot completed, could not load session id " + sessionId); + return; + } + + for (VersionedPackage oldLoggingPackage : oldLoggingPackages) { + if (sessionInfo.isStagedSessionApplied()) { + logEvent(oldLoggingPackage, + StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS, + WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); + } else if (sessionInfo.isStagedSessionFailed()) { + logEvent(oldLoggingPackage, + StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE, + WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, ""); + } + } + } + + /** + * Log a Watchdog rollback event to statsd. + * + * @param logPackage the package to associate the rollback with. + * @param type the state of the rollback. + * @param rollbackReason the reason Watchdog triggered a rollback, if known. + * @param failingPackageName the failing package or process which triggered the rollback. + */ + public static void logEvent(@Nullable VersionedPackage logPackage, int type, + int rollbackReason, @NonNull String failingPackageName) { + Slog.i(TAG, "Watchdog event occurred with type: " + rollbackTypeToString(type) + + " logPackage: " + logPackage + + " rollbackReason: " + rollbackReasonToString(rollbackReason) + + " failedPackageName: " + failingPackageName); + if (logPackage != null) { + StatsLog.logWatchdogRollbackOccurred(type, logPackage.getPackageName(), + logPackage.getVersionCode(), rollbackReason, failingPackageName); + } + } + + @VisibleForTesting + static int mapFailureReasonToMetric(@PackageWatchdog.FailureReasons int failureReason) { + switch (failureReason) { + case PackageWatchdog.FAILURE_REASON_NATIVE_CRASH: + return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH; + case PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK: + return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK; + case PackageWatchdog.FAILURE_REASON_APP_CRASH: + return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH; + case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING: + return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING; + default: + return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN; + } + } + + private static String rollbackTypeToString(int type) { + switch (type) { + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE: + return "ROLLBACK_INITIATE"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS: + return "ROLLBACK_SUCCESS"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE: + return "ROLLBACK_FAILURE"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED: + return "ROLLBACK_BOOT_TRIGGERED"; + default: + return "UNKNOWN"; + } + } + + private static String rollbackReasonToString(int reason) { + switch (reason) { + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH: + return "REASON_NATIVE_CRASH"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK: + return "REASON_EXPLICIT_HEALTH_CHECK"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH: + return "REASON_APP_CRASH"; + case StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING: + return "REASON_APP_NOT_RESPONDING"; + default: + return "UNKNOWN"; + } + } +} 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 f3197cff04a7..4f8a86d3f3c6 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -54,6 +54,7 @@ import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; +import android.hardware.health.V2_0.IHealth; import android.net.ConnectivityManager; import android.net.INetworkStatsService; import android.net.Network; @@ -95,7 +96,6 @@ import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.StatsEvent; -import android.util.StatsLog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -119,6 +119,8 @@ import com.android.internal.os.LooperStats; import com.android.internal.os.PowerProfile; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.StoragedUidIoStatsReader; +import com.android.internal.util.FrameworkStatsLog; +import com.android.server.BatteryService; import com.android.server.BinderCallsStatsService; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -239,6 +241,8 @@ public class StatsPullAtomService extends SystemService { private File mBaseDir; + private BatteryService.HealthServiceWrapper mHealthService; + @Nullable private KernelCpuThreadReaderDiff mKernelCpuThreadReader; @@ -263,116 +267,122 @@ public class StatsPullAtomService extends SystemService { @Override public int onPullAtom(int atomTag, List<StatsEvent> data) { switch(atomTag) { - case StatsLog.WIFI_BYTES_TRANSFER: + case FrameworkStatsLog.WIFI_BYTES_TRANSFER: return pullWifiBytesTransfer(atomTag, data); - case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: + case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: return pullWifiBytesTransferBackground(atomTag, data); - case StatsLog.MOBILE_BYTES_TRANSFER: + case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: return pullMobileBytesTransfer(atomTag, data); - case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: + case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: return pullMobileBytesTransferBackground(atomTag, data); - case StatsLog.BLUETOOTH_BYTES_TRANSFER: + case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: return pullBluetoothBytesTransfer(atomTag, data); - case StatsLog.KERNEL_WAKELOCK: + case FrameworkStatsLog.KERNEL_WAKELOCK: return pullKernelWakelock(atomTag, data); - case StatsLog.CPU_TIME_PER_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_FREQ: return pullCpuTimePerFreq(atomTag, data); - case StatsLog.CPU_TIME_PER_UID: + case FrameworkStatsLog.CPU_TIME_PER_UID: return pullCpuTimePerUid(atomTag, data); - case StatsLog.CPU_TIME_PER_UID_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_UID_FREQ: return pullCpuTimeperUidFreq(atomTag, data); - case StatsLog.CPU_ACTIVE_TIME: + case FrameworkStatsLog.CPU_ACTIVE_TIME: return pullCpuActiveTime(atomTag, data); - case StatsLog.CPU_CLUSTER_TIME: + case FrameworkStatsLog.CPU_CLUSTER_TIME: return pullCpuClusterTime(atomTag, data); - case StatsLog.WIFI_ACTIVITY_INFO: + case FrameworkStatsLog.WIFI_ACTIVITY_INFO: return pullWifiActivityInfo(atomTag, data); - case StatsLog.MODEM_ACTIVITY_INFO: + case FrameworkStatsLog.MODEM_ACTIVITY_INFO: return pullModemActivityInfo(atomTag, data); - case StatsLog.BLUETOOTH_ACTIVITY_INFO: + case FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO: return pullBluetoothActivityInfo(atomTag, data); - case StatsLog.SYSTEM_ELAPSED_REALTIME: + case FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME: return pullSystemElapsedRealtime(atomTag, data); - case StatsLog.SYSTEM_UPTIME: + case FrameworkStatsLog.SYSTEM_UPTIME: return pullSystemUptime(atomTag, data); - case StatsLog.PROCESS_MEMORY_STATE: + case FrameworkStatsLog.PROCESS_MEMORY_STATE: return pullProcessMemoryState(atomTag, data); - case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: + case FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: return pullProcessMemoryHighWaterMark(atomTag, data); - case StatsLog.PROCESS_MEMORY_SNAPSHOT: + case FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT: return pullProcessMemorySnapshot(atomTag, data); - case StatsLog.SYSTEM_ION_HEAP_SIZE: + case FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE: return pullSystemIonHeapSize(atomTag, data); - case StatsLog.ION_HEAP_SIZE: + case FrameworkStatsLog.ION_HEAP_SIZE: return pullIonHeapSize(atomTag, data); - case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: + case FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: return pullProcessSystemIonHeapSize(atomTag, data); - case StatsLog.TEMPERATURE: + case FrameworkStatsLog.TEMPERATURE: return pullTemperature(atomTag, data); - case StatsLog.COOLING_DEVICE: + case FrameworkStatsLog.COOLING_DEVICE: return pullCooldownDevice(atomTag, data); - case StatsLog.BINDER_CALLS: + case FrameworkStatsLog.BINDER_CALLS: return pullBinderCallsStats(atomTag, data); - case StatsLog.BINDER_CALLS_EXCEPTIONS: + case FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS: return pullBinderCallsStatsExceptions(atomTag, data); - case StatsLog.LOOPER_STATS: + case FrameworkStatsLog.LOOPER_STATS: return pullLooperStats(atomTag, data); - case StatsLog.DISK_STATS: + case FrameworkStatsLog.DISK_STATS: return pullDiskStats(atomTag, data); - case StatsLog.DIRECTORY_USAGE: + case FrameworkStatsLog.DIRECTORY_USAGE: return pullDirectoryUsage(atomTag, data); - case StatsLog.APP_SIZE: + case FrameworkStatsLog.APP_SIZE: return pullAppSize(atomTag, data); - case StatsLog.CATEGORY_SIZE: + case FrameworkStatsLog.CATEGORY_SIZE: return pullCategorySize(atomTag, data); - case StatsLog.NUM_FINGERPRINTS_ENROLLED: + case FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED: return pullNumBiometricsEnrolled( BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data); - case StatsLog.NUM_FACES_ENROLLED: + case FrameworkStatsLog.NUM_FACES_ENROLLED: return pullNumBiometricsEnrolled( BiometricsProtoEnums.MODALITY_FACE, atomTag, data); - case StatsLog.PROC_STATS: + case FrameworkStatsLog.PROC_STATS: return pullProcStats(ProcessStats.REPORT_ALL, atomTag, data); - case StatsLog.PROC_STATS_PKG_PROC: + case FrameworkStatsLog.PROC_STATS_PKG_PROC: return pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data); - case StatsLog.DISK_IO: + case FrameworkStatsLog.DISK_IO: return pullDiskIO(atomTag, data); - case StatsLog.POWER_PROFILE: + case FrameworkStatsLog.POWER_PROFILE: return pullPowerProfile(atomTag, data); - case StatsLog.PROCESS_CPU_TIME: + case FrameworkStatsLog.PROCESS_CPU_TIME: return pullProcessCpuTime(atomTag, data); - case StatsLog.CPU_TIME_PER_THREAD_FREQ: + case FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ: return pullCpuTimePerThreadFreq(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_USE: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE: return pullDeviceCalculatedPowerUse(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: return pullDeviceCalculatedPowerBlameUid(atomTag, data); - case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: + case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: return pullDeviceCalculatedPowerBlameOther(atomTag, data); - case StatsLog.DEBUG_ELAPSED_CLOCK: + case FrameworkStatsLog.DEBUG_ELAPSED_CLOCK: return pullDebugElapsedClock(atomTag, data); - case StatsLog.DEBUG_FAILING_ELAPSED_CLOCK: + case FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK: return pullDebugFailingElapsedClock(atomTag, data); - case StatsLog.BUILD_INFORMATION: + case FrameworkStatsLog.BUILD_INFORMATION: return pullBuildInformation(atomTag, data); - case StatsLog.ROLE_HOLDER: + case FrameworkStatsLog.ROLE_HOLDER: return pullRoleHolder(atomTag, data); - case StatsLog.DANGEROUS_PERMISSION_STATE: + case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE: return pullDangerousPermissionState(atomTag, data); - case StatsLog.TIME_ZONE_DATA_INFO: + case FrameworkStatsLog.TIME_ZONE_DATA_INFO: return pullTimeZoneDataInfo(atomTag, data); - case StatsLog.EXTERNAL_STORAGE_INFO: + case FrameworkStatsLog.EXTERNAL_STORAGE_INFO: return pullExternalStorageInfo(atomTag, data); - case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: + case FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO: return pullAppsOnExternalStorageInfo(atomTag, data); - case StatsLog.FACE_SETTINGS: + case FrameworkStatsLog.FACE_SETTINGS: return pullFaceSettings(atomTag, data); - case StatsLog.APP_OPS: + case FrameworkStatsLog.APP_OPS: return pullAppOps(atomTag, data); - case StatsLog.NOTIFICATION_REMOTE_VIEWS: + case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS: return pullNotificationRemoteViews(atomTag, data); - case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: + case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED: return pullDangerousPermissionState(atomTag, data); + case FrameworkStatsLog.BATTERY_LEVEL: + case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY: + case FrameworkStatsLog.FULL_BATTERY_CAPACITY: + case FrameworkStatsLog.BATTERY_VOLTAGE: + case FrameworkStatsLog.BATTERY_CYCLE_COUNT: + return pullHealthHal(atomTag, data); default: throw new UnsupportedOperationException("Unknown tagId=" + atomTag); } @@ -438,6 +448,14 @@ public class StatsPullAtomService extends SystemService { // Used by PROC_STATS and PROC_STATS_PKG_PROC atoms mBaseDir.mkdirs(); + + // Initialize HealthService + mHealthService = new BatteryService.HealthServiceWrapper(); + try { + mHealthService.init(); + } catch (RemoteException e) { + Slog.e(TAG, "failed to initialize healthHalWrapper"); + } } void registerEventListeners() { @@ -519,6 +537,11 @@ public class StatsPullAtomService extends SystemService { registerNotificationRemoteViews(); registerDangerousPermissionState(); registerDangerousPermissionStateSampled(); + registerBatteryLevel(); + registerRemainingBatteryCapacity(); + registerFullBatteryCapacity(); + registerBatteryVoltage(); + registerBatteryCycleCount(); } private INetworkStatsService getINetworkStatsService() { @@ -633,7 +656,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiBytesTransfer() { - int tagId = StatsLog.WIFI_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5}) .build(); @@ -725,7 +748,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiBytesTransferBackground() { - int tagId = StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG; + int tagId = FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3, 4, 5, 6}) .build(); @@ -763,7 +786,7 @@ public class StatsPullAtomService extends SystemService { } private void registerMobileBytesTransfer() { - int tagId = StatsLog.MOBILE_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5}) .build(); @@ -801,7 +824,7 @@ public class StatsPullAtomService extends SystemService { } private void registerMobileBytesTransferBackground() { - int tagId = StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG; + int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3, 4, 5, 6}) .build(); @@ -839,7 +862,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBluetoothBytesTransfer() { - int tagId = StatsLog.BLUETOOTH_BYTES_TRANSFER; + int tagId = FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3}) .build(); @@ -912,7 +935,7 @@ public class StatsPullAtomService extends SystemService { } private void registerKernelWakelock() { - int tagId = StatsLog.KERNEL_WAKELOCK; + int tagId = FrameworkStatsLog.KERNEL_WAKELOCK; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -940,7 +963,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerFreq() { - int tagId = StatsLog.CPU_TIME_PER_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3}) .build(); @@ -971,7 +994,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerUid() { - int tagId = StatsLog.CPU_TIME_PER_UID; + int tagId = FrameworkStatsLog.CPU_TIME_PER_UID; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3}) .build(); @@ -1000,7 +1023,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuTimePerUidFreq() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_TIME_PER_UID_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_UID_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4}) .build(); @@ -1032,7 +1055,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuActiveTime() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_ACTIVE_TIME; + int tagId = FrameworkStatsLog.CPU_ACTIVE_TIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2}) .build(); @@ -1059,7 +1082,7 @@ public class StatsPullAtomService extends SystemService { private void registerCpuClusterTime() { // the throttling is 3sec, handled in // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader - int tagId = StatsLog.CPU_CLUSTER_TIME; + int tagId = FrameworkStatsLog.CPU_CLUSTER_TIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {3}) .build(); @@ -1087,7 +1110,7 @@ public class StatsPullAtomService extends SystemService { } private void registerWifiActivityInfo() { - int tagId = StatsLog.WIFI_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.WIFI_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1139,7 +1162,7 @@ public class StatsPullAtomService extends SystemService { } private void registerModemActivityInfo() { - int tagId = StatsLog.MODEM_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.MODEM_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1177,7 +1200,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBluetoothActivityInfo() { - int tagId = StatsLog.BLUETOOTH_ACTIVITY_INFO; + int tagId = FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO; mStatsManager.registerPullAtomCallback( tagId, /* metadata */ null, @@ -1205,7 +1228,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemElapsedRealtime() { - int tagId = StatsLog.SYSTEM_ELAPSED_REALTIME; + int tagId = FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setCoolDownNs(NS_PER_SEC) .setTimeoutNs(NS_PER_SEC / 2) @@ -1228,7 +1251,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemUptime() { - int tagId = StatsLog.SYSTEM_UPTIME; + int tagId = FrameworkStatsLog.SYSTEM_UPTIME; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1247,7 +1270,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemoryState() { - int tagId = StatsLog.PROCESS_MEMORY_STATE; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_STATE; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4, 5, 6, 7, 8}) .build(); @@ -1293,7 +1316,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemoryHighWaterMark() { - int tagId = StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1346,7 +1369,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemorySnapshot() { - int tagId = StatsLog.PROCESS_MEMORY_SNAPSHOT; + int tagId = FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1406,7 +1429,7 @@ public class StatsPullAtomService extends SystemService { } private void registerSystemIonHeapSize() { - int tagId = StatsLog.SYSTEM_ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1426,7 +1449,7 @@ public class StatsPullAtomService extends SystemService { } private void registerIonHeapSize() { - int tagId = StatsLog.ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -1446,7 +1469,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessSystemIonHeapSize() { - int tagId = StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE; + int tagId = FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1472,7 +1495,7 @@ public class StatsPullAtomService extends SystemService { } private void registerTemperature() { - int tagId = StatsLog.TEMPERATURE; + int tagId = FrameworkStatsLog.TEMPERATURE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1510,7 +1533,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCoolingDevice() { - int tagId = StatsLog.COOLING_DEVICE; + int tagId = FrameworkStatsLog.COOLING_DEVICE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1547,7 +1570,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBinderCallsStats() { - int tagId = StatsLog.BINDER_CALLS; + int tagId = FrameworkStatsLog.BINDER_CALLS; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {4, 5, 6, 8, 12}) .build(); @@ -1593,7 +1616,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBinderCallsStatsExceptions() { - int tagId = StatsLog.BINDER_CALLS_EXCEPTIONS; + int tagId = FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1625,7 +1648,7 @@ public class StatsPullAtomService extends SystemService { } private void registerLooperStats() { - int tagId = StatsLog.LOOPER_STATS; + int tagId = FrameworkStatsLog.LOOPER_STATS; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {5, 6, 7, 8, 9}) .build(); @@ -1670,7 +1693,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDiskStats() { - int tagId = StatsLog.DISK_STATS; + int tagId = FrameworkStatsLog.DISK_STATS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1736,7 +1759,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDirectoryUsage() { - int tagId = StatsLog.DIRECTORY_USAGE; + int tagId = FrameworkStatsLog.DIRECTORY_USAGE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1752,7 +1775,7 @@ public class StatsPullAtomService extends SystemService { StatsEvent e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__DATA) .writeLong(statFsData.getAvailableBytes()) .writeLong(statFsData.getTotalBytes()) .build(); @@ -1760,7 +1783,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE) .writeLong(statFsCache.getAvailableBytes()) .writeLong(statFsCache.getTotalBytes()) .build(); @@ -1768,7 +1791,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM) + .writeInt(FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM) .writeLong(statFsSystem.getAvailableBytes()) .writeLong(statFsSystem.getTotalBytes()) .build(); @@ -1777,7 +1800,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppSize() { - int tagId = StatsLog.APP_SIZE; + int tagId = FrameworkStatsLog.APP_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1821,7 +1844,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCategorySize() { - int tagId = StatsLog.CATEGORY_SIZE; + int tagId = FrameworkStatsLog.CATEGORY_SIZE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1839,7 +1862,7 @@ public class StatsPullAtomService extends SystemService { StatsEvent e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_SIZE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1848,7 +1871,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1857,7 +1880,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE) .writeLong(json.optLong( DiskStatsFileLogger.APP_CACHE_AGG_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1866,7 +1889,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS) .writeLong(json.optLong( DiskStatsFileLogger.PHOTOS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1875,7 +1898,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS) .writeLong( json.optLong(DiskStatsFileLogger.VIDEOS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1884,7 +1907,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__AUDIO) .writeLong(json.optLong( DiskStatsFileLogger.AUDIO_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1893,7 +1916,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS) .writeLong( json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1901,7 +1924,8 @@ public class StatsPullAtomService extends SystemService { pulledData.add(e); e = StatsEvent.newBuilder() - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM) + .setAtomId(atomTag) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM) .writeLong(json.optLong( DiskStatsFileLogger.SYSTEM_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1910,7 +1934,7 @@ public class StatsPullAtomService extends SystemService { e = StatsEvent.newBuilder() .setAtomId(atomTag) - .writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER) + .writeInt(FrameworkStatsLog.CATEGORY_SIZE__CATEGORY__OTHER) .writeLong(json.optLong( DiskStatsFileLogger.MISC_KEY, /* fallback */ -1L)) .writeLong(cacheTime) @@ -1924,7 +1948,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNumFingerprintsEnrolled() { - int tagId = StatsLog.NUM_FINGERPRINTS_ENROLLED; + int tagId = FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1934,7 +1958,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNumFacesEnrolled() { - int tagId = StatsLog.NUM_FACES_ENROLLED; + int tagId = FrameworkStatsLog.NUM_FACES_ENROLLED; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -1992,7 +2016,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcStats() { - int tagId = StatsLog.PROC_STATS; + int tagId = FrameworkStatsLog.PROC_STATS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2002,7 +2026,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcStatsPkgProc() { - int tagId = StatsLog.PROC_STATS_PKG_PROC; + int tagId = FrameworkStatsLog.PROC_STATS_PKG_PROC; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2071,7 +2095,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDiskIO() { - int tagId = StatsLog.DISK_IO; + int tagId = FrameworkStatsLog.DISK_IO; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) .setCoolDownNs(3 * NS_PER_SEC) @@ -2108,7 +2132,7 @@ public class StatsPullAtomService extends SystemService { } private void registerPowerProfile() { - int tagId = StatsLog.POWER_PROFILE; + int tagId = FrameworkStatsLog.POWER_PROFILE; mStatsManager.registerPullAtomCallback( tagId, /* PullAtomMetadata */ null, @@ -2131,7 +2155,7 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessCpuTime() { - int tagId = StatsLog.PROCESS_CPU_TIME; + int tagId = FrameworkStatsLog.PROCESS_CPU_TIME; // Min cool-down is 5 sec, in line with what ActivityManagerService uses. PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setCoolDownNs(5 * NS_PER_SEC) @@ -2167,7 +2191,7 @@ public class StatsPullAtomService extends SystemService { } private void registerCpuTimePerThreadFreq() { - int tagId = StatsLog.CPU_TIME_PER_THREAD_FREQ; + int tagId = FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {7, 9, 11, 13, 15, 17, 19, 21}) .build(); @@ -2263,7 +2287,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerUse() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_USE; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2283,7 +2307,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerBlameUid() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_UID; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2313,7 +2337,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDeviceCalculatedPowerBlameOther() { - int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER; + int tagId = FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2346,7 +2370,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDebugElapsedClock() { - int tagId = StatsLog.DEBUG_ELAPSED_CLOCK; + int tagId = FrameworkStatsLog.DEBUG_ELAPSED_CLOCK; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {1, 2, 3, 4}) .build(); @@ -2397,7 +2421,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDebugFailingElapsedClock() { - int tagId = StatsLog.DEBUG_FAILING_ELAPSED_CLOCK; + int tagId = FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK; PullAtomMetadata metadata = new PullAtomMetadata.Builder() .setAdditiveFields(new int[] {1, 2, 3, 4}) .build(); @@ -2438,7 +2462,7 @@ public class StatsPullAtomService extends SystemService { } private void registerBuildInformation() { - int tagId = StatsLog.BUILD_INFORMATION; + int tagId = FrameworkStatsLog.BUILD_INFORMATION; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2465,7 +2489,7 @@ public class StatsPullAtomService extends SystemService { } private void registerRoleHolder() { - int tagId = StatsLog.ROLE_HOLDER; + int tagId = FrameworkStatsLog.ROLE_HOLDER; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2523,7 +2547,7 @@ public class StatsPullAtomService extends SystemService { } private void registerDangerousPermissionState() { - int tagId = StatsLog.DANGEROUS_PERMISSION_STATE; + int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2561,7 +2585,7 @@ public class StatsPullAtomService extends SystemService { } reportedUids.add(pkg.applicationInfo.uid); - if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED + if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED && ThreadLocalRandom.current().nextFloat() > 0.01f) { continue; } @@ -2588,7 +2612,7 @@ public class StatsPullAtomService extends SystemService { e.setAtomId(atomTag); e.writeString(permName); e.writeInt(pkg.applicationInfo.uid); - if (atomTag == StatsLog.DANGEROUS_PERMISSION_STATE) { + if (atomTag == FrameworkStatsLog.DANGEROUS_PERMISSION_STATE) { e.writeString(""); } e.writeBoolean((pkg.requestedPermissionsFlags[permNum] @@ -2609,7 +2633,7 @@ public class StatsPullAtomService extends SystemService { } private void registerTimeZoneDataInfo() { - int tagId = StatsLog.TIME_ZONE_DATA_INFO; + int tagId = FrameworkStatsLog.TIME_ZONE_DATA_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2636,7 +2660,7 @@ public class StatsPullAtomService extends SystemService { } private void registerExternalStorageInfo() { - int tagId = StatsLog.EXTERNAL_STORAGE_INFO; + int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2656,11 +2680,11 @@ public class StatsPullAtomService extends SystemService { final DiskInfo diskInfo = vol.getDisk(); if (diskInfo != null && envState.equals(Environment.MEDIA_MOUNTED)) { // Get the type of the volume, if it is adoptable or portable. - int volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; + int volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__OTHER; if (vol.getType() == TYPE_PUBLIC) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; + volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PUBLIC; } else if (vol.getType() == TYPE_PRIVATE) { - volumeType = StatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; + volumeType = FrameworkStatsLog.EXTERNAL_STORAGE_INFO__VOLUME_TYPE__PRIVATE; } // Get the type of external storage inserted in the device (sd cards, usb, etc.) @@ -2686,7 +2710,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppsOnExternalStorageInfo() { - int tagId = StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO; + int tagId = FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2742,7 +2766,7 @@ public class StatsPullAtomService extends SystemService { } private void registerFaceSettings() { - int tagId = StatsLog.FACE_SETTINGS; + int tagId = FrameworkStatsLog.FACE_SETTINGS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2796,7 +2820,7 @@ public class StatsPullAtomService extends SystemService { } private void registerAppOps() { - int tagId = StatsLog.APP_OPS; + int tagId = FrameworkStatsLog.APP_OPS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2907,7 +2931,7 @@ public class StatsPullAtomService extends SystemService { } private void registerNotificationRemoteViews() { - int tagId = StatsLog.NOTIFICATION_REMOTE_VIEWS; + int tagId = FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2951,7 +2975,37 @@ public class StatsPullAtomService extends SystemService { } private void registerDangerousPermissionStateSampled() { - int tagId = StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED; + int tagId = FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + + private void registerBatteryLevel() { + int tagId = FrameworkStatsLog.BATTERY_LEVEL; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + + private void registerRemainingBatteryCapacity() { + int tagId = FrameworkStatsLog.REMAINING_BATTERY_CAPACITY; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + + private void registerFullBatteryCapacity() { + int tagId = FrameworkStatsLog.FULL_BATTERY_CAPACITY; mStatsManager.registerPullAtomCallback( tagId, null, // use default PullAtomMetadata values @@ -2960,13 +3014,72 @@ public class StatsPullAtomService extends SystemService { ); } + private void registerBatteryVoltage() { + int tagId = FrameworkStatsLog.BATTERY_VOLTAGE; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + + private void registerBatteryCycleCount() { + int tagId = FrameworkStatsLog.BATTERY_CYCLE_COUNT; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + BackgroundThread.getExecutor(), + mStatsCallbackImpl + ); + } + + int pullHealthHal(int atomTag, List<StatsEvent> pulledData) { + IHealth healthService = mHealthService.getLastService(); + if (healthService == null) { + return StatsManager.PULL_SKIP; + } + try { + healthService.getHealthInfo((result, value) -> { + int pulledValue; + switch(atomTag) { + case FrameworkStatsLog.BATTERY_LEVEL: + pulledValue = value.legacy.batteryLevel; + break; + case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY: + pulledValue = value.legacy.batteryChargeCounter; + break; + case FrameworkStatsLog.FULL_BATTERY_CAPACITY: + pulledValue = value.legacy.batteryFullCharge; + break; + case FrameworkStatsLog.BATTERY_VOLTAGE: + pulledValue = value.legacy.batteryVoltage; + break; + case FrameworkStatsLog.BATTERY_CYCLE_COUNT: + pulledValue = value.legacy.batteryCycleCount; + break; + default: + throw new IllegalStateException("Invalid atomTag in healthHal puller: " + + atomTag); + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(pulledValue) + .build(); + pulledData.add(e); + }); + } catch (RemoteException | IllegalStateException e) { + return StatsManager.PULL_SKIP; + } + return StatsManager.PULL_SUCCESS; + } // Thermal event received from vendor thermal management subsystem private static final class ThermalEventListener extends IThermalEventListener.Stub { @Override public void notifyThrottling(Temperature temp) { - StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(), - temp.getName(), (int) (temp.getValue() * 10), temp.getStatus()); + FrameworkStatsLog.write(FrameworkStatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, + temp.getType(), temp.getName(), (int) (temp.getValue() * 10), temp.getStatus()); } } @@ -2974,14 +3087,14 @@ public class StatsPullAtomService extends SystemService { ConnectivityManager.NetworkCallback { @Override public void onAvailable(Network network) { - StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, - StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED); + FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, + FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED); } @Override public void onLost(Network network) { - StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, - StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED); + FrameworkStatsLog.write(FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED, network.netId, + FrameworkStatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED); } } } diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java index cdf8ea3460c4..bbd1ae60cb62 100644 --- a/services/core/java/com/android/server/timezone/RulesManagerService.java +++ b/services/core/java/com/android/server/timezone/RulesManagerService.java @@ -198,7 +198,7 @@ public final class RulesManagerService extends IRulesManager.Stub { Slog.w(TAG, "Failed to read staged distro.", e); } } - return new RulesState(baseVersion.rulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED, + return new RulesState(baseVersion.getRulesVersion(), DISTRO_FORMAT_VERSION_SUPPORTED, operationInProgress, stagedOperationStatus, stagedDistroRulesVersion, distroStatus, installedDistroRulesVersion); } diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index d746691b4773..61a33b4fb781 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -361,7 +361,7 @@ final class AccessibilityController { private final Region mTempRegion3 = new Region(); private final Region mTempRegion4 = new Region(); - private final Context mContext; + private final Context mDisplayContext; private final WindowManagerService mService; private final MagnifiedViewport mMagnifedViewport; private final Handler mHandler; @@ -378,14 +378,14 @@ final class AccessibilityController { DisplayContent displayContent, Display display, MagnificationCallbacks callbacks) { - mContext = windowManagerService.mContext; + mDisplayContext = windowManagerService.mContext.createDisplayContext(display); mService = windowManagerService; mCallbacks = callbacks; mDisplayContent = displayContent; mDisplay = display; mHandler = new MyHandler(mService.mH.getLooper()); mMagnifedViewport = new MagnifiedViewport(); - mLongAnimationDuration = mContext.getResources().getInteger( + mLongAnimationDuration = mDisplayContext.getResources().getInteger( com.android.internal.R.integer.config_longAnimTime); } @@ -568,8 +568,6 @@ final class AccessibilityController { private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain(); - private final WindowManager mWindowManager; - private final float mBorderWidth; private final int mHalfBorderWidth; private final int mDrawBorderInset; @@ -580,14 +578,13 @@ final class AccessibilityController { private int mTempLayer = 0; public MagnifiedViewport() { - mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE); - mBorderWidth = mContext.getResources().getDimension( + mBorderWidth = mDisplayContext.getResources().getDimension( com.android.internal.R.dimen.accessibility_magnification_indicator_width); mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2); mDrawBorderInset = (int) mBorderWidth / 2; - mWindow = new ViewportWindow(mContext); + mWindow = new ViewportWindow(mDisplayContext); - if (mContext.getResources().getConfiguration().isScreenRound()) { + if (mDisplayContext.getResources().getConfiguration().isScreenRound()) { mCircularPath = new Path(); mDisplay.getRealSize(mTempPoint); final int centerXY = mTempPoint.x / 2; @@ -916,7 +913,7 @@ final class AccessibilityController { public void updateSize(SurfaceControl.Transaction t) { synchronized (mService.mGlobalLock) { - mWindowManager.getDefaultDisplay().getRealSize(mTempPoint); + mDisplay.getRealSize(mTempPoint); t.setBufferSize(mSurfaceControl, mTempPoint.x, mTempPoint.y); invalidate(mDirtyRect); } diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 23b94bdb74c8..2ef0015f2b7d 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -83,13 +83,13 @@ import android.util.ArrayMap; import android.util.EventLog; import android.util.Log; import android.util.Slog; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; @@ -768,8 +768,8 @@ class ActivityMetricsLogger { builder.setType(type); builder.addTaggedData(FIELD_CLASS_NAME, activity.info.name); mMetricsLogger.write(builder); - StatsLog.write( - StatsLog.APP_START_CANCELED, + FrameworkStatsLog.write( + FrameworkStatsLog.APP_START_CANCELED, activity.info.applicationInfo.uid, activity.packageName, convertAppStartTransitionType(type), @@ -844,8 +844,8 @@ class ActivityMetricsLogger { builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER, packageOptimizationInfo.getCompilationFilter()); mMetricsLogger.write(builder); - StatsLog.write( - StatsLog.APP_START_OCCURRED, + FrameworkStatsLog.write( + FrameworkStatsLog.APP_START_OCCURRED, info.applicationInfo.uid, info.packageName, convertAppStartTransitionType(info.type), @@ -895,15 +895,15 @@ class ActivityMetricsLogger { private int convertAppStartTransitionType(int tronType) { if (tronType == TYPE_TRANSITION_COLD_LAUNCH) { - return StatsLog.APP_START_OCCURRED__TYPE__COLD; + return FrameworkStatsLog.APP_START_OCCURRED__TYPE__COLD; } if (tronType == TYPE_TRANSITION_WARM_LAUNCH) { - return StatsLog.APP_START_OCCURRED__TYPE__WARM; + return FrameworkStatsLog.APP_START_OCCURRED__TYPE__WARM; } if (tronType == TYPE_TRANSITION_HOT_LAUNCH) { - return StatsLog.APP_START_OCCURRED__TYPE__HOT; + return FrameworkStatsLog.APP_START_OCCURRED__TYPE__HOT; } - return StatsLog.APP_START_OCCURRED__TYPE__UNKNOWN; + return FrameworkStatsLog.APP_START_OCCURRED__TYPE__UNKNOWN; } /** @return the last known window drawn delay of the given activity. */ @@ -957,13 +957,13 @@ class ActivityMetricsLogger { builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING, info.mProcessRunning ? 1 : 0); mMetricsLogger.write(builder); - StatsLog.write( - StatsLog.APP_START_FULLY_DRAWN, + FrameworkStatsLog.write( + FrameworkStatsLog.APP_START_FULLY_DRAWN, info.mLastLaunchedActivity.info.applicationInfo.uid, info.mLastLaunchedActivity.packageName, restoredFromBundle - ? StatsLog.APP_START_FULLY_DRAWN__TYPE__WITH_BUNDLE - : StatsLog.APP_START_FULLY_DRAWN__TYPE__WITHOUT_BUNDLE, + ? FrameworkStatsLog.APP_START_FULLY_DRAWN__TYPE__WITH_BUNDLE + : FrameworkStatsLog.APP_START_FULLY_DRAWN__TYPE__WITHOUT_BUNDLE, info.mLastLaunchedActivity.info.name, info.mProcessRunning, startupTimeMs); @@ -1068,8 +1068,8 @@ class ActivityMetricsLogger { return; } - StatsLog.write( - StatsLog.APP_START_MEMORY_STATE_CAPTURED, + FrameworkStatsLog.write( + FrameworkStatsLog.APP_START_MEMORY_STATE_CAPTURED, uid, info.processName, info.launchedActivityName, diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index dda11f96cc8a..b05c25082f85 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3074,7 +3074,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this); waitingToShow = false; - boolean delayed = isAnimating(TRANSITION | CHILDREN); + // Defer removal of this activity when either a child is animating, or app transition is on + // going. App transition animation might be applied on the parent stack not on the activity, + // but the actual frame buffer is associated with the activity, so we have to keep the + // activity while a parent is animating. + boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN); if (getDisplayContent().mClosingApps.contains(this)) { delayed = true; } else if (getDisplayContent().mAppTransition.isTransitionSet()) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 362e781f7fb9..a513ef8f3190 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -1711,6 +1711,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { * invisible as well and added to the stopping list. After which we process the * stopping list by handling the idle. */ + stack.cancelAnimation(); stack.mForceHidden = true; stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); stack.mForceHidden = false; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 976fbdb36bba..f019013eedf1 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -222,7 +222,6 @@ import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.view.IRecentsAnimationRunner; @@ -248,6 +247,7 @@ import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.KeyguardDismissCallback; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; @@ -5380,7 +5380,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION, "Updating global configuration to: " + values); writeConfigurationChanged(changes); - StatsLog.write(StatsLog.RESOURCE_CONFIGURATION_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.RESOURCE_CONFIGURATION_CHANGED, values.colorMode, values.densityDpi, values.fontScale, @@ -5699,8 +5699,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // will wake up stacks or put them to sleep as appropriate. if (wasSleeping) { mSleeping = false; - StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, - StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__AWAKE); + FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, + FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__AWAKE); startTimeTrackingFocusedActivityLocked(); mTopProcessState = ActivityManager.PROCESS_STATE_TOP; Slog.d(TAG, "Top Process State changed to PROCESS_STATE_TOP"); @@ -5712,8 +5712,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } else if (!mSleeping && shouldSleep) { mSleeping = true; - StatsLog.write(StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, - StatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__ASLEEP); + FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED, + FrameworkStatsLog.ACTIVITY_MANAGER_SLEEP_STATE_CHANGED__STATE__ASLEEP); if (mCurAppTimeTracker != null) { mCurAppTimeTracker.stop(); } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 3927d5fa2604..0798a910c860 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -431,6 +431,8 @@ public class AppTransitionController { while (!candidates.isEmpty()) { final WindowContainer current = candidates.removeFirst(); final WindowContainer parent = current.getParent(); + siblings.clear(); + siblings.add(current); boolean canPromote = true; if (parent == null) { @@ -468,12 +470,11 @@ public class AppTransitionController { // // [Task] +- [ActivityRecord1] (visible, in opening apps) // +- [ActivityRecord2] (visible, not in opening apps) - siblings.clear(); for (int j = 0; j < parent.getChildCount(); ++j) { final WindowContainer sibling = parent.getChildAt(j); - if (sibling == current || candidates.remove(sibling)) { + if (candidates.remove(sibling)) { siblings.add(sibling); - } else if (sibling.isVisible()) { + } else if (sibling != current && sibling.isVisible()) { canPromote = false; } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c50048eeab64..6e479b2b53e0 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1244,6 +1244,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mDisplayRotation; } + void setInsetProvider(@InternalInsetsType int type, WindowState win, + @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider){ + setInsetProvider(type, win, frameProvider, null /* imeFrameProvider */); + } + /** * Marks a window as providing insets for the rest of the windows in the system. * @@ -1251,10 +1256,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * @param win The window. * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of * the window should be taken. + * @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or + * {@code null} if the normal frame should be taken. */ void setInsetProvider(@InternalInsetsType int type, WindowState win, - @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { - mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider); + @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider, + @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) { + mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider, + imeFrameProvider); } InsetsStateController getInsetsStateController() { @@ -3283,7 +3292,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } computeImeTarget(true /* updateImeTarget */); mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win, - null /* frameProvider */); + null /* frameProvider */, null /* imeFrameProvider */); } /** @@ -3407,6 +3416,57 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo && mInputMethodTarget.mActivityRecord.matchParentBounds()); } + /** + * Get IME target that should host IME when this display that is reparented to another + * WindowState. + * IME is never displayed in a child display. + * Use {@link WindowState#getImeControlTarget()} when IME target window + * which originally called + * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is known. + * + * @return {@link WindowState} of host that controls IME. + * {@code null} when {@param dc} is not a virtual display. + * @see DisplayContent#reparent + */ + @Nullable + WindowState getImeControlTarget() { + WindowState imeTarget = mInputMethodTarget; + if (imeTarget != null) { + return imeTarget.getImeControlTarget(); + } + + return getInsetsStateController().getImeSourceProvider().getControlTarget().getWindow(); + } + + /** + * Finds the window which can host IME if IME target cannot host it. + * e.g. IME target cannot host IME when it's display has a parent display OR when display + * doesn't support IME/system decorations. + * + * @param target current IME target. + * @return {@link WindowState} that can host IME. + * @see DisplayContent#getImeControlTarget() + */ + WindowState getImeHostOrFallback(WindowState target) { + if (target != null && target.getDisplayContent().canShowIme()) { + return target; + } + + // host is in non-default display that doesn't support system decor, default to + // default display's StatusBar to control IME. + // TODO: (b/148234093)find a better host OR control IME animation/visibility directly + // because it won't work when statusbar isn't available. + return mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar(); + } + + boolean canShowIme() { + if (isUntrustedVirtualDisplay()) { + return false; + } + return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this) + || mWmService.mForceDesktopModeOnExternalDisplays; + } + private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) { if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) { return; @@ -3416,10 +3476,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mInputMethodTargetWaitingAnim = targetWaitingAnim; assignWindowLayers(false /* setLayoutNeeded */); mInputMethodControlTarget = computeImeControlTarget(); - mInsetsStateController.onImeTargetChanged(mInputMethodControlTarget); + mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget); updateImeParent(); } + /** + * IME control target is the window that controls the IME visibility and animation. + * This window is same as the window on which startInput is called. + * @param target the window that receives IME control. + * + * @see #getImeControlTarget() + */ + void updateImeControlTarget(WindowState target) { + mInputMethodControlTarget = target; + mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget); + } + private void updateImeParent() { // Force attaching IME to the display when magnifying, or it would be magnified with // target app together. diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index c6ccd4af06c5..40c335b0592b 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -131,6 +131,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.hardware.power.V1_0.PowerHint; +import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -968,6 +969,12 @@ public class DisplayPolicy { } break; case TYPE_NAVIGATION_BAR_PANEL: + // Check for permission if the caller is not the recents component. + if (!mService.mAtmInternal.isCallerRecents(Binder.getCallingUid())) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.STATUS_BAR_SERVICE, "DisplayPolicy"); + } + break; case TYPE_STATUS_BAR_PANEL: case TYPE_STATUS_BAR_SUB_PANEL: case TYPE_VOICE_INTERACTION_STARTING: @@ -1026,7 +1033,12 @@ public class DisplayPolicy { - getNavigationBarHeight(displayFrames.mRotation, mDisplayContent.getConfiguration().uiMode); } - }); + }, + + // For IME we use regular frame. + (displayFrames, windowState, inOutFrame) -> + inOutFrame.set(windowState.getFrameLw())); + mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win, (displayFrames, windowState, inOutFrame) -> { inOutFrame.top -= mBottomGestureAdditionalInset; @@ -3068,7 +3080,9 @@ public class DisplayPolicy { } final InsetsControlTarget controlTarget = swipeTarget.getControllableInsetProvider().getControlTarget(); - if (controlTarget == null) { + + // No transient mode on lockscreen (in notification shade window). + if (controlTarget == null || controlTarget == getNotificationShade()) { return; } if (controlTarget.canShowTransient()) { diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index fb97ecf8bbc4..3ff1b95dc716 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -16,9 +16,13 @@ package com.android.server.wm; +import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME; + import android.view.InsetsSource; import android.view.WindowInsets; +import com.android.server.protolog.common.ProtoLog; + /** * Controller for IME inset source on the server. It's called provider as it provides the * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}. @@ -35,40 +39,40 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { } /** - * Called when a layout pass has occurred. - */ - void onPostLayout() { - super.onPostLayout(); - - if (mImeTargetFromIme != null - && isImeTargetFromDisplayContentAndImeSame() - && mWin != null - && mWin.isDrawnLw() - && !mWin.mGivenInsetsPending) { - mIsImeLayoutDrawn = true; - } - } - - /** - * Called when Insets have been dispatched to client. + * Called when Insets have been dispatched to client. This gets called just after onPostLayout. */ void onPostInsetsDispatched() { - if (mIsImeLayoutDrawn && mShowImeRunner != null) { - // Show IME if InputMethodService requested to be shown and it's layout has finished. - mShowImeRunner.run(); - } + checkShowImePostLayout(); } /** * Called from {@link WindowManagerInternal#showImePostLayout} when {@link InputMethodService} * requests to show IME on {@param imeTarget}. + * * @param imeTarget imeTarget on which IME request is coming from. */ void scheduleShowImePostLayout(WindowState imeTarget) { + boolean targetChanged = mImeTargetFromIme != imeTarget + && mImeTargetFromIme != null && imeTarget != null && mShowImeRunner != null + && mImeTargetFromIme.mActivityRecord == imeTarget.mActivityRecord; mImeTargetFromIme = imeTarget; + if (targetChanged) { + // target changed, check if new target can show IME. + ProtoLog.d(WM_DEBUG_IME, "IME target changed within ActivityRecord"); + checkShowImePostLayout(); + // if IME cannot be shown at this time, it is scheduled to be shown. + // once window that called IMM.showSoftInput() and DisplayContent's ImeTarget match, + // it will be shown. + return; + } + + ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeTargetFromIme.getName()); mShowImeRunner = () -> { + ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner"); // Target should still be the same. if (isImeTargetFromDisplayContentAndImeSame()) { + ProtoLog.d(WM_DEBUG_IME, "call showInsets(ime) on %s", + mDisplayContent.mInputMethodControlTarget.getWindow().getName()); mDisplayContent.mInputMethodControlTarget.showInsets( WindowInsets.Type.ime(), true /* fromIme */); } @@ -76,10 +80,27 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { }; } + private void checkShowImePostLayout() { + // check if IME is drawn + if (mIsImeLayoutDrawn + || (mImeTargetFromIme != null + && isImeTargetFromDisplayContentAndImeSame() + && mWin != null + && mWin.isDrawnLw() + && !mWin.mGivenInsetsPending)) { + mIsImeLayoutDrawn = true; + // show IME if InputMethodService requested it to be shown. + if (mShowImeRunner != null) { + mShowImeRunner.run(); + } + } + } + /** * Abort any pending request to show IME post layout. */ void abortShowImePostLayout() { + ProtoLog.d(WM_DEBUG_IME, "abortShowImePostLayout"); mImeTargetFromIme = null; mIsImeLayoutDrawn = false; mShowImeRunner = null; @@ -96,12 +117,14 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of // actual IME target. final WindowState dcTarget = mDisplayContent.mInputMethodTarget; - if (dcTarget == null) { + if (dcTarget == null || mImeTargetFromIme == null) { return false; } + ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeTargetFromIme: %s", + dcTarget.getName(), mImeTargetFromIme.getName()); + return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget) || (mImeTargetFromIme != null && dcTarget.getParentWindow() == mImeTargetFromIme - && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer); + && dcTarget.mSubLayer > mImeTargetFromIme.mSubLayer); } - } diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java index ef6f84703723..2f02ffb17d3a 100644 --- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java +++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java @@ -275,7 +275,7 @@ public class ImmersiveModeConfirmation { super.onAttachedToWindow(); DisplayMetrics metrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(metrics); + mContext.getDisplay().getMetrics(metrics); float density = metrics.density; getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener); diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java index 154cde140810..20e8f2ba485a 100644 --- a/services/core/java/com/android/server/wm/InsetsControlTarget.java +++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java @@ -26,6 +26,13 @@ interface InsetsControlTarget { void notifyInsetsControlChanged(); /** + * @return {@link WindowState} of this target, if any. + */ + default WindowState getWindow() { + return null; + } + + /** * Instructs the control target to show inset sources. * * @param types to specify which types of insets source window should be shown. diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index fa764e3dfc18..2d4211aa16d8 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -187,6 +187,10 @@ class InsetsPolicy { if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) { return mTransientControlTarget; } + if (focusedWin == mPolicy.getNotificationShade()) { + // Notification shade has control anyways, no reason to force anything. + return focusedWin; + } if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) { return null; } @@ -197,6 +201,10 @@ class InsetsPolicy { if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) { return mTransientControlTarget; } + if (focusedWin == mPolicy.getNotificationShade()) { + // Notification shade has control anyways, no reason to force anything. + return focusedWin; + } if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) { return null; } @@ -204,9 +212,6 @@ class InsetsPolicy { } private boolean isKeyguardOrStatusBarForciblyVisible() { - if (mPolicy.isKeyguardShowing()) { - return true; - } final WindowState statusBar = mPolicy.getStatusBar(); if (statusBar != null) { // TODO(b/118118435): Pretend to the app that it's still able to control it? diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 2bb58ddc5b38..db434800c979 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -34,6 +34,7 @@ import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; +import android.view.InsetsState.InternalInsetsType; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; @@ -61,6 +62,8 @@ class InsetsSourceProvider { private @Nullable ControlAdapter mAdapter; private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider; + private TriConsumer<DisplayFrames, WindowState, Rect> mImeFrameProvider; + private final Rect mImeOverrideFrame = new Rect(); /** The visibility override from the current controlling window. */ private boolean mClientVisible; @@ -111,9 +114,12 @@ class InsetsSourceProvider { * @param win The window that links to this source. * @param frameProvider Based on display frame state and the window, calculates the resulting * frame that should be reported to clients. + * @param imeFrameProvider Based on display frame state and the window, calculates the resulting + * frame that should be reported to IME. */ void setWindow(@Nullable WindowState win, - @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) { + @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider, + @Nullable TriConsumer<DisplayFrames, WindowState, Rect> imeFrameProvider) { if (mWin != null) { if (mControllable) { mWin.setControllableInsetProvider(null); @@ -126,6 +132,7 @@ class InsetsSourceProvider { } mWin = win; mFrameProvider = frameProvider; + mImeFrameProvider = imeFrameProvider; if (win == null) { setServerVisible(false); mSource.setFrame(new Rect()); @@ -162,6 +169,12 @@ class InsetsSourceProvider { } mSource.setFrame(mTmpRect); + if (mImeFrameProvider != null) { + mImeOverrideFrame.set(mWin.getFrameLw()); + mImeFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, + mImeOverrideFrame); + } + if (mWin.mGivenVisibleInsets.left != 0 || mWin.mGivenVisibleInsets.top != 0 || mWin.mGivenVisibleInsets.right != 0 || mWin.mGivenVisibleInsets.bottom != 0) { mTmpRect.set(mWin.getFrameLw()); @@ -209,6 +222,12 @@ class InsetsSourceProvider { // to control the window for now. return; } + if (target != null && target.getWindow() != null) { + // ime control target could be a different window. + // Refer WindowState#getImeControlTarget(). + target = target.getWindow().getImeControlTarget(); + } + if (mWin == null) { mControlTarget = target; return; @@ -303,6 +322,21 @@ class InsetsSourceProvider { return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible; } + /** + * @return Whether this provider uses a different frame to dispatch to the IME. + */ + boolean overridesImeFrame() { + return mImeFrameProvider != null; + } + + /** + * @return Rect to dispatch to the IME as frame. Only valid if {@link #overridesImeFrame()} + * returns {@code true}. + */ + Rect getImeOverrideFrame() { + return mImeOverrideFrame; + } + private class ControlAdapter implements AnimationAdapter { private SurfaceControl mCapturedLeash; diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index b2234d17984e..568966ae8d2e 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -88,6 +88,20 @@ class InsetsStateController { state.removeSource(ITYPE_IME); state.removeSource(ITYPE_STATUS_BAR); } + + // IME needs different frames for certain cases (e.g. navigation bar in gesture nav). + if (type == ITYPE_IME) { + for (int i = mProviders.size() - 1; i >= 0; i--) { + InsetsSourceProvider otherProvider = mProviders.valueAt(i); + if (otherProvider.overridesImeFrame()) { + InsetsSource override = + new InsetsSource(state.getSource(otherProvider.getSource().getType())); + override.setFrame(otherProvider.getImeOverrideFrame()); + state.addSource(override); + } + } + } + return state; } @@ -167,7 +181,7 @@ class InsetsStateController { return mTypeFakeControlTargetMap.get(type) == target; } - void onImeTargetChanged(@Nullable InsetsControlTarget imeTarget) { + void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) { onControlChanged(ITYPE_IME, imeTarget); notifyPendingInsetsControlChanged(); } diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/services/core/java/com/android/server/wm/ProtoLogGroup.java index 5c2830e13b75..51725cecbc74 100644 --- a/services/core/java/com/android/server/wm/ProtoLogGroup.java +++ b/services/core/java/com/android/server/wm/ProtoLogGroup.java @@ -59,6 +59,8 @@ public enum ProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM), WM_DEBUG_WINDOW_MOVEMENT(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM), + WM_DEBUG_IME(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, + Consts.TAG_WM), TEST_GROUP(true, true, false, "WindowManagetProtoLogTest"); private final boolean mEnabled; diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 283be4010677..66c65e226bce 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import android.os.IBinder; import android.os.RemoteException; @@ -106,9 +107,11 @@ class TaskOrganizerController { * and receive taskVanished callbacks in the process. */ void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) { - if (windowingMode != WINDOWING_MODE_PINNED) { + if (windowingMode != WINDOWING_MODE_PINNED && + windowingMode != WINDOWING_MODE_MULTI_WINDOW) { throw new UnsupportedOperationException( - "As of now only Pinned windowing mode is supported for registerTaskOrganizer"); + "As of now only Pinned and Multiwindow windowing modes are" + + " supported for registerTaskOrganizer"); } clearIfNeeded(windowingMode); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index e47eaee5bce4..f4e42455087d 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -36,7 +36,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; - import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.getColorViewLeftInset; @@ -188,8 +187,9 @@ class TaskSnapshotSurface implements StartingSurface { return null; } sysUiVis = topFullscreenOpaqueWindow.getSystemUiVisibility(); - windowFlags = topFullscreenOpaqueWindow.getAttrs().flags; - windowPrivateFlags = topFullscreenOpaqueWindow.getAttrs().privateFlags; + WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs; + windowFlags = attrs.flags; + windowPrivateFlags = attrs.privateFlags; layoutParams.packageName = mainWindow.getAttrs().packageName; layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations; @@ -204,6 +204,14 @@ class TaskSnapshotSurface implements StartingSurface { layoutParams.width = LayoutParams.MATCH_PARENT; layoutParams.height = LayoutParams.MATCH_PARENT; layoutParams.systemUiVisibility = sysUiVis; + layoutParams.insetsFlags.behavior + = topFullscreenOpaqueWindow.mAttrs.insetsFlags.behavior; + layoutParams.insetsFlags.appearance + = topFullscreenOpaqueWindow.mAttrs.insetsFlags.appearance; + layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes()); + layoutParams.setFitInsetsSides(attrs.getFitInsetsSides()); + layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility()); + layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId)); final TaskDescription td = task.getTaskDescription(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2c6c756dda3b..7f845671d3d1 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2536,11 +2536,12 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void addWindowToken(IBinder binder, int type, int displayId) { - addWindowContextToken(binder, type, displayId, null); + addWindowTokenWithOptions(binder, type, displayId, null /* options */, + null /* packageName */); } - @Override - public int addWindowContextToken(IBinder binder, int type, int displayId, String packageName) { + public int addWindowTokenWithOptions(IBinder binder, int type, int displayId, Bundle options, + String packageName) { final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()"); if (!callerCanManageAppTokens) { @@ -6991,8 +6992,15 @@ public class WindowManagerService extends IWindowManager.Stub throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); } boolean show; + final DisplayContent dc = mRoot.getDisplayContent(displayId); + if (dc == null) { + ProtoLog.w(WM_ERROR, + "Attempted to get IME flag of a display that does not exist: %d", + displayId); + return false; + } synchronized (mGlobalLock) { - show = shouldShowImeSystemWindowUncheckedLocked(displayId); + show = dc.canShowIme(); } return show; @@ -7291,6 +7299,10 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG_WM, "updateInputMethodTargetWindow: imeToken=" + imeToken + " imeTargetWindowToken=" + imeTargetWindowToken); } + final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); + if (imeTarget != null) { + imeTarget.getDisplayContent().updateImeControlTarget(imeTarget); + } } @Override @@ -7405,15 +7417,13 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void showImePostLayout(IBinder imeTargetWindowToken) { synchronized (mGlobalLock) { - final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); + WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); if (imeTarget == null) { return; } - final int displayId = imeTarget.getDisplayId(); - if (!shouldShowImeSystemWindowUncheckedLocked(displayId)) { - return; - } + imeTarget = imeTarget.getImeControlTarget(); + final int displayId = imeTarget.getDisplayId(); mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider() .scheduleShowImePostLayout(imeTarget); } @@ -7423,12 +7433,16 @@ public class WindowManagerService extends IWindowManager.Stub public void hideIme(int displayId) { synchronized (mGlobalLock) { final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc != null && dc.mInputMethodTarget != null) { + if (dc != null) { + WindowState imeTarget = dc.getImeControlTarget(); + if (imeTarget == null) { + return; + } // If there was a pending IME show(), reset it as IME has been // requested to be hidden. - dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout(); - dc.mInputMethodControlTarget.hideInsets(WindowInsets.Type.ime(), - true /* fromIme */); + imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider() + .abortShowImePostLayout(); + imeTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */); } } } @@ -7936,21 +7950,6 @@ public class WindowManagerService extends IWindowManager.Stub return true; } - private boolean shouldShowImeSystemWindowUncheckedLocked(final int displayId) { - final DisplayContent displayContent = mRoot.getDisplayContent(displayId); - if (displayContent == null) { - ProtoLog.w(WM_ERROR, - "Attempted to get IME flag of a display that does not exist: %d", - displayId); - return false; - } - if (displayContent.isUntrustedVirtualDisplay()) { - return false; - } - return mDisplayWindowSettings.shouldShowImeLocked(displayContent) - || mForceDesktopModeOnExternalDisplays; - } - @Override public void getWindowInsets(WindowManager.LayoutParams attrs, int displayId, Rect outContentInsets, Rect outStableInsets, diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 874a25e50ae6..fc04126714d1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -196,7 +196,6 @@ import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.MergedConfiguration; import android.util.Slog; -import android.util.StatsLog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.view.Display; @@ -227,6 +226,7 @@ import android.view.animation.Interpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.KeyInterceptionInfo; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ToBooleanFunction; import com.android.server.policy.WindowManagerPolicy; import com.android.server.protolog.common.ProtoLog; @@ -3154,7 +3154,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final int requested = mLastRequestedExclusionHeight[side]; final int granted = mLastGrantedExclusionHeight[side]; - StatsLog.write(StatsLog.EXCLUSION_RECT_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.EXCLUSION_RECT_STATE_CHANGED, mAttrs.packageName, requested, requested - granted /* rejected */, side + 1 /* Sides are 1-indexed in atoms.proto */, (getConfiguration().orientation == ORIENTATION_LANDSCAPE), @@ -3518,6 +3518,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } @Override + public WindowState getWindow() { + return this; + } + + @Override public void showInsets(@InsetsType int types, boolean fromIme) { try { mClient.showInsets(types, fromIme); @@ -5334,6 +5339,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } + /** + * Get IME target that should host IME when this window's display has a parent. + * Note: IME is never hosted by a display that has a parent. + * When window calling + * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown, + * use {@link DisplayContent#getImeControlTarget()} instead. + * + * @return {@link WindowState} of host that controls the IME. + * When window is doesn't have a parent, it is returned as-is. + */ + WindowState getImeControlTarget() { + final DisplayContent dc = getDisplayContent(); + final WindowState parentWindow = dc.getParentWindow(); + + // If target's display has a parent, IME is displayed in the parent display. + return dc.getImeHostOrFallback(parentWindow != null ? parentWindow : this); + } + @Override void assignLayer(Transaction t, int layer) { // See comment in assignRelativeLayerForImeTargetChild diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp index 78b64ca072ad..67254b811ee0 100644 --- a/services/core/jni/com_android_server_SystemServer.cpp +++ b/services/core/jni/com_android_server_SystemServer.cpp @@ -14,6 +14,12 @@ * limitations under the License. */ +#include <dlfcn.h> +#include <pthread.h> + +#include <chrono> +#include <thread> + #include <jni.h> #include <nativehelper/JNIHelp.h> @@ -25,12 +31,17 @@ #include <sensorservicehidl/SensorManager.h> #include <bionic/malloc.h> +#include <bionic/reserved_signals.h> +#include <android-base/properties.h> #include <cutils/properties.h> #include <utils/Log.h> #include <utils/misc.h> #include <utils/AndroidThreads.h> +using android::base::GetIntProperty; +using namespace std::chrono_literals; + namespace android { static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) { @@ -68,7 +79,50 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject / static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* env */, jobject /* clazz */) { - android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0); + android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0); +} + +static int get_current_max_fd() { + // Not actually guaranteed to be the max, but close enough for our purposes. + int fd = open("/dev/null", O_RDONLY | O_CLOEXEC); + LOG_ALWAYS_FATAL_IF(fd == -1, "failed to open /dev/null: %s", strerror(errno)); + close(fd); + return fd; +} + +static const char kFdLeakEnableThresholdProperty[] = "persist.sys.debug.fdtrack_enable_threshold"; +static const char kFdLeakAbortThresholdProperty[] = "persist.sys.debug.fdtrack_abort_threshold"; +static const char kFdLeakCheckIntervalProperty[] = "persist.sys.debug.fdtrack_interval"; + +static void android_server_SystemServer_spawnFdLeakCheckThread(JNIEnv*, jobject) { + std::thread([]() { + pthread_setname_np(pthread_self(), "FdLeakCheckThread"); + bool loaded = false; + while (true) { + const int enable_threshold = GetIntProperty(kFdLeakEnableThresholdProperty, 1024); + const int abort_threshold = GetIntProperty(kFdLeakAbortThresholdProperty, 2048); + const int check_interval = GetIntProperty(kFdLeakCheckIntervalProperty, 120); + int max_fd = get_current_max_fd(); + if (max_fd > enable_threshold && !loaded) { + loaded = true; + ALOGE("fd count above threshold of %d, starting fd backtraces", enable_threshold); + if (dlopen("libfdtrack.so", RTLD_GLOBAL) == nullptr) { + ALOGE("failed to load libfdtrack.so: %s", dlerror()); + } + } else if (max_fd > abort_threshold) { + raise(BIONIC_SIGNAL_FDTRACK); + + // Wait for a bit to allow fdtrack to dump backtraces to logcat. + std::this_thread::sleep_for(5s); + + LOG_ALWAYS_FATAL( + "b/140703823: aborting due to fd leak: check logs for fd " + "backtraces"); + } + + std::this_thread::sleep_for(std::chrono::seconds(check_interval)); + } + }).detach(); } /* @@ -80,6 +134,9 @@ static const JNINativeMethod gMethods[] = { { "startHidlServices", "()V", (void*) android_server_SystemServer_startHidlServices }, { "initZygoteChildHeapProfiling", "()V", (void*) android_server_SystemServer_initZygoteChildHeapProfiling }, + { "spawnFdLeakCheckThread", "()V", + (void*) android_server_SystemServer_spawnFdLeakCheckThread }, + }; int register_android_server_SystemServer(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 d7ea2f53c286..ec3ef7807c3a 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -9553,9 +9553,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public void setDefaultSmsApplication(ComponentName admin, String packageName) { + public void setDefaultSmsApplication(ComponentName admin, String packageName, boolean parent) { Objects.requireNonNull(admin, "ComponentName is null"); - enforceDeviceOwner(admin); + + if (parent) { + ActiveAdmin ap = getActiveAdminForCallerLocked(admin, + DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent); + enforceProfileOwnerOfOrganizationOwnedDevice(ap); + mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage( + packageName, getProfileParentId(mInjector.userHandleGetCallingUserId()))); + } else { + enforceDeviceOwner(admin); + } + mInjector.binderWithCleanCallingIdentity(() -> SmsApplication.setDefaultApplication(packageName, mContext)); } @@ -10778,7 +10788,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // API cannot be used to leak if certain non-system package exists in the person // profile. mInjector.binderWithCleanCallingIdentity(() -> - enforcePackageIsSystemPackage(packageName, hidden, userId)); + enforcePackageIsSystemPackage(packageName, userId)); } result = mInjector.binderWithCleanCallingIdentity(() -> mIPackageManager @@ -10811,7 +10821,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER, parent); // Ensure the package provided is a system package. mInjector.binderWithCleanCallingIdentity(() -> - enforcePackageIsSystemPackage(packageName, false, userId)); + enforcePackageIsSystemPackage(packageName, userId)); } return mInjector.binderWithCleanCallingIdentity( @@ -10819,16 +10829,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void enforcePackageIsSystemPackage(String packageName, boolean hidden, int userId) + private void enforcePackageIsSystemPackage(String packageName, int userId) throws RemoteException { - int flags = PackageManager.MATCH_SYSTEM_ONLY; - // If the package is currently hidden then it is considered uninstalled and - // the MATCH_UNINSTALLED_PACKAGES flag has to be added. - if (!hidden) { - flags |= PackageManager.MATCH_UNINSTALLED_PACKAGES; - } - PackageInfo packageInfo = mIPackageManager.getPackageInfo(packageName, flags, userId); - if (packageInfo == null || !packageInfo.applicationInfo.isSystemApp()) { + if (!isSystemApp(mIPackageManager, packageName, userId)) { throw new IllegalArgumentException( "The provided package is not a system package"); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 4f5c1abae73c..2a6b0294a031 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -72,7 +72,6 @@ import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; import android.util.StatsLog; -import android.view.WindowManager; import android.view.contentcapture.ContentCaptureManager; import com.android.internal.R; @@ -366,6 +365,12 @@ public final class SystemServer { */ private static native void initZygoteChildHeapProfiling(); + + /** + * Spawn a thread that monitors for fd leaks. + */ + private static native void spawnFdLeakCheckThread(); + /** * The main entry point from zygote. */ @@ -500,6 +505,11 @@ public final class SystemServer { initZygoteChildHeapProfiling(); } + // Debug builds - spawn a thread to monitor for fd leaks. + if (Build.IS_DEBUGGABLE) { + spawnFdLeakCheckThread(); + } + // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); @@ -2083,8 +2093,7 @@ public final class SystemServer { // propagate to it. final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY); DisplayMetrics metrics = new DisplayMetrics(); - WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - w.getDefaultDisplay().getMetrics(metrics); + context.getDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); // The system context's theme may be configuration-dependent. diff --git a/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java new file mode 100644 index 000000000000..38ec4ce3e827 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/location/AppForegroundHelperTest.java @@ -0,0 +1,112 @@ +/* + * 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.location; + +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.MockitoAnnotations.initMocks; + +import android.app.ActivityManager; +import android.content.Context; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import java.util.ArrayList; +import java.util.List; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AppForegroundHelperTest { + + private static final long TIMEOUT_MS = 5000; + + @Mock private Context mContext; + @Mock private ActivityManager mActivityManager; + + private List<ActivityManager.OnUidImportanceListener> mListeners = new ArrayList<>(); + + private AppForegroundHelper mHelper; + + @Before + public void setUp() { + initMocks(this); + + doReturn(mActivityManager).when(mContext).getSystemService(ActivityManager.class); + doAnswer(invocation -> { + mListeners.add(invocation.getArgument(0)); + return null; + }).when(mActivityManager).addOnUidImportanceListener(any( + ActivityManager.OnUidImportanceListener.class), eq(IMPORTANCE_FOREGROUND_SERVICE)); + + mHelper = new AppForegroundHelper(mContext); + mHelper.onSystemReady(); + } + + private void setImportance(int uid, int importance) { + doReturn(importance).when(mActivityManager).getUidImportance(uid); + for (ActivityManager.OnUidImportanceListener listener : mListeners) { + listener.onUidImportance(uid, importance); + } + } + + @Test + public void testListeners() { + AppForegroundHelper.AppForegroundListener listener = mock( + AppForegroundHelper.AppForegroundListener.class); + mHelper.addListener(listener); + + setImportance(0, IMPORTANCE_FOREGROUND); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(0, true); + + setImportance(1, IMPORTANCE_FOREGROUND_SERVICE); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(1, true); + + setImportance(2, IMPORTANCE_VISIBLE); + verify(listener, timeout(TIMEOUT_MS)).onAppForegroundChanged(2, false); + } + + @Test + public void testIsAppForeground() { + setImportance(0, IMPORTANCE_FOREGROUND); + assertThat(mHelper.isAppForeground(0)).isEqualTo(true); + + setImportance(0, IMPORTANCE_FOREGROUND_SERVICE); + assertThat(mHelper.isAppForeground(0)).isEqualTo(true); + + setImportance(0, IMPORTANCE_VISIBLE); + assertThat(mHelper.isAppForeground(0)).isEqualTo(false); + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/location/UserInfoStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java index 06fb10257a37..389fdf9b0abc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/UserInfoStoreTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/UserInfoHelperTest.java @@ -57,7 +57,7 @@ import java.util.List; @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) -public class UserInfoStoreTest { +public class UserInfoHelperTest { private static final int USER1_ID = 1; private static final int USER1_MANAGED_ID = 11; @@ -72,7 +72,7 @@ public class UserInfoStoreTest { private StaticMockitoSession mMockingSession; private List<BroadcastReceiver> mBroadcastReceivers = new ArrayList<>(); - private UserInfoStore mStore; + private UserInfoHelper mHelper; @Before public void setUp() { @@ -97,8 +97,8 @@ public class UserInfoStoreTest { doReturn(USER1_ID).when(ActivityManager::getCurrentUser); - mStore = new UserInfoStore(mContext); - mStore.onSystemReady(); + mHelper = new UserInfoHelper(mContext); + mHelper.onSystemReady(); } @After @@ -119,8 +119,9 @@ public class UserInfoStoreTest { @Test public void testListeners() { - UserInfoStore.UserChangedListener listener = mock(UserInfoStore.UserChangedListener.class); - mStore.addListener(listener); + UserInfoHelper.UserChangedListener listener = mock( + UserInfoHelper.UserChangedListener.class); + mHelper.addListener(listener); switchUser(USER1_ID); verify(listener, never()).onUserChanged(anyInt(), anyInt()); @@ -134,44 +135,44 @@ public class UserInfoStoreTest { @Test public void testCurrentUser() { - assertThat(mStore.getCurrentUserId()).isEqualTo(USER1_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER1_ID); switchUser(USER2_ID); - assertThat(mStore.getCurrentUserId()).isEqualTo(USER2_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER2_ID); switchUser(USER1_ID); - assertThat(mStore.getCurrentUserId()).isEqualTo(USER1_ID); + assertThat(mHelper.getCurrentUserId()).isEqualTo(USER1_ID); } @Test public void testIsCurrentUserOrProfile() { - assertThat(mStore.isCurrentUserOrProfile(USER1_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER1_MANAGED_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER2_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_MANAGED_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_MANAGED_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_MANAGED_ID)).isFalse(); switchUser(USER2_ID); - assertThat(mStore.isCurrentUserOrProfile(USER1_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_ID)).isTrue(); - assertThat(mStore.isCurrentUserOrProfile(USER1_MANAGED_ID)).isFalse(); - assertThat(mStore.isCurrentUserOrProfile(USER2_MANAGED_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_ID)).isTrue(); + assertThat(mHelper.isCurrentUserOrProfile(USER1_MANAGED_ID)).isFalse(); + assertThat(mHelper.isCurrentUserOrProfile(USER2_MANAGED_ID)).isTrue(); } @Test public void testGetParentUserId() { - assertThat(mStore.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); - assertThat(mStore.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); switchUser(USER2_ID); - assertThat(mStore.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); - assertThat(mStore.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); - assertThat(mStore.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_ID)).isEqualTo(USER2_ID); + assertThat(mHelper.getParentUserId(USER1_MANAGED_ID)).isEqualTo(USER1_ID); + assertThat(mHelper.getParentUserId(USER2_MANAGED_ID)).isEqualTo(USER2_ID); } } diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 556f6362d872..f99081024494 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -30,6 +30,7 @@ android_test { "services.usage", "guava", "androidx.test.core", + "androidx.test.ext.truth", "androidx.test.runner", "androidx.test.rules", "mockito-target-minus-junit4", diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index b7c900130e39..d2ddff3627b9 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -66,8 +66,6 @@ <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.SUSPEND_APPS"/> <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/> - <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> - <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/> <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/> <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java index bec265e6d62d..156cd6e5826d 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java @@ -421,6 +421,7 @@ public class BiometricServiceTest { public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception { setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); + when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true); invokeAuthenticate(mBiometricService.mImpl, mReceiver1, true /* requireConfirmation */, Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK); @@ -467,6 +468,22 @@ public class BiometricServiceTest { } @Test + public void testAuthenticate_no_Biometrics_noCredential() throws Exception { + setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); + when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false); + when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(false); + + invokeAuthenticate(mBiometricService.mImpl, mReceiver1, + true /* requireConfirmation */, + Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG); + waitForIdle(); + + verify(mReceiver1).onError(anyInt() /* modality */, + eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS)/* error */, + eq(0) /* vendorCode */); + } + + @Test public void testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused() throws Exception { setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); @@ -1216,7 +1233,8 @@ public class BiometricServiceTest { when(mDevicePolicyManager .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1); + invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, + Authenticators.BIOMETRIC_STRONG); waitForIdle(); assertEquals(mBiometricService.mPendingAuthSession.mState, BiometricService.STATE_AUTH_CALLED); @@ -1233,7 +1251,8 @@ public class BiometricServiceTest { when(mDevicePolicyManager .getKeyguardDisabledFeatures(any() /* admin*/, anyInt() /* userHandle */)) .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FACE); - invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1); + invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, + Authenticators.BIOMETRIC_STRONG); waitForIdle(); assertEquals(mBiometricService.mPendingAuthSession.mState, BiometricService.STATE_AUTH_CALLED); @@ -1247,27 +1266,24 @@ public class BiometricServiceTest { public void testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager() throws Exception { setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG); + when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true); when(mDevicePolicyManager .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT); - invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1); + + invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1, + Authenticators.BIOMETRIC_STRONG); waitForIdle(); - assertNotNull(mBiometricService.mCurrentAuthSession); - assertEquals(mBiometricService.mCurrentAuthSession.mState, - BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL); - } + verify(mReceiver1).onError(eq(BiometricAuthenticator.TYPE_NONE), + eq(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(0) /* vendorCode */); - @Test - public void testWorkAuthentication_faceFailsIfDisabledByDevicePolicyManager() throws Exception { - setupAuthForOnly(BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG); - when(mDevicePolicyManager - .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */)) - .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FACE); - invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1); + invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver2, + Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL); waitForIdle(); assertNotNull(mBiometricService.mCurrentAuthSession); assertEquals(mBiometricService.mCurrentAuthSession.mState, BiometricService.STATE_SHOWING_DEVICE_CREDENTIAL); + verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt()); } // Helper methods @@ -1376,33 +1392,35 @@ public class BiometricServiceTest { 0 /* userId */, receiver, TEST_PACKAGE_NAME /* packageName */, - createTestBiometricPromptBundle(requireConfirmation, authenticators)); + createTestBiometricPromptBundle(requireConfirmation, authenticators, + false /* checkDevicePolicy */)); } private static void invokeAuthenticateForWorkApp(IBiometricService.Stub service, - IBiometricServiceReceiver receiver) throws Exception { - final Bundle bundle = new Bundle(); - bundle.putBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, true); - bundle.putBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true); - bundle.putBoolean(BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, true); + IBiometricServiceReceiver receiver, Integer authenticators) throws Exception { service.authenticate( new Binder() /* token */, 0 /* sessionId */, 0 /* userId */, receiver, TEST_PACKAGE_NAME /* packageName */, - bundle); + createTestBiometricPromptBundle(false /* requireConfirmation */, authenticators, + true /* checkDevicePolicy */)); } private static Bundle createTestBiometricPromptBundle( boolean requireConfirmation, - Integer authenticators) { + Integer authenticators, + boolean checkDevicePolicy) { final Bundle bundle = new Bundle(); bundle.putBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION, requireConfirmation); if (authenticators != null) { bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators); } + if (checkDevicePolicy) { + bundle.putBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, true); + } return bundle; } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 422c278a3af7..f7a9e5456156 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -2223,17 +2223,13 @@ public class DevicePolicyManagerTest extends DpmTestBase { String packageName = "com.google.android.test"; - PackageInfo packageInfo = new PackageInfo(); - packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID)) .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0)); - when(getServices().ipackageManager.getPackageInfo(packageName, - PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM)).thenReturn( - packageInfo); - when(getServices().ipackageManager.getPackageInfo(packageName, - PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.MATCH_SYSTEM_ONLY, - UserHandle.USER_SYSTEM)).thenReturn(packageInfo); + when(getServices().ipackageManager.getApplicationInfo(packageName, + PackageManager.MATCH_UNINSTALLED_PACKAGES, UserHandle.USER_SYSTEM)).thenReturn( + applicationInfo); parentDpm.setApplicationHidden(admin1, packageName, true); verify(getServices().ipackageManager).setApplicationHiddenSettingAsUser(packageName, diff --git a/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java b/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java new file mode 100644 index 000000000000..6fafe113d90d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java @@ -0,0 +1,213 @@ +/* + * 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.location; + +import static androidx.test.ext.truth.location.LocationSubject.assertThat; + +import static com.android.internal.location.ProviderRequest.EMPTY_REQUEST; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.location.Criteria; +import android.location.Location; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.location.ProviderProperties; +import com.android.internal.location.ProviderRequest; +import com.android.server.location.test.FakeProvider; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.LinkedList; +import java.util.List; + +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class MockableLocationProviderTest { + + private Object mLock; + private ListenerCapture mListener; + + private AbstractLocationProvider mRealProvider; + private MockProvider mMockProvider; + + private MockableLocationProvider mProvider; + + @Before + public void setUp() { + mLock = new Object(); + mListener = new ListenerCapture(); + + mRealProvider = spy(new FakeProvider()); + mMockProvider = spy(new MockProvider(new ProviderProperties( + false, + false, + false, + false, + true, + true, + true, + Criteria.POWER_LOW, + Criteria.ACCURACY_FINE))); + + mProvider = new MockableLocationProvider(mLock, mListener); + mProvider.setRealProvider(mRealProvider); + } + + @Test + public void testSetProvider() { + assertThat(mProvider.getProvider()).isEqualTo(mRealProvider); + + mProvider.setMockProvider(mMockProvider); + assertThat(mProvider.getProvider()).isEqualTo(mMockProvider); + + mProvider.setMockProvider(null); + assertThat(mProvider.getProvider()).isEqualTo(mRealProvider); + + mProvider.setRealProvider(null); + assertThat(mProvider.getProvider()).isNull(); + } + + @Test + public void testSetRequest() { + assertThat(mProvider.getCurrentRequest()).isEqualTo(EMPTY_REQUEST); + verify(mRealProvider, times(1)).onSetRequest(EMPTY_REQUEST); + + ProviderRequest request = new ProviderRequest.Builder().setInterval(1).build(); + mProvider.setRequest(request); + + assertThat(mProvider.getCurrentRequest()).isEqualTo(request); + verify(mRealProvider, times(1)).onSetRequest(request); + + mProvider.setMockProvider(mMockProvider); + assertThat(mProvider.getCurrentRequest()).isEqualTo(request); + verify(mRealProvider, times(2)).onSetRequest(EMPTY_REQUEST); + verify(mMockProvider, times(1)).onSetRequest(request); + + mProvider.setMockProvider(null); + assertThat(mProvider.getCurrentRequest()).isEqualTo(request); + verify(mMockProvider, times(1)).onSetRequest(EMPTY_REQUEST); + verify(mRealProvider, times(2)).onSetRequest(request); + + mProvider.setRealProvider(null); + assertThat(mProvider.getCurrentRequest()).isEqualTo(request); + verify(mRealProvider, times(3)).onSetRequest(EMPTY_REQUEST); + } + + @Test + public void testRequestSetAllowed() { + mProvider.requestSetAllowed(true); + verify(mRealProvider, times(1)).onRequestSetAllowed(true); + + mProvider.setMockProvider(mMockProvider); + mProvider.requestSetAllowed(true); + verify(mMockProvider, times(1)).onRequestSetAllowed(true); + } + + @Test + public void testSendExtraCommand() { + mProvider.sendExtraCommand(0, 0, "command", null); + verify(mRealProvider, times(1)).onExtraCommand(0, 0, "command", null); + + mProvider.setMockProvider(mMockProvider); + mProvider.sendExtraCommand(0, 0, "command", null); + verify(mMockProvider, times(1)).onExtraCommand(0, 0, "command", null); + } + + @Test + public void testSetState() { + assertThat(mProvider.getState().allowed).isFalse(); + + AbstractLocationProvider.State newState; + + mRealProvider.setAllowed(true); + newState = mListener.getNextNewState(); + assertThat(newState).isNotNull(); + assertThat(newState.allowed).isTrue(); + + mProvider.setMockProvider(mMockProvider); + newState = mListener.getNextNewState(); + assertThat(newState).isNotNull(); + assertThat(newState.allowed).isFalse(); + + mMockProvider.setAllowed(true); + newState = mListener.getNextNewState(); + assertThat(newState).isNotNull(); + assertThat(newState.allowed).isTrue(); + + mRealProvider.setAllowed(false); + assertThat(mListener.getNextNewState()).isNull(); + + mProvider.setMockProvider(null); + newState = mListener.getNextNewState(); + assertThat(newState).isNotNull(); + assertThat(newState.allowed).isFalse(); + } + + @Test + public void testReportLocation() { + Location realLocation = new Location("real"); + Location mockLocation = new Location("mock"); + + mRealProvider.reportLocation(realLocation); + assertThat(mListener.getNextLocation()).isEqualTo(realLocation); + + mProvider.setMockProvider(mMockProvider); + mRealProvider.reportLocation(realLocation); + mMockProvider.reportLocation(mockLocation); + assertThat(mListener.getNextLocation()).isEqualTo(mockLocation); + } + + private class ListenerCapture implements AbstractLocationProvider.Listener { + + private final LinkedList<AbstractLocationProvider.State> mNewStates = new LinkedList<>(); + private final LinkedList<Location> mLocations = new LinkedList<>(); + + @Override + public void onStateChanged(AbstractLocationProvider.State oldState, + AbstractLocationProvider.State newState) { + assertThat(Thread.holdsLock(mLock)).isTrue(); + mNewStates.add(newState); + } + + private AbstractLocationProvider.State getNextNewState() { + return mNewStates.poll(); + } + + @Override + public void onReportLocation(Location location) { + assertThat(Thread.holdsLock(mLock)).isTrue(); + mLocations.add(location); + } + + private Location getNextLocation() { + return mLocations.poll(); + } + + @Override + public void onReportLocation(List<Location> locations) {} + } +} diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java index f262733bb882..f16cf35bfb34 100644 --- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -31,7 +32,6 @@ import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; import android.Manifest; -import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -46,13 +46,15 @@ import android.location.IGnssNavigationMessageListener; import android.location.IGnssStatusListener; import android.location.INetInitiatedListener; import android.location.Location; +import android.location.LocationManagerInternal; import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Message; import android.os.RemoteException; -import com.android.server.LocationManagerService; +import com.android.server.LocalServices; +import com.android.server.location.AppForegroundHelper; import com.android.server.location.GnssBatchingProvider; import com.android.server.location.GnssCapabilitiesProvider; import com.android.server.location.GnssLocationProvider; @@ -63,7 +65,9 @@ import com.android.server.location.GnssNavigationMessageProvider; import com.android.server.location.GnssNavigationMessageProvider.GnssNavigationMessageProviderNative; import com.android.server.location.GnssStatusListenerHelper; import com.android.server.location.LocationUsageLogger; +import com.android.server.location.SettingsHelper; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.AdditionalMatchers; @@ -93,18 +97,20 @@ public class GnssManagerServiceTest { @Mock private GnssMeasurementCorrectionsProvider mMockGnssMeasurementCorrectionsProvider; @Mock - private INetInitiatedListener mMockNetInitiatedListener; + private INetInitiatedListener mNetInitiatedListener; private GnssMeasurementsProvider mTestGnssMeasurementsProvider; private GnssStatusListenerHelper mTestGnssStatusProvider; private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider; // Managers and services @Mock - private AppOpsManager mMockAppOpsManager; + private AppOpsManager mAppOpsManager; @Mock - private ActivityManager mMockActivityManager; + private SettingsHelper mSettingsHelper; @Mock - private LocationManagerService mMockLocationManagerService; + private AppForegroundHelper mAppForegroundHelper; + @Mock + private LocationManagerInternal mLocationManagerInternal; // Context and handler @Mock @@ -113,25 +119,23 @@ public class GnssManagerServiceTest { private Context mMockContext; // Class under test - private com.android.server.location.gnss.GnssManagerService mGnssManagerService; + private GnssManagerService mGnssManagerService; @Before public void setUp() { MockitoAnnotations.initMocks(this); GnssLocationProvider.setIsSupportedForTest(true); - // Set up mock context when(mMockContext.getSystemServiceName(AppOpsManager.class)).thenReturn( Context.APP_OPS_SERVICE); - when(mMockContext.getSystemServiceName(ActivityManager.class)).thenReturn( - Context.ACTIVITY_SERVICE); when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn( - mMockAppOpsManager); - when(mMockContext.getSystemService( - eq(Context.ACTIVITY_SERVICE))).thenReturn( - mMockActivityManager); + mAppOpsManager); enableLocationPermissions(); + when(mAppForegroundHelper.isAppForeground(anyInt())).thenReturn(true); + + LocalServices.addService(LocationManagerInternal.class, mLocationManagerInternal); + // Mock Handler will execute posted runnables immediately when(mMockHandler.sendMessageAtTime(any(Message.class), anyLong())).thenAnswer( (InvocationOnMock invocation) -> { @@ -164,15 +168,22 @@ public class GnssManagerServiceTest { when(mMockGnssLocationProvider.getGnssNavigationMessageProvider()).thenReturn( mTestGnssNavigationMessageProvider); when(mMockGnssLocationProvider.getNetInitiatedListener()).thenReturn( - mMockNetInitiatedListener); + mNetInitiatedListener); // Setup GnssBatching provider when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true); when(mMockGnssBatchingProvider.stop()).thenReturn(true); // Create GnssManagerService - mGnssManagerService = new GnssManagerService(mMockLocationManagerService, mMockContext, - mMockGnssLocationProvider, new LocationUsageLogger()); + mGnssManagerService = new GnssManagerService(mMockContext, mSettingsHelper, + mAppForegroundHelper, new LocationUsageLogger(), + mMockGnssLocationProvider); + mGnssManagerService.onSystemReady(); + } + + @After + public void tearDown() { + LocalServices.removeServiceForTest(LocationManagerInternal.class); } private void overrideAsBinder(IInterface mockListener) { @@ -225,7 +236,7 @@ public class GnssManagerServiceTest { PackageManager.PERMISSION_GRANTED); // AppOpsManager will return true if OP_FINE_LOCATION is checked - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer( + when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenAnswer( (InvocationOnMock invocation) -> { int code = (int) (invocation.getArguments()[0]); if (code == AppOpsManager.OP_FINE_LOCATION) { @@ -237,11 +248,11 @@ public class GnssManagerServiceTest { private void disableLocationPermissions() { Mockito.doThrow(new SecurityException()).when( - mMockContext).enforceCallingPermission(anyString(), anyString()); + mMockContext).enforceCallingPermission(anyString(), nullable(String.class)); Mockito.doThrow(new SecurityException()).when( mMockContext).checkPermission(anyString(), anyInt(), anyInt()); - when(mMockAppOpsManager.checkOp(anyInt(), anyInt(), + when(mAppOpsManager.checkOp(anyInt(), anyInt(), anyString())).thenReturn(AppOpsManager.MODE_ERRORED); } @@ -733,14 +744,12 @@ public class GnssManagerServiceTest { @Test public void sendNiResponseWithPermissionsTest() throws RemoteException { - when(mMockNetInitiatedListener.sendNiResponse(anyInt(), anyInt())).thenReturn(true); - int notifId = 0; int userResponse = 0; enableLocationPermissions(); - assertThat(mGnssManagerService.sendNiResponse(notifId, userResponse)).isEqualTo(true); + mGnssManagerService.sendNiResponse(notifId, userResponse); - verify(mMockNetInitiatedListener, times(1)).sendNiResponse(notifId, userResponse); + verify(mNetInitiatedListener, times(1)).sendNiResponse(notifId, userResponse); } } diff --git a/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java b/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java new file mode 100644 index 000000000000..762080fe5745 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java @@ -0,0 +1,45 @@ +/* + * 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.location.test; + +import android.os.Bundle; + +import com.android.internal.location.ProviderRequest; +import com.android.server.location.AbstractLocationProvider; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.Collections; + +public class FakeProvider extends AbstractLocationProvider { + + public FakeProvider() { + super(Runnable::run, Collections.emptySet()); + } + + @Override + protected void onSetRequest(ProviderRequest request) {} + + @Override + protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {} + + @Override + protected void onRequestSetAllowed(boolean allowed) {} + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {} +} diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 2469cec5766e..118c540a4131 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -336,9 +336,6 @@ public final class UserManagerTest { assertThat(userInfo).isNotNull(); final int userId = userInfo.id; - UserManager userManagerForUser = (UserManager) mContext.createPackageContextAsUser( - "android", 0, asHandle(userId)).getSystemService(Context.USER_SERVICE); - assertThat(mUserManager.hasBadge(userId)).isEqualTo(userTypeDetails.hasBadge()); assertThat(mUserManager.getUserIconBadgeResId(userId)) .isEqualTo(userTypeDetails.getIconBadge()); @@ -346,17 +343,18 @@ public final class UserManagerTest { .isEqualTo(userTypeDetails.getBadgePlain()); assertThat(mUserManager.getUserBadgeNoBackgroundResId(userId)) .isEqualTo(userTypeDetails.getBadgeNoBackground()); - assertThat(mUserManager.isUserOfType(asHandle(userId), userTypeDetails.getName())) - .isTrue(); - assertThat(userManagerForUser.isProfile()).isEqualTo(userTypeDetails.isProfile()); - assertThat(userManagerForUser.isUserOfType(asHandle(userId), userTypeDetails.getName())) - .isTrue(); final int badgeIndex = userInfo.profileBadge; assertThat(mUserManager.getUserBadgeColor(userId)).isEqualTo( Resources.getSystem().getColor(userTypeDetails.getBadgeColor(badgeIndex), null)); assertThat(mUserManager.getBadgedLabelForUser("Test", asHandle(userId))).isEqualTo( Resources.getSystem().getString(userTypeDetails.getBadgeLabel(badgeIndex), "Test")); + + // Test @UserHandleAware methods + final UserManager userManagerForUser = UserManager.get(mContext.createPackageContextAsUser( + "android", 0, asHandle(userId))); + assertThat(userManagerForUser.isUserOfType(userTypeDetails.getName())).isTrue(); + assertThat(userManagerForUser.isProfile()).isEqualTo(userTypeDetails.isProfile()); } // Make sure only max managed profiles can be created diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java index f871203728c0..3ceaac207680 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; import android.content.pm.VersionedPackage; import android.content.rollback.PackageRollbackInfo; @@ -34,12 +35,15 @@ import android.content.rollback.PackageRollbackInfo.RestoreInfo; import android.util.IntArray; import android.util.SparseLongArray; +import com.android.server.pm.ApexManager; import com.android.server.pm.Installer; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.InOrder; +import org.mockito.Mock; import org.mockito.Mockito; import java.io.File; @@ -48,10 +52,17 @@ import java.util.ArrayList; @RunWith(JUnit4.class) public class AppDataRollbackHelperTest { + @Mock private ApexManager mApexManager; + + @Before + public void setUp() { + initMocks(this); + } + @Test public void testSnapshotAppData() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer)); + AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer, mApexManager)); // All users are unlocked so we should snapshot data for them. doReturn(true).when(helper).isUserCredentialLocked(eq(10)); @@ -114,7 +125,7 @@ public class AppDataRollbackHelperTest { @Test public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer)); + AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer, mApexManager)); PackageRollbackInfo info = createPackageRollbackInfo("com.foo"); IntArray pendingBackups = info.getPendingBackups(); @@ -139,7 +150,7 @@ public class AppDataRollbackHelperTest { @Test public void testRestoreAppDataSnapshot_availableBackupForLockedUser() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer)); + AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer, mApexManager)); doReturn(true).when(helper).isUserCredentialLocked(eq(10)); PackageRollbackInfo info = createPackageRollbackInfo("com.foo"); @@ -163,7 +174,7 @@ public class AppDataRollbackHelperTest { @Test public void testRestoreAppDataSnapshot_availableBackupForUnlockedUser() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer)); + AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer, mApexManager)); doReturn(false).when(helper).isUserCredentialLocked(eq(10)); PackageRollbackInfo info = createPackageRollbackInfo("com.foo"); @@ -184,7 +195,7 @@ public class AppDataRollbackHelperTest { @Test public void destroyAppData() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = new AppDataRollbackHelper(installer); + AppDataRollbackHelper helper = new AppDataRollbackHelper(installer, mApexManager); PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar"); info.putCeSnapshotInode(11, 239L); @@ -206,7 +217,7 @@ public class AppDataRollbackHelperTest { @Test public void commitPendingBackupAndRestoreForUser() throws Exception { Installer installer = mock(Installer.class); - AppDataRollbackHelper helper = new AppDataRollbackHelper(installer); + AppDataRollbackHelper helper = new AppDataRollbackHelper(installer, mApexManager); when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(53L); diff --git a/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java new file mode 100644 index 000000000000..61117f18445b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java @@ -0,0 +1,119 @@ +/* + * 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.rollback; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.content.pm.VersionedPackage; +import android.os.Bundle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class WatchdogRollbackLoggerTest { + + private static final VersionedPackage sTestPackageV1 = new VersionedPackage("test.package", 1); + private Context mMockContext = mock(Context.class); + private PackageManager mMockPm; + private ApplicationInfo mApplicationInfo; + private PackageInfo mPackageInfo; + + private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT"; + + @Before + public void setUp() { + mApplicationInfo = new ApplicationInfo(); + mMockPm = mock(PackageManager.class); + when(mMockContext.getPackageManager()).thenReturn(mMockPm); + PackageInstaller mockPi = mock(PackageInstaller.class); + when(mMockPm.getPackageInstaller()).thenReturn(mockPi); + PackageInstaller.SessionInfo mockSessionInfo = mock(PackageInstaller.SessionInfo.class); + when(mockPi.getSessionInfo(anyInt())).thenReturn(mockSessionInfo); + mPackageInfo = new PackageInfo(); + } + + /** + * Ensures that the original package is returned if the application info has no metadata. + */ + @Test + public void testLogPackageHasNoMetadata() throws Exception { + when(mMockPm.getApplicationInfo(anyString(), anyInt())).thenReturn(mApplicationInfo); + VersionedPackage logPackage = WatchdogRollbackLogger.getLogPackage(mMockContext, + sTestPackageV1); + assertThat(logPackage).isEqualTo(sTestPackageV1); + } + + /** + * Ensures the original package is returned if the application info does not contain a logging + * parent key. + */ + @Test + public void testLogPackageParentKeyIsNull() throws Exception { + when(mMockPm.getApplicationInfo(anyString(), anyInt())).thenReturn(mApplicationInfo); + Bundle bundle = new Bundle(); + bundle.putString(LOGGING_PARENT_KEY, null); + VersionedPackage logPackage = WatchdogRollbackLogger.getLogPackage(mMockContext, + sTestPackageV1); + assertThat(logPackage).isEqualTo(sTestPackageV1); + } + + /** + * Ensures that the logging parent is returned as the logging package, if it exists. + */ + @Test + public void testLogPackageHasParentKey() throws Exception { + Bundle bundle = new Bundle(); + bundle.putString(LOGGING_PARENT_KEY, "logging.parent"); + mApplicationInfo.metaData = bundle; + mPackageInfo.setLongVersionCode(12345L); + when(mMockPm.getApplicationInfo(anyString(), anyInt())).thenReturn(mApplicationInfo); + when(mMockPm.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo); + VersionedPackage logPackage = WatchdogRollbackLogger.getLogPackage(mMockContext, + sTestPackageV1); + VersionedPackage expectedLogPackage = new VersionedPackage("logging.parent", 12345); + assertThat(logPackage).isEqualTo(expectedLogPackage); + } + + /** + * Ensures that the original package is returned if Package Manager does not know about the + * logging parent. + */ + @Test + public void testLogPackageNameNotFound() throws Exception { + Bundle bundle = new Bundle(); + bundle.putString("android.content.pm.LOGGING_PARENT", "logging.parent"); + mApplicationInfo.metaData = bundle; + when(mMockPm.getPackageInfo(anyString(), anyInt())).thenThrow( + new PackageManager.NameNotFoundException()); + VersionedPackage logPackage = WatchdogRollbackLogger.getLogPackage(mMockContext, + sTestPackageV1); + assertThat(logPackage).isEqualTo(sTestPackageV1); + } +} diff --git a/core/java/com/android/internal/logging/testing/InstanceIdSequenceFake.java b/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java index 0fd40b9ceb06..1629ef00b65a 100644 --- a/core/java/com/android/internal/logging/testing/InstanceIdSequenceFake.java +++ b/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java @@ -14,12 +14,7 @@ * limitations under the License. */ -package com.android.internal.logging.testing; - -import android.annotation.SuppressLint; - -import com.android.internal.logging.InstanceId; -import com.android.internal.logging.InstanceIdSequence; +package com.android.internal.logging; /** * A fake implementation of InstanceIdSequence that returns 0, 1, 2, ... @@ -30,27 +25,15 @@ public class InstanceIdSequenceFake extends InstanceIdSequence { super(instanceIdMax); } - /** - * Extend InstanceId to add a constructor we can call, strictly for testing purposes. - * Public so that tests can check whether the InstanceIds they see are fake. - */ - public static class InstanceIdFake extends InstanceId { - @SuppressLint("VisibleForTests") // This is test infrastructure, which ought to count - InstanceIdFake(int id) { - super(id); - } - } - private int mNextId = 0; @Override public InstanceId newInstanceId() { synchronized (this) { - ++mNextId; if (mNextId >= mInstanceIdMax) { mNextId = 0; } - return new InstanceIdFake(mNextId); + return newInstanceIdInternal(mNextId++); } } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 651ad40a4781..f029bc80480a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -72,6 +72,8 @@ import android.view.accessibility.IAccessibilityManagerClient; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.logging.InstanceIdSequence; +import com.android.internal.logging.InstanceIdSequenceFake; import com.android.internal.util.IntPair; import com.android.server.UiServiceTestCase; import com.android.server.lights.LogicalLight; @@ -99,6 +101,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { @Mock IAccessibilityManager mAccessibilityService; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); + private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( + 1 << 30); private NotificationManagerService mService; private String mPkg = "com.android.server.notification"; @@ -149,7 +153,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt()); assertTrue(accessibilityManager.isEnabled()); - mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger)); + mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger, + mNotificationInstanceIdSequence)); mService.setAudioManager(mAudioManager); mService.setVibrator(mVibrator); mService.setSystemReady(true); 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 768b4721a1ee..2cf5eaefcc58 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -148,6 +148,8 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.R; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; +import com.android.internal.logging.InstanceIdSequence; +import com.android.internal.logging.InstanceIdSequenceFake; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.util.FastXmlSerializer; import com.android.server.LocalServices; @@ -257,7 +259,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock NotificationHistoryManager mHistoryManager; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); - + private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( + 1 << 30); // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { @@ -267,8 +270,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Nullable NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback; - TestableNotificationManagerService(Context context, NotificationRecordLogger logger) { - super(context, logger); + TestableNotificationManagerService(Context context, NotificationRecordLogger logger, + InstanceIdSequence notificationInstanceIdSequence) { + super(context, logger, notificationInstanceIdSequence); } @Override @@ -355,7 +359,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); - mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger); + mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, + mNotificationInstanceIdSequence); // Use this testable looper. mTestableLooper = TestableLooper.get(this); @@ -1135,6 +1140,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(PKG, call.r.sbn.getPackageName()); assertEquals(0, call.r.sbn.getId()); assertEquals(tag, call.r.sbn.getTag()); + assertNotNull(call.r.sbn.getInstanceId()); + assertEquals(0, call.r.sbn.getInstanceId().getId()); } @Test @@ -1151,14 +1158,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0); waitForIdle(); assertEquals(2, mNotificationRecordLogger.getCalls().size()); + assertTrue(mNotificationRecordLogger.get(0).shouldLog()); assertEquals( NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED, mNotificationRecordLogger.get(0).getUiEvent()); + assertEquals(0, mNotificationRecordLogger.get(0).r.sbn.getInstanceId().getId()); + + assertTrue(mNotificationRecordLogger.get(1).shouldLog()); assertEquals( NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_UPDATED, mNotificationRecordLogger.get(1).getUiEvent()); - assertTrue(mNotificationRecordLogger.get(1).shouldLog()); + // Instance ID doesn't change on update of an active notification + assertEquals(0, mNotificationRecordLogger.get(1).r.sbn.getInstanceId().getId()); } @Test @@ -1175,6 +1187,34 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testEnqueueNotificationWithTag_LogsAgainAfterCancel() throws Exception { + final String tag = "testEnqueueNotificationWithTag_LogsAgainAfterCancel"; + Notification notification = new Notification.Builder(mContext, + mTestNotificationChannel.getId()) + .setSmallIcon(android.R.drawable.sym_def_app_icon).build(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); + waitForIdle(); + mBinderService.cancelNotificationWithTag(PKG, PKG, tag, 0, 0); + waitForIdle(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0); + waitForIdle(); + assertEquals(2, mNotificationRecordLogger.getCalls().size()); + + assertTrue(mNotificationRecordLogger.get(0).shouldLog()); + assertEquals( + NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED, + mNotificationRecordLogger.get(0).getUiEvent()); + assertEquals(0, mNotificationRecordLogger.get(0).r.sbn.getInstanceId().getId()); + + assertTrue(mNotificationRecordLogger.get(1).shouldLog()); + assertEquals( + NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED, + mNotificationRecordLogger.get(1).getUiEvent()); + // New instance ID because notification was canceled before re-post + assertEquals(1, mNotificationRecordLogger.get(1).r.sbn.getInstanceId().getId()); + } + + @Test public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCancelNotificationImmediatelyAfterEnqueue", 0, @@ -2309,7 +2349,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testHasCompanionDevice_noService() { - mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger); + mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, + mNotificationInstanceIdSequence); assertFalse(mService.hasCompanionDevice(mListener)); } @@ -4679,8 +4720,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } // cross user, with permission, no problem - TestablePermissions perms = mContext.getTestablePermissions(); - perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + enableInteractAcrossUsers(); mBinderService.canNotifyAsPackage("src", "target", mContext.getUserId() + 1); } @@ -4698,8 +4738,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } // cross user, with permission, no problem - TestablePermissions perms = mContext.getTestablePermissions(); - perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + enableInteractAcrossUsers(); mBinderService.getNotificationChannels("src", "target", mContext.getUserId() + 1); } @@ -5317,8 +5356,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } // cross user, with permission, no problem - TestablePermissions perms = mContext.getTestablePermissions(); - perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + enableInteractAcrossUsers(); mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid + UserHandle.PER_USER_RANGE); } @@ -5334,12 +5372,16 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } // cross user, with permission, no problem - TestablePermissions perms = mContext.getTestablePermissions(); - perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + enableInteractAcrossUsers(); mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(), mUid + UserHandle.PER_USER_RANGE); } + private void enableInteractAcrossUsers() { + TestablePermissions perms = mContext.getTestablePermissions(); + perms.setPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, PERMISSION_GRANTED); + } + @Test public void testNotificationBubbleChanged_false() throws Exception { // Bubbles are allowed! diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java index 11972fd6a8dc..5c1487f0fdf6 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java @@ -23,7 +23,7 @@ import java.util.List; * Fake implementation of NotificationRecordLogger, for testing. */ class NotificationRecordLoggerFake implements NotificationRecordLogger { - class CallRecord extends NotificationRecordPair { + static class CallRecord extends NotificationRecordPair { public int position, buzzBeepBlink; CallRecord(NotificationRecord r, NotificationRecord old, int position, int buzzBeepBlink) { @@ -35,7 +35,7 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger { return shouldLog(buzzBeepBlink); } } - List<CallRecord> mCalls = new ArrayList<CallRecord>(); + private List<CallRecord> mCalls = new ArrayList<CallRecord>(); List<CallRecord> getCalls() { return mCalls; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java index e18c8919b645..64a980484539 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java @@ -54,6 +54,8 @@ import android.util.ArraySet; import android.util.AtomicFile; import android.util.Pair; +import com.android.internal.logging.InstanceIdSequence; +import com.android.internal.logging.InstanceIdSequenceFake; import com.android.server.LocalServices; import com.android.server.UiServiceTestCase; import com.android.server.lights.LightsManager; @@ -92,12 +94,15 @@ public class RoleObserverTest extends UiServiceTestCase { @Mock private RoleManager mRoleManager; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); - + private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( + 1 << 30); private List<UserInfo> mUsers; private static class TestableNotificationManagerService extends NotificationManagerService { - TestableNotificationManagerService(Context context, NotificationRecordLogger logger) { - super(context, logger); + TestableNotificationManagerService(Context context, + NotificationRecordLogger logger, + InstanceIdSequence notificationInstanceIdSequence) { + super(context, logger, notificationInstanceIdSequence); } @Override @@ -120,7 +125,8 @@ public class RoleObserverTest extends UiServiceTestCase { mUsers.add(new UserInfo(10, "second", 0)); when(mUm.getUsers()).thenReturn(mUsers); - mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger); + mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, + mNotificationInstanceIdSequence); mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor); try { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index c3bead7162e6..e71225579989 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -119,18 +119,6 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNull(controls); } - @Test - public void testControlsForDispatch_keyguard() { - addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); - addWindow(TYPE_NAVIGATION_BAR, "navBar"); - mockKeyguardShowing(); - - final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); - // The app must not control the top bar. - assertNotNull(controls); - assertEquals(1, controls.length); - } - // TODO: adjust this test if we pretend to the app that it's still able to control it. @Test public void testControlsForDispatch_forceStatusBarVisible() { @@ -159,6 +147,21 @@ public class InsetsPolicyTest extends WindowTestsBase { } @Test + public void testControlsForDispatch_statusBarForceShowNavigation_butFocusedAnyways() { + WindowState notifShade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); + notifShade.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + addWindow(TYPE_NAVIGATION_BAR, "navBar"); + + mDisplayContent.getInsetsPolicy().updateBarControlTarget(notifShade); + InsetsSourceControl[] controls + = mDisplayContent.getInsetsStateController().getControlsForDispatch(notifShade); + + // The app controls the navigation bar. + assertNotNull(controls); + assertEquals(1, controls.length); + } + + @Test public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() { addWindow(TYPE_STATUS_BAR, "statusBar") .getControllableInsetProvider().getSource().setVisible(false); @@ -260,10 +263,4 @@ public class InsetsPolicyTest extends WindowTestsBase { mDisplayContent.getInsetsPolicy().updateBarControlTarget(win); return mDisplayContent.getInsetsStateController().getControlsForDispatch(win); } - - private void mockKeyguardShowing() { - final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); - spyOn(displayPolicy); - doReturn(true).when(displayPolicy).isKeyguardShowing(); - } } diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java index d819b1ada659..7ffdd7cdceb6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java @@ -57,7 +57,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); statusBar.getFrameLw().set(0, 0, 500, 100); statusBar.mHasSurface = true; - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); mProvider.onPostLayout(); assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), @@ -74,7 +74,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { ime.getGivenContentInsetsLw().set(0, 0, 0, 60); ime.getGivenVisibleInsetsLw().set(0, 0, 0, 75); ime.mHasSurface = true; - mProvider.setWindow(ime, null); + mProvider.setWindow(ime, null, null); mProvider.onPostLayout(); assertEquals(new Rect(0, 0, 500, 40), mProvider.getSource().getFrame()); assertEquals(new Rect(0, 0, 500, 25), mProvider.getSource().getVisibleFrame()); @@ -89,7 +89,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { public void testPostLayout_invisible() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); statusBar.getFrameLw().set(0, 0, 500, 100); - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); mProvider.onPostLayout(); assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); @@ -102,7 +102,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { mProvider.setWindow(statusBar, (displayFrames, windowState, rect) -> { rect.set(10, 10, 20, 20); - }); + }, null); mProvider.onPostLayout(); assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame()); } @@ -112,7 +112,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); statusBar.getFrameLw().set(0, 0, 500, 100); - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); mProvider.updateControlForTarget(target, false /* force */); assertNotNull(mProvider.getControl(target)); mProvider.updateControlForTarget(null, false /* force */); @@ -124,7 +124,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); statusBar.getFrameLw().set(0, 0, 500, 100); - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); mProvider.updateControlForFakeTarget(target); assertNotNull(mProvider.getControl(target)); assertNull(mProvider.getControl(target).getLeash()); @@ -137,7 +137,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); statusBar.getFrameLw().set(0, 0, 500, 100); - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); mProvider.updateControlForTarget(target, false /* force */); InsetsState state = new InsetsState(); state.getSource(ITYPE_STATUS_BAR).setVisible(false); @@ -150,7 +150,7 @@ public class InsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); statusBar.getFrameLw().set(0, 0, 500, 100); - mProvider.setWindow(statusBar, null); + mProvider.setWindow(statusBar, null, null); InsetsState state = new InsetsState(); state.getSource(ITYPE_STATUS_BAR).setVisible(false); mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR)); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index d13baeccb68a..39cdd2cb907e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -21,26 +21,26 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.test.InsetsModeSession; -import androidx.test.filters.FlakyTest; -import androidx.test.filters.SmallTest; - import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; +import androidx.test.filters.FlakyTest; +import androidx.test.filters.SmallTest; + @SmallTest @FlakyTest(detail = "Promote to pre-submit once confirmed stable.") @Presubmit @@ -65,7 +65,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testStripForDispatch_notOwn() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null); + getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR)); assertNotNull(getController().getInsetsForDispatch(app).getSource(ITYPE_STATUS_BAR)); } @@ -74,7 +74,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testStripForDispatch_own() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR) - .setWindow(statusBar, null); + .setWindow(statusBar, null, null); statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR)); final InsetsState state = getController().getInsetsForDispatch(statusBar); for (int i = state.getSourcesCount() - 1; i >= 0; i--) { @@ -88,19 +88,36 @@ public class InsetsStateControllerTest extends WindowTestsBase { final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar"); final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null); - getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null); - getController().getSourceProvider(ITYPE_IME).setWindow(ime, null); + getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); + getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null); + getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null); assertEquals(0, getController().getInsetsForDispatch(navBar).getSourcesCount()); } @Test + public void testImeForDispatch() { + final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); + final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime"); + InsetsSourceProvider statusBarProvider = + getController().getSourceProvider(ITYPE_STATUS_BAR); + statusBarProvider.setWindow(statusBar, null, ((displayFrames, windowState, rect) -> + rect.set(0, 1, 2, 3))); + getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null); + statusBar.setControllableInsetProvider(statusBarProvider); + + statusBarProvider.onPostLayout(); + + final InsetsState state = getController().getInsetsForDispatch(ime); + assertEquals(new Rect(0, 1, 2, 3), state.getSource(ITYPE_STATUS_BAR).getFrame()); + } + + @Test public void testBarControllingWinChanged() { final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar"); final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null); - getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null); + getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); + getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null); getController().onBarControlTargetChanged(app, null, app, null); InsetsSourceControl[] controls = getController().getControlsForDispatch(app); assertEquals(2, controls.length); @@ -110,7 +127,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testControlRevoked() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null); + getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); getController().onBarControlTargetChanged(app, null, null, null); assertNotNull(getController().getControlsForDispatch(app)); getController().onBarControlTargetChanged(null, null, null, null); @@ -122,7 +139,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { public void testControlRevoked_animation() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); - getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null); + getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null); getController().onBarControlTargetChanged(app, null, null, null); assertNotNull(getController().getControlsForDispatch(app)); statusBar.cancelAnimation(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index c9fd79fb4e39..9e80cf223271 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -16,9 +16,9 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; @@ -63,20 +63,24 @@ import org.junit.runner.RunWith; @Presubmit @RunWith(WindowTestRunner.class) public class TaskOrganizerTests extends WindowTestsBase { - private ITaskOrganizer makeAndRegisterMockOrganizer() { + private ITaskOrganizer registerMockOrganizer(int windowingMode) { final ITaskOrganizer organizer = mock(ITaskOrganizer.class); when(organizer.asBinder()).thenReturn(new Binder()); - mWm.mAtmService.registerTaskOrganizer(organizer, WINDOWING_MODE_PINNED); + mWm.mAtmService.registerTaskOrganizer(organizer, windowingMode); return organizer; } + private ITaskOrganizer registerMockOrganizer() { + return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + } + @Test public void testAppearVanish() throws RemoteException { final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stack, 0 /* userId */); - final ITaskOrganizer organizer = makeAndRegisterMockOrganizer(); + final ITaskOrganizer organizer = registerMockOrganizer(); task.setTaskOrganizer(organizer); verify(organizer).taskAppeared(any(), any()); @@ -89,8 +93,8 @@ public class TaskOrganizerTests extends WindowTestsBase { public void testSwapOrganizer() throws RemoteException { final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stack, 0 /* userId */); - final ITaskOrganizer organizer = makeAndRegisterMockOrganizer(); - final ITaskOrganizer organizer2 = makeAndRegisterMockOrganizer(); + final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); task.setTaskOrganizer(organizer); verify(organizer).taskAppeared(any(), any()); @@ -100,10 +104,24 @@ public class TaskOrganizerTests extends WindowTestsBase { } @Test + public void testSwapWindowingModes() throws RemoteException { + final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); + final Task task = createTaskInStack(stack, 0 /* userId */); + final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); + final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED); + + stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + verify(organizer).taskAppeared(any(), any()); + stack.setWindowingMode(WINDOWING_MODE_PINNED); + verify(organizer).taskVanished(any()); + verify(organizer2).taskAppeared(any(), any()); + } + + @Test public void testClearOrganizer() throws RemoteException { final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stack, 0 /* userId */); - final ITaskOrganizer organizer = makeAndRegisterMockOrganizer(); + final ITaskOrganizer organizer = registerMockOrganizer(); stack.setTaskOrganizer(organizer); verify(organizer).taskAppeared(any(), any()); @@ -116,7 +134,7 @@ public class TaskOrganizerTests extends WindowTestsBase { @Test public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException { - final ITaskOrganizer organizer = makeAndRegisterMockOrganizer(); + final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED); final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(stack, 0 /* userId */); 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 186ff6b1515b..2c68cc7a19bf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -425,7 +425,7 @@ public class WindowStateTests extends WindowTestsBase { statusBar.mHasSurface = true; assertTrue(statusBar.isVisible()); mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR) - .setWindow(statusBar, null /* frameProvider */); + .setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */); mDisplayContent.getInsetsStateController().onBarControlTargetChanged( app, null /* fakeTopControlling */, app, null /* fakeNavControlling */); final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR); 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 20eab5a45ff1..8e362ae4c59a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -110,7 +110,7 @@ class WindowTestsBase extends SystemServiceTestsBase { beforeCreateDisplay(); context.getDisplay().getDisplayInfo(mDisplayInfo); - mDisplayContent = createNewDisplay(); + mDisplayContent = createNewDisplay(true /* supportIme */); // Set-up some common windows. mCommonWindows = new HashSet<>(); @@ -349,16 +349,29 @@ class WindowTestsBase extends SystemServiceTestsBase { return WindowTestUtils.createTaskInStack(mWm, stack, userId); } - /** Creates a {@link DisplayContent} and adds it to the system. */ + /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */ DisplayContent createNewDisplay() { - return createNewDisplay(mDisplayInfo); + return createNewDisplay(true /* supportIme */); } /** Creates a {@link DisplayContent} and adds it to the system. */ + private DisplayContent createNewDisplay(boolean supportIme) { + return createNewDisplay(mDisplayInfo, supportIme); + } + + /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */ DisplayContent createNewDisplay(DisplayInfo info) { + return createNewDisplay(info, true /* supportIme */); + } + + /** Creates a {@link DisplayContent} and adds it to the system. */ + private DisplayContent createNewDisplay(DisplayInfo info, boolean supportIme) { final DisplayContent display = new TestDisplayContent.Builder(mWm.mAtmService, info).build(); - return display.mDisplayContent; + final DisplayContent dc = display.mDisplayContent; + // this display can show IME. + dc.mWmService.mDisplayWindowSettings.setShouldShowImeLocked(dc, supportIme); + return dc; } /** @@ -372,7 +385,7 @@ class WindowTestsBase extends SystemServiceTestsBase { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.copyFrom(mDisplayInfo); displayInfo.state = displayState; - return createNewDisplay(displayInfo); + return createNewDisplay(displayInfo, true /* supportIme */); } /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */ @@ -389,7 +402,7 @@ class WindowTestsBase extends SystemServiceTestsBase { displayInfo.copyFrom(mDisplayInfo); displayInfo.type = Display.TYPE_VIRTUAL; displayInfo.ownerUid = SYSTEM_UID; - return createNewDisplay(displayInfo); + return createNewDisplay(displayInfo, false /* supportIme */); } /** Sets the default minimum task size to 1 so that tests can use small task sizes */ diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING index 7b53d09fdbef..523d5f95c6f3 100644 --- a/services/usage/java/com/android/server/usage/TEST_MAPPING +++ b/services/usage/java/com/android/server/usage/TEST_MAPPING @@ -28,6 +28,14 @@ "include-filter": "android.app.usage.cts.UsageStatsTest" } ] + }, + { + "name": "CtsShortcutManagerTestCases", + "options": [ + { + "include-filter": "android.content.pm.cts.shortcutmanager.ShortcutManagerUsageTest" + } + ] } ] } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 9a18f8cd3a46..14852d0f4161 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -60,6 +60,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.content.pm.ShortcutServiceInternal; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Binder; @@ -156,6 +157,8 @@ public class UsageStatsService extends SystemService implements PackageManagerInternal mPackageManagerInternal; // Do not use directly. Call getDpmInternal() instead DevicePolicyManagerInternal mDpmInternal; + // Do not use directly. Call getShortcutServiceInternal() instead + ShortcutServiceInternal mShortcutServiceInternal; private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private final SparseBooleanArray mUserUnlockedStates = new SparseBooleanArray(); @@ -267,6 +270,8 @@ public class UsageStatsService extends SystemService implements if (phase == PHASE_SYSTEM_SERVICES_READY) { // initialize mDpmInternal getDpmInternal(); + // initialize mShortcutServiceInternal + getShortcutServiceInternal(); if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) { try { @@ -400,6 +405,13 @@ public class UsageStatsService extends SystemService implements return mDpmInternal; } + private ShortcutServiceInternal getShortcutServiceInternal() { + if (mShortcutServiceInternal == null) { + mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class); + } + return mShortcutServiceInternal; + } + private void readUsageSourceSetting() { synchronized (mLock) { mUsageSource = Settings.Global.getInt(getContext().getContentResolver(), @@ -469,6 +481,16 @@ public class UsageStatsService extends SystemService implements return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId); } + private boolean shouldHideShortcutInvocationEvents(int userId, String callingPackage, + int callingPid, int callingUid) { + final ShortcutServiceInternal shortcutServiceInternal = getShortcutServiceInternal(); + if (shortcutServiceInternal != null) { + return !shortcutServiceInternal.hasShortcutHostPermission(userId, callingPackage, + callingPid, callingUid); + } + return true; // hide by default if we can't verify visibility + } + private static void deleteRecursively(File f) { File[] files = f.listFiles(); if (files != null) { @@ -1008,7 +1030,7 @@ public class UsageStatsService extends SystemService implements * Called by the Binder stub. */ UsageEvents queryEvents(int userId, long beginTime, long endTime, - boolean shouldObfuscateInstantApps) { + boolean shouldObfuscateInstantApps, boolean shouldHideShortcutInvocationEvents) { synchronized (mLock) { if (!mUserUnlockedStates.get(userId)) { Slog.w(TAG, "Failed to query events for locked user " + userId); @@ -1019,7 +1041,8 @@ public class UsageStatsService extends SystemService implements if (service == null) { return null; // user was stopped or removed } - return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps); + return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps, + shouldHideShortcutInvocationEvents); } } @@ -1418,14 +1441,18 @@ public class UsageStatsService extends SystemService implements return null; } + final int userId = UserHandle.getCallingUserId(); + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( - Binder.getCallingUid(), UserHandle.getCallingUserId()); + callingUid, userId); - final int userId = UserHandle.getCallingUserId(); final long token = Binder.clearCallingIdentity(); try { + final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents( + userId, callingPackage, callingPid, callingUid); return UsageStatsService.this.queryEvents(userId, beginTime, endTime, - obfuscateInstantApps); + obfuscateInstantApps, hideShortcutInvocationEvents); } finally { Binder.restoreCallingIdentity(token); } @@ -1456,19 +1483,24 @@ public class UsageStatsService extends SystemService implements return null; } - if (userId != UserHandle.getCallingUserId()) { + final int callingUserId = UserHandle.getCallingUserId(); + if (userId != callingUserId) { getContext().enforceCallingPermission( Manifest.permission.INTERACT_ACROSS_USERS_FULL, "No permission to query usage stats for this user"); } + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( - Binder.getCallingUid(), UserHandle.getCallingUserId()); + callingUid, callingUserId); final long token = Binder.clearCallingIdentity(); try { + final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents( + userId, callingPackage, callingPid, callingUid); return UsageStatsService.this.queryEvents(userId, beginTime, endTime, - obfuscateInstantApps); + obfuscateInstantApps, hideShortcutInvocationEvents); } finally { Binder.restoreCallingIdentity(token); } @@ -2087,7 +2119,7 @@ public class UsageStatsService extends SystemService implements public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime, boolean shouldObfuscateInstantApps) { return UsageStatsService.this.queryEvents( - userId, beginTime, endTime, shouldObfuscateInstantApps); + userId, beginTime, endTime, shouldObfuscateInstantApps, false); } @Override diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 179b6490a7fd..4d711128da76 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -482,7 +482,7 @@ class UserUsageStatsService { } UsageEvents queryEvents(final long beginTime, final long endTime, - boolean obfuscateInstantApps) { + boolean obfuscateInstantApps, boolean hideShortcutInvocationEvents) { if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { return null; } @@ -500,6 +500,10 @@ class UserUsageStatsService { } Event event = stats.events.get(i); + if (hideShortcutInvocationEvents + && event.mEventType == Event.SHORTCUT_INVOCATION) { + continue; + } if (obfuscateInstantApps) { event = event.getObfuscatedIfInstantApp(); } diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index 9967bebf20b8..140a95d61100 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -34,9 +34,9 @@ import android.service.usb.UsbIsHeadsetProto; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.server.usb.descriptors.UsbDescriptor; @@ -418,10 +418,11 @@ public class UsbHostManager { parser.getRawDescriptors()); // Stats collection - StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, newDevice.getVendorId(), - newDevice.getProductId(), parser.hasAudioInterface(), - parser.hasHIDInterface(), parser.hasStorageInterface(), - StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_CONNECTED, 0); + FrameworkStatsLog.write(FrameworkStatsLog.USB_DEVICE_ATTACHED, + newDevice.getVendorId(), newDevice.getProductId(), + parser.hasAudioInterface(), parser.hasHIDInterface(), + parser.hasStorageInterface(), + FrameworkStatsLog.USB_DEVICE_ATTACHED__STATE__STATE_CONNECTED, 0); } } @@ -454,10 +455,10 @@ public class UsbHostManager { UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress, current.mDescriptors); // Stats collection - StatsLog.write(StatsLog.USB_DEVICE_ATTACHED, device.getVendorId(), - device.getProductId(), parser.hasAudioInterface(), + FrameworkStatsLog.write(FrameworkStatsLog.USB_DEVICE_ATTACHED, + device.getVendorId(), device.getProductId(), parser.hasAudioInterface(), parser.hasHIDInterface(), parser.hasStorageInterface(), - StatsLog.USB_DEVICE_ATTACHED__STATE__STATE_DISCONNECTED, + FrameworkStatsLog.USB_DEVICE_ATTACHED__STATE__STATE_DISCONNECTED, System.currentTimeMillis() - current.mTimestamp); } } else { diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index c3e2013eff10..1025bf5d67b0 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -66,11 +66,11 @@ import android.service.usb.UsbServiceProto; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; -import android.util.StatsLog; import com.android.internal.annotations.GuardedBy; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.server.FgThread; @@ -1040,8 +1040,9 @@ public class UsbPortManager { if (mConnected.containsKey(portInfo.mUsbPort.getId())) { //Previous logged a connected. Set it to disconnected. if (mConnected.get(portInfo.mUsbPort.getId())) { - StatsLog.write(StatsLog.USB_CONNECTOR_STATE_CHANGED, - StatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED, + FrameworkStatsLog.write(FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED, + FrameworkStatsLog + .USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED, portInfo.mUsbPort.getId(), portInfo.mLastConnectDurationMillis); } mConnected.remove(portInfo.mUsbPort.getId()); @@ -1051,7 +1052,7 @@ public class UsbPortManager { //Previous logged a contaminant detected. Set it to not detected. if ((mContaminantStatus.get(portInfo.mUsbPort.getId()) == UsbPortStatus.CONTAMINANT_DETECTION_DETECTED)) { - StatsLog.write(StatsLog.USB_CONTAMINANT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.USB_CONTAMINANT_REPORTED, portInfo.mUsbPort.getId(), convertContaminantDetectionStatusToProto( UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED)); @@ -1065,10 +1066,10 @@ public class UsbPortManager { || (mConnected.get(portInfo.mUsbPort.getId()) != portInfo.mUsbPortStatus.isConnected())) { mConnected.put(portInfo.mUsbPort.getId(), portInfo.mUsbPortStatus.isConnected()); - StatsLog.write(StatsLog.USB_CONNECTOR_STATE_CHANGED, + FrameworkStatsLog.write(FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED, portInfo.mUsbPortStatus.isConnected() - ? StatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_CONNECTED : - StatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED, + ? FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_CONNECTED : + FrameworkStatsLog.USB_CONNECTOR_STATE_CHANGED__STATE__STATE_DISCONNECTED, portInfo.mUsbPort.getId(), portInfo.mLastConnectDurationMillis); } @@ -1077,7 +1078,7 @@ public class UsbPortManager { != portInfo.mUsbPortStatus.getContaminantDetectionStatus())) { mContaminantStatus.put(portInfo.mUsbPort.getId(), portInfo.mUsbPortStatus.getContaminantDetectionStatus()); - StatsLog.write(StatsLog.USB_CONTAMINANT_REPORTED, + FrameworkStatsLog.write(FrameworkStatsLog.USB_CONTAMINANT_REPORTED, portInfo.mUsbPort.getId(), convertContaminantDetectionStatusToProto( portInfo.mUsbPortStatus.getContaminantDetectionStatus())); diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java index b230e4bbf8a2..43d5bf323abb 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java @@ -292,9 +292,27 @@ public final class UsbDescriptorParser { // Clean up descriptor.postParse(stream); } catch (Exception ex) { - Log.e(TAG, "Exception parsing USB descriptors.", ex); + // Clean up, compute error status + descriptor.postParse(stream); - // Clean up + // Report + Log.w(TAG, "Exception parsing USB descriptors. type:0x" + descriptor.getType() + + " status:" + descriptor.getStatus()); + if (DEBUG) { + // Show full stack trace if debugging + Log.e(TAG, "Exception parsing USB descriptors.", ex); + } + StackTraceElement[] stackElems = ex.getStackTrace(); + if (stackElems.length > 0) { + Log.i(TAG, " class:" + stackElems[0].getClassName() + + " @ " + stackElems[0].getLineNumber()); + } + if (stackElems.length > 1) { + Log.i(TAG, " class:" + stackElems[1].getClassName() + + " @ " + stackElems[1].getLineNumber()); + } + + // Finish up descriptor.setStatus(UsbDescriptor.STATUS_PARSE_EXCEPTION); } finally { mDescriptors.add(descriptor); diff --git a/telephony/java/android/service/carrier/CarrierIdentifier.java b/telephony/java/android/service/carrier/CarrierIdentifier.java index 7957c258b54f..bc0f909e1331 100644 --- a/telephony/java/android/service/carrier/CarrierIdentifier.java +++ b/telephony/java/android/service/carrier/CarrierIdentifier.java @@ -20,10 +20,10 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; -import com.android.telephony.Rlog; import android.telephony.TelephonyManager; import com.android.internal.telephony.uicc.IccUtils; +import com.android.telephony.Rlog; import java.util.Objects; diff --git a/telephony/java/android/telephony/AnomalyReporter.java b/telephony/java/android/telephony/AnomalyReporter.java index 097041f672ac..ffdb23f98fb8 100644 --- a/telephony/java/android/telephony/AnomalyReporter.java +++ b/telephony/java/android/telephony/AnomalyReporter.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.content.Context; @@ -27,6 +25,7 @@ import android.content.pm.ResolveInfo; import android.os.ParcelUuid; import com.android.internal.util.IndentingPrintWriter; +import com.android.telephony.Rlog; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java index 33ad5e8beea3..1dd7539420ac 100644 --- a/telephony/java/android/telephony/CallForwardingInfo.java +++ b/telephony/java/android/telephony/CallForwardingInfo.java @@ -15,7 +15,6 @@ */ package android.telephony; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -25,6 +24,8 @@ import android.os.Parcelable; import android.telephony.Annotation.CallForwardingReason; import android.telephony.Annotation.CallForwardingStatus; +import com.android.telephony.Rlog; + import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java index 719ba8d98773..c0ae99e89cb3 100644 --- a/telephony/java/android/telephony/CbGeoUtils.java +++ b/telephony/java/android/telephony/CbGeoUtils.java @@ -16,13 +16,12 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.annotation.SystemApi; import android.text.TextUtils; import com.android.internal.telephony.util.TelephonyUtils; +import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.List; diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java index 3f0aeb54f132..0c2f1f325793 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -69,8 +69,8 @@ public abstract class CellIdentity implements Parcelable { protected String mAlphaShort; /** @hide */ - protected CellIdentity(String tag, int type, String mcc, String mnc, String alphal, - String alphas) { + protected CellIdentity(@Nullable String tag, int type, @Nullable String mcc, + @Nullable String mnc, @Nullable String alphal, @Nullable String alphas) { mTag = tag; mType = type; diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java index 1a6bf33cec71..e220b07d703a 100644 --- a/telephony/java/android/telephony/CellIdentityCdma.java +++ b/telephony/java/android/telephony/CellIdentityCdma.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Parcel; import android.telephony.cdma.CdmaCellLocation; @@ -90,8 +91,8 @@ public final class CellIdentityCdma extends CellIdentity { * * @hide */ - public CellIdentityCdma( - int nid, int sid, int bid, int lon, int lat, String alphal, String alphas) { + public CellIdentityCdma(int nid, int sid, int bid, int lon, int lat, + @Nullable String alphal, @Nullable String alphas) { super(TAG, CellInfo.TYPE_CDMA, null, null, alphal, alphas); mNetworkId = inRangeOrUnavailable(nid, 0, NETWORK_ID_MAX); mSystemId = inRangeOrUnavailable(sid, 0, SYSTEM_ID_MAX); @@ -108,22 +109,22 @@ public final class CellIdentityCdma extends CellIdentity { } /** @hide */ - public CellIdentityCdma(android.hardware.radio.V1_0.CellIdentityCdma cid) { + public CellIdentityCdma(@NonNull android.hardware.radio.V1_0.CellIdentityCdma cid) { this(cid.networkId, cid.systemId, cid.baseStationId, cid.longitude, cid.latitude, "", ""); } /** @hide */ - public CellIdentityCdma(android.hardware.radio.V1_2.CellIdentityCdma cid) { + public CellIdentityCdma(@NonNull android.hardware.radio.V1_2.CellIdentityCdma cid) { this(cid.base.networkId, cid.base.systemId, cid.base.baseStationId, cid.base.longitude, cid.base.latitude, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort); } - private CellIdentityCdma(CellIdentityCdma cid) { + private CellIdentityCdma(@NonNull CellIdentityCdma cid) { this(cid.mNetworkId, cid.mSystemId, cid.mBasestationId, cid.mLongitude, cid.mLatitude, cid.mAlphaLong, cid.mAlphaShort); } - CellIdentityCdma copy() { + @NonNull CellIdentityCdma copy() { return new CellIdentityCdma(this); } diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java index dc73cbf735b0..9f2537c7ed10 100644 --- a/telephony/java/android/telephony/CellIdentityGsm.java +++ b/telephony/java/android/telephony/CellIdentityGsm.java @@ -23,6 +23,7 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -78,26 +79,31 @@ public final class CellIdentityGsm extends CellIdentity { * * @hide */ - public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, String mccStr, - String mncStr, String alphal, String alphas, - List<String> additionalPlmns) { + public CellIdentityGsm(int lac, int cid, int arfcn, int bsic, @Nullable String mccStr, + @Nullable String mncStr, @Nullable String alphal, @Nullable String alphas, + @NonNull List<String> additionalPlmns) { super(TAG, CellInfo.TYPE_GSM, mccStr, mncStr, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mArfcn = inRangeOrUnavailable(arfcn, 0, MAX_ARFCN); mBsic = inRangeOrUnavailable(bsic, 0, MAX_BSIC); - mAdditionalPlmns = additionalPlmns; + mAdditionalPlmns = new ArrayList<>(additionalPlmns.size()); + for (String plmn : additionalPlmns) { + if (isValidPlmn(plmn)) { + mAdditionalPlmns.add(plmn); + } + } } /** @hide */ - public CellIdentityGsm(android.hardware.radio.V1_0.CellIdentityGsm cid) { + public CellIdentityGsm(@NonNull android.hardware.radio.V1_0.CellIdentityGsm cid) { this(cid.lac, cid.cid, cid.arfcn, cid.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.bsic, cid.mcc, cid.mnc, "", "", Collections.emptyList()); } /** @hide */ - public CellIdentityGsm(android.hardware.radio.V1_2.CellIdentityGsm cid) { + public CellIdentityGsm(@NonNull android.hardware.radio.V1_2.CellIdentityGsm cid) { this(cid.base.lac, cid.base.cid, cid.base.arfcn, cid.base.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.base.bsic, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, @@ -105,7 +111,7 @@ public final class CellIdentityGsm extends CellIdentity { } /** @hide */ - public CellIdentityGsm(android.hardware.radio.V1_5.CellIdentityGsm cid) { + public CellIdentityGsm(@NonNull android.hardware.radio.V1_5.CellIdentityGsm cid) { this(cid.base.base.lac, cid.base.base.cid, cid.base.base.arfcn, cid.base.base.bsic == (byte) 0xFF ? CellInfo.UNAVAILABLE : cid.base.base.bsic, cid.base.base.mcc, @@ -113,12 +119,12 @@ public final class CellIdentityGsm extends CellIdentity { cid.base.operatorNames.alphaShort, cid.additionalPlmns); } - private CellIdentityGsm(CellIdentityGsm cid) { + private CellIdentityGsm(@NonNull CellIdentityGsm cid) { this(cid.mLac, cid.mCid, cid.mArfcn, cid.mBsic, cid.mMccStr, cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns); } - CellIdentityGsm copy() { + @NonNull CellIdentityGsm copy() { return new CellIdentityGsm(this); } diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java index cf8fe6a3c345..a194ae35216c 100644 --- a/telephony/java/android/telephony/CellIdentityLte.java +++ b/telephony/java/android/telephony/CellIdentityLte.java @@ -24,6 +24,7 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -104,34 +105,40 @@ public final class CellIdentityLte extends CellIdentity { * * @hide */ - public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr, - String mncStr, String alphal, String alphas, List<String> additionalPlmns, - ClosedSubscriberGroupInfo csgInfo) { + public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, + @Nullable String mccStr, @Nullable String mncStr, @Nullable String alphal, + @Nullable String alphas, @NonNull List<String> additionalPlmns, + @Nullable ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_LTE, mccStr, mncStr, alphal, alphas); mCi = inRangeOrUnavailable(ci, 0, MAX_CI); mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); mEarfcn = inRangeOrUnavailable(earfcn, 0, MAX_EARFCN); mBandwidth = inRangeOrUnavailable(bandwidth, 0, MAX_BANDWIDTH); - mAdditionalPlmns = additionalPlmns; + mAdditionalPlmns = new ArrayList<>(additionalPlmns.size()); + for (String plmn : additionalPlmns) { + if (isValidPlmn(plmn)) { + mAdditionalPlmns.add(plmn); + } + } mCsgInfo = csgInfo; } /** @hide */ - public CellIdentityLte(android.hardware.radio.V1_0.CellIdentityLte cid) { + public CellIdentityLte(@NonNull android.hardware.radio.V1_0.CellIdentityLte cid) { this(cid.ci, cid.pci, cid.tac, cid.earfcn, CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", "", Collections.emptyList(), null); } /** @hide */ - public CellIdentityLte(android.hardware.radio.V1_2.CellIdentityLte cid) { + public CellIdentityLte(@NonNull android.hardware.radio.V1_2.CellIdentityLte cid) { this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, cid.bandwidth, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, Collections.emptyList(), null); } /** @hide */ - public CellIdentityLte(android.hardware.radio.V1_5.CellIdentityLte cid) { + public CellIdentityLte(@NonNull android.hardware.radio.V1_5.CellIdentityLte cid) { this(cid.base.base.ci, cid.base.base.pci, cid.base.base.tac, cid.base.base.earfcn, cid.base.bandwidth, cid.base.base.mcc, cid.base.base.mnc, cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, @@ -139,7 +146,7 @@ public final class CellIdentityLte extends CellIdentity { ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null); } - private CellIdentityLte(CellIdentityLte cid) { + private CellIdentityLte(@NonNull CellIdentityLte cid) { this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr, cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } @@ -152,7 +159,7 @@ public final class CellIdentityLte extends CellIdentity { mMccStr, mMncStr, mAlphaLong, mAlphaShort, mAdditionalPlmns, null); } - CellIdentityLte copy() { + @NonNull CellIdentityLte copy() { return new CellIdentityLte(this); } diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index d4f181fc735a..a0ef5aa2feae 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -64,26 +64,32 @@ public final class CellIdentityNr extends CellIdentity { * @hide */ public CellIdentityNr(int pci, int tac, int nrArfcn, @NgranBand List<Integer> bands, - String mccStr, String mncStr, long nci, String alphal, String alphas, - List<String> additionalPlmns) { + @Nullable String mccStr, @Nullable String mncStr, long nci, + @Nullable String alphal, @Nullable String alphas, + @NonNull List<String> additionalPlmns) { super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas); mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN); mBands = new ArrayList<>(bands); mNci = inRangeOrUnavailable(nci, 0, MAX_NCI); - mAdditionalPlmns = new ArrayList<>(additionalPlmns); + mAdditionalPlmns = new ArrayList<>(additionalPlmns.size()); + for (String plmn : additionalPlmns) { + if (isValidPlmn(plmn)) { + mAdditionalPlmns.add(plmn); + } + } } /** @hide */ - public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) { + public CellIdentityNr(@NonNull android.hardware.radio.V1_4.CellIdentityNr cid) { this(cid.pci, cid.tac, cid.nrarfcn, Collections.emptyList(), cid.mcc, cid.mnc, cid.nci, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, Collections.emptyList()); } /** @hide */ - public CellIdentityNr(android.hardware.radio.V1_5.CellIdentityNr cid) { + public CellIdentityNr(@NonNull android.hardware.radio.V1_5.CellIdentityNr cid) { this(cid.base.pci, cid.base.tac, cid.base.nrarfcn, cid.bands, cid.base.mcc, cid.base.mnc, cid.base.nci, cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, cid.additionalPlmns); diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java index 2ff351c17e9a..531487a313d9 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -82,39 +83,44 @@ public final class CellIdentityTdscdma extends CellIdentity { * * @hide */ - public CellIdentityTdscdma(String mcc, String mnc, int lac, int cid, int cpid, int uarfcn, - String alphal, String alphas, @NonNull List<String> additionalPlmns, - ClosedSubscriberGroupInfo csgInfo) { + public CellIdentityTdscdma(@Nullable String mcc, @Nullable String mnc, int lac, int cid, + int cpid, int uarfcn, @Nullable String alphal, @Nullable String alphas, + @NonNull List<String> additionalPlmns, @Nullable ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_TDSCDMA, mcc, mnc, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mCpid = inRangeOrUnavailable(cpid, 0, MAX_CPID); mUarfcn = inRangeOrUnavailable(uarfcn, 0, MAX_UARFCN); - mAdditionalPlmns = additionalPlmns; + mAdditionalPlmns = new ArrayList<>(additionalPlmns.size()); + for (String plmn : additionalPlmns) { + if (isValidPlmn(plmn)) { + mAdditionalPlmns.add(plmn); + } + } mCsgInfo = csgInfo; } - private CellIdentityTdscdma(CellIdentityTdscdma cid) { + private CellIdentityTdscdma(@NonNull CellIdentityTdscdma cid) { this(cid.mMccStr, cid.mMncStr, cid.mLac, cid.mCid, cid.mCpid, cid.mUarfcn, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } /** @hide */ - public CellIdentityTdscdma(android.hardware.radio.V1_0.CellIdentityTdscdma cid) { + public CellIdentityTdscdma(@NonNull android.hardware.radio.V1_0.CellIdentityTdscdma cid) { this(cid.mcc, cid.mnc, cid.lac, cid.cid, cid.cpid, CellInfo.UNAVAILABLE, "", "", Collections.emptyList(), null); } /** @hide */ - public CellIdentityTdscdma(android.hardware.radio.V1_2.CellIdentityTdscdma cid) { + public CellIdentityTdscdma(@NonNull android.hardware.radio.V1_2.CellIdentityTdscdma cid) { this(cid.base.mcc, cid.base.mnc, cid.base.lac, cid.base.cid, cid.base.cpid, cid.uarfcn, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, Collections.emptyList(), null); } /** @hide */ - public CellIdentityTdscdma(android.hardware.radio.V1_5.CellIdentityTdscdma cid) { + public CellIdentityTdscdma(@NonNull android.hardware.radio.V1_5.CellIdentityTdscdma cid) { this(cid.base.base.mcc, cid.base.base.mnc, cid.base.base.lac, cid.base.base.cid, cid.base.base.cpid, cid.base.uarfcn, cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, @@ -130,7 +136,7 @@ public final class CellIdentityTdscdma extends CellIdentity { mAdditionalPlmns, null); } - CellIdentityTdscdma copy() { + @NonNull CellIdentityTdscdma copy() { return new CellIdentityTdscdma(this); } diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java index 9be42a17677b..15e491b66575 100644 --- a/telephony/java/android/telephony/CellIdentityWcdma.java +++ b/telephony/java/android/telephony/CellIdentityWcdma.java @@ -23,6 +23,7 @@ import android.os.Parcel; import android.telephony.gsm.GsmCellLocation; import android.text.TextUtils; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -83,34 +84,38 @@ public final class CellIdentityWcdma extends CellIdentity { * * @hide */ - public CellIdentityWcdma (int lac, int cid, int psc, int uarfcn, - String mccStr, String mncStr, String alphal, String alphas, - @NonNull List<String> additionalPlmns, - @Nullable ClosedSubscriberGroupInfo csgInfo) { + public CellIdentityWcdma(int lac, int cid, int psc, int uarfcn, @Nullable String mccStr, + @Nullable String mncStr, @Nullable String alphal, @Nullable String alphas, + @NonNull List<String> additionalPlmns, @Nullable ClosedSubscriberGroupInfo csgInfo) { super(TAG, CellInfo.TYPE_WCDMA, mccStr, mncStr, alphal, alphas); mLac = inRangeOrUnavailable(lac, 0, MAX_LAC); mCid = inRangeOrUnavailable(cid, 0, MAX_CID); mPsc = inRangeOrUnavailable(psc, 0, MAX_PSC); mUarfcn = inRangeOrUnavailable(uarfcn, 0, MAX_UARFCN); - mAdditionalPlmns = additionalPlmns; + mAdditionalPlmns = new ArrayList<>(additionalPlmns.size()); + for (String plmn : additionalPlmns) { + if (isValidPlmn(plmn)) { + mAdditionalPlmns.add(plmn); + } + } mCsgInfo = csgInfo; } /** @hide */ - public CellIdentityWcdma(android.hardware.radio.V1_0.CellIdentityWcdma cid) { + public CellIdentityWcdma(@NonNull android.hardware.radio.V1_0.CellIdentityWcdma cid) { this(cid.lac, cid.cid, cid.psc, cid.uarfcn, cid.mcc, cid.mnc, "", "", Collections.emptyList(), null); } /** @hide */ - public CellIdentityWcdma(android.hardware.radio.V1_2.CellIdentityWcdma cid) { + public CellIdentityWcdma(@NonNull android.hardware.radio.V1_2.CellIdentityWcdma cid) { this(cid.base.lac, cid.base.cid, cid.base.psc, cid.base.uarfcn, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, cid.operatorNames.alphaShort, Collections.emptyList(), null); } /** @hide */ - public CellIdentityWcdma(android.hardware.radio.V1_5.CellIdentityWcdma cid) { + public CellIdentityWcdma(@NonNull android.hardware.radio.V1_5.CellIdentityWcdma cid) { this(cid.base.base.lac, cid.base.base.cid, cid.base.base.psc, cid.base.base.uarfcn, cid.base.base.mcc, cid.base.base.mnc, cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort, cid.additionalPlmns, @@ -118,7 +123,7 @@ public final class CellIdentityWcdma extends CellIdentity { ? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null); } - private CellIdentityWcdma(CellIdentityWcdma cid) { + private CellIdentityWcdma(@NonNull CellIdentityWcdma cid) { this(cid.mLac, cid.mCid, cid.mPsc, cid.mUarfcn, cid.mMccStr, cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo); } @@ -131,7 +136,7 @@ public final class CellIdentityWcdma extends CellIdentity { mAlphaLong, mAlphaShort, mAdditionalPlmns, null); } - CellIdentityWcdma copy() { + @NonNull CellIdentityWcdma copy() { return new CellIdentityWcdma(this); } diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java index acb21f450243..0edb4a4eed9b 100644 --- a/telephony/java/android/telephony/CellInfoCdma.java +++ b/telephony/java/android/telephony/CellInfoCdma.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.telephony.Rlog; + /** * A {@link CellInfo} representing a CDMA cell that provides identity and measurement info. */ diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java index 79a9d44f36a2..2dddd3f935cd 100644 --- a/telephony/java/android/telephony/CellInfoGsm.java +++ b/telephony/java/android/telephony/CellInfoGsm.java @@ -16,13 +16,13 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import com.android.telephony.Rlog; + /** * A {@link CellInfo} representing a GSM cell that provides identity and measurement info. */ diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java index fed3ebf4af03..a57c7cd136db 100644 --- a/telephony/java/android/telephony/CellInfoLte.java +++ b/telephony/java/android/telephony/CellInfoLte.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.telephony.Rlog; + import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java index 58ff8c9558d9..d2cc9c6ce422 100644 --- a/telephony/java/android/telephony/CellInfoTdscdma.java +++ b/telephony/java/android/telephony/CellInfoTdscdma.java @@ -16,12 +16,12 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import com.android.telephony.Rlog; + import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java index 33f6a555414c..3f792d17b8ef 100644 --- a/telephony/java/android/telephony/CellInfoWcdma.java +++ b/telephony/java/android/telephony/CellInfoWcdma.java @@ -18,6 +18,7 @@ package android.telephony; import android.os.Parcel; import android.os.Parcelable; + import com.android.telephony.Rlog; import java.util.Objects; diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java index cab3b0cd3c47..1c92705b9422 100644 --- a/telephony/java/android/telephony/CellSignalStrengthCdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java @@ -20,6 +20,7 @@ import android.annotation.IntRange; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; + import com.android.telephony.Rlog; import java.util.Objects; diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java index 28052aa93486..76d2df918423 100644 --- a/telephony/java/android/telephony/CellSignalStrengthGsm.java +++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntRange; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; @@ -25,6 +23,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import com.android.telephony.Rlog; + import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java index 2ef2a52977ff..6d6eaa4677f0 100644 --- a/telephony/java/android/telephony/CellSignalStrengthLte.java +++ b/telephony/java/android/telephony/CellSignalStrengthLte.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntRange; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import com.android.telephony.Rlog; + import java.util.Arrays; import java.util.Objects; diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index f4c13fff9943..e3d03a38b6b0 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntDef; import android.annotation.IntRange; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import com.android.telephony.Rlog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java index 3bd9d5810136..e96f200280b6 100644 --- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntRange; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; +import com.android.telephony.Rlog; + import java.util.Objects; /** diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java index 535e9520074d..8b14b7490679 100644 --- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java +++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntRange; import android.annotation.StringDef; import android.compat.annotation.UnsupportedAppUsage; @@ -26,6 +24,8 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.text.TextUtils; +import com.android.telephony.Rlog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java index a6dedf761636..adf31ed45c9a 100644 --- a/telephony/java/android/telephony/NetworkScan.java +++ b/telephony/java/android/telephony/NetworkScan.java @@ -16,12 +16,11 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntDef; import android.os.RemoteException; import com.android.internal.telephony.ITelephony; +import com.android.telephony.Rlog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java index 844289ce75d4..87d94bfda662 100644 --- a/telephony/java/android/telephony/NetworkService.java +++ b/telephony/java/android/telephony/NetworkService.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -34,6 +32,7 @@ import android.telephony.NetworkRegistrationInfo.Domain; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.List; diff --git a/telephony/java/android/telephony/NetworkServiceCallback.java b/telephony/java/android/telephony/NetworkServiceCallback.java index 214ab41ae4f2..e8e73ee86f58 100644 --- a/telephony/java/android/telephony/NetworkServiceCallback.java +++ b/telephony/java/android/telephony/NetworkServiceCallback.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.RemoteException; import android.telephony.NetworkService.NetworkServiceProvider; +import com.android.telephony.Rlog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 0074772a221d..ec9940836afe 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -45,6 +43,7 @@ import com.android.i18n.phonenumbers.NumberParseException; import com.android.i18n.phonenumbers.PhoneNumberUtil; import com.android.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.android.telephony.Rlog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index 094b8b0d1631..54c22ae282fb 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -135,11 +135,12 @@ public final class PreciseDataConnectionState implements Parcelable { } /** - * To check the SDK version for {@code PreciseDataConnectionState#getDataConnectionState}. + * Used for checking if the SDK version for + * {@code PreciseDataConnectionState#getDataConnectionState} is above Q. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) - private static final long GET_DATA_CONNECTION_STATE_CODE_CHANGE = 147600208L; + private static final long GET_DATA_CONNECTION_STATE_R_VERSION = 148535736L; /** * Returns the state of data connection that supported the apn types returned by @@ -152,7 +153,7 @@ public final class PreciseDataConnectionState implements Parcelable { @SystemApi public @DataState int getDataConnectionState() { if (mState == TelephonyManager.DATA_DISCONNECTING - && !Compatibility.isChangeEnabled(GET_DATA_CONNECTION_STATE_CODE_CHANGE)) { + && !Compatibility.isChangeEnabled(GET_DATA_CONNECTION_STATE_R_VERSION)) { return TelephonyManager.DATA_CONNECTED; } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index 5cd7cf8fae8a..8e83c4c11992 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2543,7 +2543,7 @@ public final class SmsManager { MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); if (m != null) { m.sendMultimediaMessage(getSubscriptionId(), contentUri, locationUrl, configOverrides, - sentIntent); + sentIntent, 0L /* messageId */); } } @@ -2581,7 +2581,7 @@ public final class SmsManager { MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); if (m != null) { m.downloadMultimediaMessage(getSubscriptionId(), locationUrl, contentUri, - configOverrides, downloadedIntent); + configOverrides, downloadedIntent, 0L /* messageId */); } } diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java index 7a30f143a3a4..6d82e51c14af 100644 --- a/telephony/java/android/telephony/SmsMessage.java +++ b/telephony/java/android/telephony/SmsMessage.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA; import android.Manifest; @@ -40,13 +38,13 @@ import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.SmsMessageBase.SubmitPduBase; import com.android.internal.telephony.cdma.sms.UserData; +import com.android.telephony.Rlog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; - /** * A Short Message Service message. * @see android.provider.Telephony.Sms.Intents#getMessagesFromIntent diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index c24eeb74f6cd..832771daa409 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; @@ -40,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.Log; import com.android.internal.telephony.util.TelephonyUtils; +import com.android.telephony.Rlog; import java.util.ArrayList; import java.util.Arrays; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 26dc5f01e67b..672352211089 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5562,11 +5562,11 @@ public class TelephonyManager { public static final int DATA_DISCONNECTING = 4; /** - * To check the SDK version for {@link TelephonyManager#getDataState}. + * Used for checking if the SDK version for {@link TelephonyManager#getDataState} is above Q. */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) - private static final long GET_DATA_STATE_CODE_CHANGE = 147600208L; + private static final long GET_DATA_STATE_R_VERSION = 148534348L; /** * Returns a constant indicating the current data connection state @@ -5586,7 +5586,7 @@ public class TelephonyManager { int state = telephony.getDataStateForSubId( getSubId(SubscriptionManager.getActiveDataSubscriptionId())); if (state == TelephonyManager.DATA_DISCONNECTING - && !Compatibility.isChangeEnabled(GET_DATA_STATE_CODE_CHANGE)) { + && !Compatibility.isChangeEnabled(GET_DATA_STATE_R_VERSION)) { return TelephonyManager.DATA_CONNECTED; } diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java index a1d40e85fb10..cdff651c9c3d 100644 --- a/telephony/java/android/telephony/TelephonyScanManager.java +++ b/telephony/java/android/telephony/TelephonyScanManager.java @@ -16,8 +16,6 @@ package android.telephony; -import com.android.telephony.Rlog; - import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; @@ -33,6 +31,7 @@ import android.os.RemoteException; import android.util.SparseArray; import com.android.internal.telephony.ITelephony; +import com.android.telephony.Rlog; import java.util.Arrays; import java.util.List; diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java index 81a09c645070..3e948fc75d00 100644 --- a/telephony/java/android/telephony/UiccAccessRule.java +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -15,8 +15,6 @@ */ package android.telephony; -import com.android.telephony.Rlog; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -28,6 +26,7 @@ import android.os.Parcelable; import android.text.TextUtils; import com.android.internal.telephony.uicc.IccUtils; +import com.android.telephony.Rlog; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java index d4a27d925208..27187e68d5cc 100644 --- a/telephony/java/android/telephony/VoLteServiceState.java +++ b/telephony/java/android/telephony/VoLteServiceState.java @@ -16,14 +16,14 @@ package android.telephony; -import com.android.telephony.Rlog; - import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import com.android.telephony.Rlog; + /** * Contains LTE network state related information. * @deprecated Only contains SRVCC state, which isn't specific to LTE handovers. For SRVCC diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java index bff12b624ae8..6c4e7ce51ebf 100644 --- a/telephony/java/android/telephony/data/DataService.java +++ b/telephony/java/android/telephony/data/DataService.java @@ -31,10 +31,10 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.telephony.AccessNetworkConstants; -import com.android.telephony.Rlog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.telephony.Rlog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index d33d3f9a5eee..72b68e4645c9 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -22,9 +22,10 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.LinkProperties; import android.os.RemoteException; -import com.android.telephony.Rlog; import android.telephony.data.DataService.DataServiceProvider; +import com.android.telephony.Rlog; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java index 8220b16500de..05971c4d2e70 100644 --- a/telephony/java/android/telephony/data/QualifiedNetworksService.java +++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java @@ -28,10 +28,10 @@ import android.os.Message; import android.os.RemoteException; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.Annotation.ApnType; -import com.android.telephony.Rlog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.telephony.Rlog; import java.util.List; diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java index cd3fc953f9d2..d9d5c14735ea 100644 --- a/telephony/java/android/telephony/emergency/EmergencyNumber.java +++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java @@ -25,6 +25,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.telephony.CarrierConfigManager; import android.telephony.PhoneNumberUtils; + import com.android.telephony.Rlog; import java.lang.annotation.Retention; diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java index abfee61930ed..21bef001efae 100644 --- a/telephony/java/android/telephony/ims/ImsConferenceState.java +++ b/telephony/java/android/telephony/ims/ImsConferenceState.java @@ -24,8 +24,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.telecom.Call; import android.telecom.Connection; + import com.android.telephony.Rlog; -import android.util.Log; import java.util.HashMap; import java.util.Iterator; diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java index 136a83e2eec9..7d73165d4540 100644 --- a/telephony/java/android/telephony/ims/ImsExternalCallState.java +++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; + import com.android.telephony.Rlog; import java.lang.annotation.Retention; diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java index 2d2e63812fad..70bf0c57366d 100644 --- a/telephony/java/android/telephony/ims/ImsSsData.java +++ b/telephony/java/android/telephony/ims/ImsSsData.java @@ -22,6 +22,7 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; + import com.android.telephony.Rlog; import java.lang.annotation.Retention; diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java index 0f6ce13a6ce4..96f77d809183 100644 --- a/telephony/java/com/android/ims/ImsConfig.java +++ b/telephony/java/com/android/ims/ImsConfig.java @@ -19,13 +19,13 @@ package com.android.ims; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; -import com.android.telephony.Rlog; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ProvisioningManager; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsConfigCallback; import com.android.internal.telephony.util.HandlerExecutor; +import com.android.telephony.Rlog; import java.util.concurrent.Executor; diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java index 8e86ff788a08..3bd8cdd23df3 100644 --- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java +++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java @@ -19,12 +19,12 @@ package com.android.internal.telephony; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.content.res.XmlResourceParser; -import com.android.telephony.Rlog; import android.util.SparseIntArray; import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.telephony.util.TelephonyUtils; import com.android.internal.telephony.util.XmlUtils; +import com.android.telephony.Rlog; public class Sms7BitEncodingTranslator { private static final String TAG = "Sms7BitEncodingTranslator"; diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java index d0c8024c56fe..6ed0be24a0f1 100644 --- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java @@ -20,7 +20,6 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.sysprop.TelephonyProperties; import android.telephony.PhoneNumberUtils; -import com.android.telephony.Rlog; import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; import android.telephony.cdma.CdmaSmsCbProgramData; @@ -41,6 +40,7 @@ import com.android.internal.telephony.cdma.sms.UserData; import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.HexDump; +import com.android.telephony.Rlog; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java index 6ad6dd119f50..6dc1e0e2c8e4 100644 --- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java +++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java @@ -18,7 +18,6 @@ package com.android.internal.telephony.cdma.sms; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; -import com.android.telephony.Rlog; import android.telephony.SmsCbCmasInfo; import android.telephony.cdma.CdmaSmsCbProgramData; import android.telephony.cdma.CdmaSmsCbProgramResults; @@ -31,6 +30,7 @@ import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.uicc.IccUtils; import com.android.internal.util.BitwiseInputStream; import com.android.internal.util.BitwiseOutputStream; +import com.android.telephony.Rlog; import java.io.ByteArrayOutputStream; import java.time.Instant; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java index c91ea696ec29..08580012ad17 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java @@ -28,7 +28,6 @@ import static com.android.internal.telephony.SmsConstants.MessageClass; import android.compat.annotation.UnsupportedAppUsage; import android.content.res.Resources; import android.telephony.PhoneNumberUtils; -import com.android.telephony.Rlog; import android.text.TextUtils; import com.android.internal.telephony.EncodeException; @@ -38,6 +37,7 @@ import com.android.internal.telephony.Sms7BitEncodingTranslator; import com.android.internal.telephony.SmsHeader; import com.android.internal.telephony.SmsMessageBase; import com.android.internal.telephony.uicc.IccUtils; +import com.android.telephony.Rlog; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java index 0dc740194034..1d136924aa2c 100644 --- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java +++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java @@ -21,10 +21,10 @@ import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Color; -import com.android.telephony.Rlog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.GsmAlphabet; +import com.android.telephony.Rlog; import java.io.UnsupportedEncodingException; import java.util.List; diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java index 36074edd187e..359c44849634 100644 --- a/test-mock/src/android/test/mock/MockContext.java +++ b/test-mock/src/android/test/mock/MockContext.java @@ -812,7 +812,7 @@ public class MockContext extends Context { } @Override - public @NonNull Context createWindowContext(int type) { + public @NonNull Context createWindowContext(int type, Bundle options) { throw new UnsupportedOperationException(); } diff --git a/test-runner/src/android/test/TouchUtils.java b/test-runner/src/android/test/TouchUtils.java index 28dc7b2f900c..bb4e00ba1ef9 100644 --- a/test-runner/src/android/test/TouchUtils.java +++ b/test-runner/src/android/test/TouchUtils.java @@ -222,7 +222,8 @@ public class TouchUtils { */ public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v, int stepCount) { - int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight(); + int screenHeight = + activity.getWindowManager().getCurrentWindowMetrics().getSize().getHeight(); int[] xy = new int[2]; v.getLocationOnScreen(xy); diff --git a/tests/GamePerformance/src/android/gameperformance/BaseTest.java b/tests/GamePerformance/src/android/gameperformance/BaseTest.java index b0640b444914..e7057565499c 100644 --- a/tests/GamePerformance/src/android/gameperformance/BaseTest.java +++ b/tests/GamePerformance/src/android/gameperformance/BaseTest.java @@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit; import android.annotation.NonNull; import android.content.Context; import android.util.Log; -import android.view.WindowManager; /** * Base class for a test that performs bisection to determine maximum @@ -55,9 +54,7 @@ public abstract class BaseTest { public BaseTest(@NonNull GamePerformanceActivity activity) { mActivity = activity; - final WindowManager windowManager = - (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE); - mRefreshRate = windowManager.getDefaultDisplay().getRefreshRate(); + mRefreshRate = activity.getDisplay().getRefreshRate(); } @NonNull diff --git a/tests/GamePerformance/src/android/gameperformance/CustomControlView.java b/tests/GamePerformance/src/android/gameperformance/CustomControlView.java index 219085a83b2c..e63736b9ee61 100644 --- a/tests/GamePerformance/src/android/gameperformance/CustomControlView.java +++ b/tests/GamePerformance/src/android/gameperformance/CustomControlView.java @@ -25,18 +25,16 @@ import android.annotation.WorkerThread; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Point; import android.graphics.drawable.AnimationDrawable; -import android.util.Log; -import android.view.WindowManager; import android.widget.AbsoluteLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; /** * View that holds requested number of UI controls as ImageView with an infinite animation. */ public class CustomControlView extends AbsoluteLayout { - private final static int CONTROL_DIMENTION = 48; + private final static int CONTROL_DIMENSION = 48; private final int mPerRowControlCount; private List<Long> mFrameTimes = new ArrayList<>(); @@ -44,8 +42,9 @@ public class CustomControlView extends AbsoluteLayout { public CustomControlView(@NonNull Context context) { super(context); - final WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - mPerRowControlCount = windowManager.getDefaultDisplay().getWidth() / CONTROL_DIMENTION; + final Point size = new Point(); + context.getDisplay().getSize(size); + mPerRowControlCount = size.x / CONTROL_DIMENSION; } /** @@ -76,11 +75,11 @@ public class CustomControlView extends AbsoluteLayout { for (int i = 0; i < controlCount; ++i) { final ImageView image = (i == 0) ? new ReferenceImageView(activity) : new ImageView(activity); - final int x = (i % mPerRowControlCount) * CONTROL_DIMENTION; - final int y = (i / mPerRowControlCount) * CONTROL_DIMENTION; + final int x = (i % mPerRowControlCount) * CONTROL_DIMENSION; + final int y = (i / mPerRowControlCount) * CONTROL_DIMENSION; final AbsoluteLayout.LayoutParams layoutParams = new AbsoluteLayout.LayoutParams( - CONTROL_DIMENTION, CONTROL_DIMENTION, x, y); + CONTROL_DIMENSION, CONTROL_DIMENSION, x, y); image.setLayoutParams(layoutParams); image.setBackgroundResource(R.drawable.animation); final AnimationDrawable animation = diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java index 0f4c66817a05..6d8c43c00acf 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java @@ -122,7 +122,7 @@ public class TextureViewActivity extends Activity implements TextureView.Surface if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) break; } - int rotation = getWindowManager().getDefaultDisplay().getRotation(); + int rotation = getDisplay().getRotation(); int degrees = 0; switch (rotation) { diff --git a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java index b863713df15b..e255ce234c65 100644 --- a/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java +++ b/tests/MirrorSurfaceTest/src/com/google/android/test/mirrorsurface/MirrorSurfaceActivity.java @@ -16,6 +16,7 @@ package com.google.android.test.mirrorsurface; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import android.app.Activity; import android.graphics.Canvas; @@ -26,7 +27,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; -import android.util.DisplayMetrics; +import android.util.Size; import android.view.Gravity; import android.view.IWindowManager; import android.view.MotionEvent; @@ -48,6 +49,8 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe private static final int MOVE_FRAME_AMOUNT = 20; private IWindowManager mIWm; + // An instance of WindowManager that is adjusted for adding windows with type + // TYPE_APPLICATION_OVERLAY. private WindowManager mWm; private SurfaceControl mSurfaceControl = new SurfaceControl(); @@ -57,7 +60,7 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe private View mOverlayView; private View mArrowOverlay; - private Rect mDisplayBounds = new Rect(); + private Rect mWindowBounds = new Rect(); private EditText mScaleText; private EditText mDisplayFrameText; @@ -83,21 +86,21 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe super.onCreate(savedInstanceState); setContentView(R.layout.activity_mirror_surface); - mWm = (WindowManager) getSystemService(WINDOW_SERVICE); + mWm = createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */) + .getSystemService(WindowManager.class); mIWm = WindowManagerGlobal.getWindowManagerService(); - DisplayMetrics displayMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - mDisplayBounds.set(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); + Size windowSize = mWm.getCurrentWindowMetrics().getSize(); + mWindowBounds.set(0, 0, windowSize.getWidth(), windowSize.getHeight()); mScaleText = findViewById(R.id.scale); mDisplayFrameText = findViewById(R.id.displayFrame); mSourcePositionText = findViewById(R.id.sourcePosition); - mCurrFrame.set(0, 0, mDisplayBounds.width() / 2, mDisplayBounds.height() / 2); + mCurrFrame.set(0, 0, mWindowBounds.width() / 2, mWindowBounds.height() / 2); mCurrScale = DEFAULT_SCALE; - mDisplayId = getWindowManager().getDefaultDisplay().getDisplayId(); + mDisplayId = getDisplay().getDisplayId(); updateEditTexts(); findViewById(R.id.mirror_button).setOnClickListener(view -> { @@ -194,8 +197,8 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe private void createMirrorOverlay() { mOverlayView = new LinearLayout(this); - WindowManager.LayoutParams params = new WindowManager.LayoutParams(mDisplayBounds.width(), - mDisplayBounds.height(), + WindowManager.LayoutParams params = new WindowManager.LayoutParams(mWindowBounds.width(), + mWindowBounds.height(), WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, @@ -290,7 +293,7 @@ public class MirrorSurfaceActivity extends Activity implements View.OnClickListe private void updateMirror(Rect displayFrame, float scale) { if (displayFrame.isEmpty()) { - Rect bounds = mDisplayBounds; + Rect bounds = mWindowBounds; int defaultCropW = Math.round(bounds.width() / 2); int defaultCropH = Math.round(bounds.height() / 2); displayFrame.set(0, 0, defaultCropW, defaultCropH); diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp index 609896ea9e95..5e9ef8efc402 100644 --- a/tests/PlatformCompatGating/Android.bp +++ b/tests/PlatformCompatGating/Android.bp @@ -18,6 +18,7 @@ android_test { name: "PlatformCompatGating", // Only compile source java files in this apk. srcs: ["src/**/*.java"], + certificate: "platform", libs: [ "android.test.runner", "android.test.base", diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java index c00aa2ac25b3..932ec643d478 100644 --- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java +++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java @@ -16,9 +16,7 @@ package android.compat.testing; -import android.Manifest; import android.app.Instrumentation; -import android.app.UiAutomation; import android.compat.Compatibility; import android.compat.Compatibility.ChangeConfig; import android.content.Context; @@ -85,16 +83,12 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { @Override public void evaluate() throws Throwable { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - UiAutomation uiAutomation = instrumentation.getUiAutomation(); String packageName = instrumentation.getTargetContext().getPackageName(); IPlatformCompat platformCompat = IPlatformCompat.Stub .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); if (platformCompat == null) { throw new IllegalStateException("Could not get IPlatformCompat service!"); } - uiAutomation.adoptShellPermissionIdentity( - Manifest.permission.READ_COMPAT_CHANGE_CONFIG, - Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG); Compatibility.setOverrides(mConfig); try { platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig), @@ -107,7 +101,6 @@ public class PlatformCompatChangeRule extends CoreCompatChangeRule { } catch (RemoteException e) { throw new RuntimeException("Could not call IPlatformCompat binder method!", e); } finally { - uiAutomation.dropShellPermissionIdentity(); Compatibility.clearOverrides(); } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 80491cd98bc9..0fdcbc52bffa 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -584,6 +584,25 @@ public class StagedRollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); } + @Test + public void testRollbackApexDataDirectories_Phase1() throws Exception { + int sessionId = Install.single(TEST_APEX_WITH_APK_V2).setStaged().setEnableRollback() + .commit(); + InstallUtils.waitForSessionReady(sessionId); + } + + @Test + public void testRollbackApexDataDirectories_Phase2() throws Exception { + RollbackInfo available = RollbackUtils.getAvailableRollback(APK_IN_APEX_TESTAPEX_NAME); + + RollbackUtils.rollback(available.getRollbackId(), TEST_APEX_WITH_APK_V2); + RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId()); + + // Note: The app is not rolled back until after the rollback is staged + // and the device has been rebooted. + InstallUtils.waitForSessionReady(committed.getCommittedSessionId()); + } + private static void runShellCommand(String cmd) { ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation() .executeShellCommand(cmd); diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index 672cbb084dae..ce2f7c50e581 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -16,6 +16,8 @@ package com.android.tests.rollback.host; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; import static org.testng.Assert.assertThrows; @@ -53,6 +55,17 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test"; + private static final String TEST_SUBDIR = "/subdir/"; + + private static final String TEST_FILENAME_1 = "test_file.txt"; + private static final String TEST_STRING_1 = "hello this is a test"; + private static final String TEST_FILENAME_2 = "another_file.txt"; + private static final String TEST_STRING_2 = "this is a different file"; + private static final String TEST_FILENAME_3 = "also.xyz"; + private static final String TEST_STRING_3 = "also\n a\n test\n string"; + private static final String TEST_FILENAME_4 = "one_more.test"; + private static final String TEST_STRING_4 = "once more unto the test"; + @Before public void setUp() throws Exception { if (!getDevice().isAdbRoot()) { @@ -77,6 +90,10 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { getDevice().executeShellCommand( "rm -f /system/apex/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex " + "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex"); + getDevice().executeShellCommand( + "rm -rf " + apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "*"); + getDevice().executeShellCommand( + "rm -rf " + apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "*"); getDevice().reboot(); } @@ -245,15 +262,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { @Test public void testRollbackApexWithApk() throws Exception { getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A"); - CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); - final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"; - final File apex = buildHelper.getTestFile(fileName); - if (!getDevice().isAdbRoot()) { - getDevice().enableAdbRoot(); - } - getDevice().remountSystemWritable(); - assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); - getDevice().reboot(); + pushTestApex(); runPhase("testRollbackApexWithApk_Phase1"); getDevice().reboot(); runPhase("testRollbackApexWithApk_Phase2"); @@ -267,15 +276,7 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { @Test public void testRollbackApexWithApkCrashing() throws Exception { getDevice().uninstallPackage("com.android.cts.install.lib.testapp.A"); - CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); - final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"; - final File apex = buildHelper.getTestFile(fileName); - if (!getDevice().isAdbRoot()) { - getDevice().enableAdbRoot(); - } - getDevice().remountSystemWritable(); - assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); - getDevice().reboot(); + pushTestApex(); // Install an apex with apk that crashes runPhase("testRollbackApexWithApkCrashing_Phase1"); @@ -289,6 +290,102 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { runPhase("testRollbackApexWithApkCrashing_Phase3"); } + /** + * Tests that data in DE_sys apex data directory is restored when apex is rolled back. + */ + @Test + public void testRollbackApexDataDirectories_DeSys() throws Exception { + pushTestApex(); + + // Push files to apex data directory + String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1; + String oldFilePath2 = + apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2; + assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); + assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + + // Install new version of the APEX with rollback enabled + runPhase("testRollbackApexDataDirectories_Phase1"); + getDevice().reboot(); + + // Replace files in data directory + getDevice().deleteFile(oldFilePath1); + getDevice().deleteFile(oldFilePath2); + String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3; + String newFilePath4 = + apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4; + assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); + assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + + // Roll back the APEX + runPhase("testRollbackApexDataDirectories_Phase2"); + getDevice().reboot(); + + // Verify that old files have been restored and new files are gone + assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1)); + assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2)); + assertNull(getDevice().pullFile(newFilePath3)); + assertNull(getDevice().pullFile(newFilePath4)); + } + + /** + * Tests that data in CE apex data directory is restored when apex is rolled back. + */ + @Test + public void testRollbackApexDataDirectories_Ce() throws Exception { + pushTestApex(); + + // Push files to apex data directory + String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1; + String oldFilePath2 = + apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2; + assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); + assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + + // Install new version of the APEX with rollback enabled + runPhase("testRollbackApexDataDirectories_Phase1"); + getDevice().reboot(); + + // Replace files in data directory + getDevice().deleteFile(oldFilePath1); + getDevice().deleteFile(oldFilePath2); + String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3; + String newFilePath4 = + apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4; + assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); + assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + + // Roll back the APEX + runPhase("testRollbackApexDataDirectories_Phase2"); + getDevice().reboot(); + + // Verify that old files have been restored and new files are gone + assertEquals(TEST_STRING_1, getDevice().pullFileContents(oldFilePath1)); + assertEquals(TEST_STRING_2, getDevice().pullFileContents(oldFilePath2)); + assertNull(getDevice().pullFile(newFilePath3)); + assertNull(getDevice().pullFile(newFilePath4)); + } + + private void pushTestApex() throws Exception { + CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); + final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"; + final File apex = buildHelper.getTestFile(fileName); + if (!getDevice().isAdbRoot()) { + getDevice().enableAdbRoot(); + } + getDevice().remountSystemWritable(); + assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); + getDevice().reboot(); + } + + private static String apexDataDirDeSys(String apexName) { + return String.format("/data/misc/apexdata/%s", apexName); + } + + private static String apexDataDirCe(String apexName, int userId) { + return String.format("/data/misc_ce/%d/apexdata/%s", userId, apexName); + } + private void crashProcess(String processName, int numberOfCrashes) throws Exception { String pid = ""; String lastPid = "invalid"; diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java index 4771b6cfc750..e0a96689c191 100644 --- a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java +++ b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java @@ -23,7 +23,6 @@ import android.app.ActionBar; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.MemoryInfo; -import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.PixelFormat; @@ -531,8 +530,7 @@ public class SurfaceCompositionMeasuringActivity extends Activity implements OnC } private void detectRefreshRate() { - WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); - mRefreshRate = wm.getDefaultDisplay().getRefreshRate(); + mRefreshRate = getDisplay().getRefreshRate(); if (mRefreshRate < MIN_REFRESH_RATE_SUPPORTED) throw new RuntimeException("Unsupported display refresh rate: " + mRefreshRate); mTargetFPS = mRefreshRate - 2.0f; diff --git a/tests/TaskOrganizerTest/AndroidManifest.xml b/tests/TaskOrganizerTest/AndroidManifest.xml index 0cb6c10a7ff5..a77d7ee80242 100644 --- a/tests/TaskOrganizerTest/AndroidManifest.xml +++ b/tests/TaskOrganizerTest/AndroidManifest.xml @@ -19,5 +19,11 @@ <service android:name=".TaskOrganizerPipTest" android:exported="true"> </service> + <activity android:name="TaskOrganizerMultiWindowTest" android:label="TaskOrganizer MW Test"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> </application> </manifest> diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java new file mode 100644 index 000000000000..bc8d3c349f9d --- /dev/null +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.taskembed; + +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; + +import android.app.ActivityManager; +import android.app.Activity; +import android.app.ActivityOptions; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Bundle; +import android.view.ITaskOrganizer; +import android.view.IWindowContainer; +import android.view.SurfaceControl; +import android.view.SurfaceHolder; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +public class TaskOrganizerMultiWindowTest extends Activity { + class TaskLaunchingView extends TaskView { + TaskLaunchingView(Context c, ITaskOrganizer o, int windowingMode) { + super(c, o, windowingMode); + } + + @Override + public void surfaceChanged(SurfaceHolder h, int format, int width, int height) { + startCalculatorActivity(width, height); + } + } + TaskView mView; + + class Organizer extends ITaskOrganizer.Stub { + @Override + public void taskAppeared(IWindowContainer wc, ActivityManager.RunningTaskInfo ti) { + mView.reparentTask(wc); + } + public void taskVanished(IWindowContainer wc) { + } + public void transactionReady(int id, SurfaceControl.Transaction t) { + } + } + + Organizer mOrganizer = new Organizer(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mView = new TaskLaunchingView(this, mOrganizer, WINDOWING_MODE_MULTI_WINDOW); + setContentView(mView); + } + + Intent makeCalculatorIntent() { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_APP_CALCULATOR); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return intent; + } + + Bundle makeLaunchOptions(int width, int height) { + ActivityOptions o = ActivityOptions.makeBasic(); + o.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + o.setLaunchBounds(new Rect(0, 0, width, height)); + return o.toBundle(); + } + + void startCalculatorActivity(int width, int height) { + startActivity(makeCalculatorIntent(), makeLaunchOptions(width, height)); + } +} diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java index 6ffa19d4ec98..fc1be28d2b8f 100644 --- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java @@ -16,6 +16,8 @@ package com.android.test.taskembed; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.Service; @@ -38,48 +40,11 @@ public class TaskOrganizerPipTest extends Service { static final int PIP_WIDTH = 640; static final int PIP_HEIGHT = 360; - class PipOrgView extends SurfaceView implements SurfaceHolder.Callback { - PipOrgView(Context c) { - super(c); - getHolder().addCallback(this); - setZOrderOnTop(true); - } - @Override - public void surfaceCreated(SurfaceHolder holder) { - try { - ActivityTaskManager.getService().registerTaskOrganizer(mOrganizer, - WindowConfiguration.WINDOWING_MODE_PINNED); - } catch (Exception e) { - } - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - } - - void reparentTask(IWindowContainer wc) { - SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - SurfaceControl leash = null; - try { - leash = wc.getLeash(); - } catch (Exception e) { - // System server died.. oh well - } - t.reparent(leash, getSurfaceControl()) - .setPosition(leash, 0, 0) - .apply(); - } - } - - PipOrgView mPipView; + TaskView mTaskView; class Organizer extends ITaskOrganizer.Stub { public void taskAppeared(IWindowContainer wc, ActivityManager.RunningTaskInfo ti) { - mPipView.reparentTask(wc); + mTaskView.reparentTask(wc); final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.scheduleFinishEnterPip(wc, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT)); @@ -113,8 +78,8 @@ public class TaskOrganizerPipTest extends Service { FrameLayout layout = new FrameLayout(this); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(PIP_WIDTH, PIP_HEIGHT); - mPipView = new PipOrgView(this); - layout.addView(mPipView, lp); + mTaskView = new TaskView(this, mOrganizer, WINDOWING_MODE_PINNED); + layout.addView(mTaskView, lp); WindowManager wm = getSystemService(WindowManager.class); wm.addView(layout, wlp); diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java new file mode 100644 index 000000000000..ff73340fc947 --- /dev/null +++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java @@ -0,0 +1,73 @@ +/* + * 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.test.taskembed; + +import android.app.ActivityTaskManager; +import android.content.Context; +import android.view.ITaskOrganizer; +import android.view.IWindowContainer; +import android.view.SurfaceControl; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +/** + * Simple SurfaceView wrapper which registers a TaskOrganizer + * after it's Surface is ready. + */ +class TaskView extends SurfaceView implements SurfaceHolder.Callback { + final ITaskOrganizer mTaskOrganizer; + final int mWindowingMode; + + TaskView(Context c, ITaskOrganizer o, int windowingMode) { + super(c); + getHolder().addCallback(this); + setZOrderOnTop(true); + + mTaskOrganizer = o; + mWindowingMode = windowingMode; + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + try { + ActivityTaskManager.getService().registerTaskOrganizer(mTaskOrganizer, + mWindowingMode); + } catch (Exception e) { + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + } + + void reparentTask(IWindowContainer wc) { + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + SurfaceControl leash = null; + try { + leash = wc.getLeash(); + } catch (Exception e) { + // System server died.. oh well + } + t.reparent(leash, getSurfaceControl()) + .setPosition(leash, 0, 0) + .apply(); + } +} diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING index a7853b68c1c1..005cbe9ffdc4 100644 --- a/tests/net/TEST_MAPPING +++ b/tests/net/TEST_MAPPING @@ -1,7 +1,12 @@ { - "postsubmit": [ + "presubmit": [ { "name": "FrameworksNetIntegrationTests" } + ], + "postsubmit": [ + { + "name": "FrameworksNetDeflakeTest" + } ] }
\ No newline at end of file diff --git a/tests/net/common/java/android/net/NetworkScoreTest.kt b/tests/net/common/java/android/net/NetworkScoreTest.kt index 30836b7c9be1..a63d58d5a0f6 100644 --- a/tests/net/common/java/android/net/NetworkScoreTest.kt +++ b/tests/net/common/java/android/net/NetworkScoreTest.kt @@ -16,7 +16,7 @@ package android.net -import android.os.Parcelable +import android.net.NetworkScore.Metrics.BANDWIDTH_UNKNOWN import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import com.android.testutils.assertParcelSane @@ -28,77 +28,49 @@ import org.junit.Test import org.junit.runner.RunWith private const val TEST_SCORE = 80 -private const val KEY_DEFAULT_CAPABILITIES = "DEFAULT_CAPABILITIES" @RunWith(AndroidJUnit4::class) @SmallTest class NetworkScoreTest { @Test fun testParcelNetworkScore() { - val networkScore = NetworkScore() val defaultCap = NetworkCapabilities() - networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) - assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES)) - networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) - assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) - assertParcelSane(networkScore, 1) - } + val builder = NetworkScore.Builder().setLegacyScore(TEST_SCORE) + assertEquals(TEST_SCORE, builder.build().getLegacyScore()) + assertParcelSane(builder.build(), 7) - @Test - fun testNullKeyAndValue() { - val networkScore = NetworkScore() - val defaultCap = NetworkCapabilities() - networkScore.putIntExtension(null, TEST_SCORE) - assertEquals(TEST_SCORE, networkScore.getIntExtension(null)) - networkScore.putExtension(null, defaultCap) - assertEquals(defaultCap, networkScore.getExtension(null)) - networkScore.putExtension(null, null) - val result: Parcelable? = networkScore.getExtension(null) - assertEquals(null, result) - } + builder.addPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI) + .addPolicy(NetworkScore.POLICY_DEFAULT_SUBSCRIPTION) + .setLinkLayerMetrics(NetworkScore.Metrics(44 /* latency */, + 380 /* downlinkBandwidth */, BANDWIDTH_UNKNOWN /* uplinkBandwidth */)) + .setEndToEndMetrics(NetworkScore.Metrics(11 /* latency */, + BANDWIDTH_UNKNOWN /* downlinkBandwidth */, 100_000 /* uplinkBandwidth */)) + .setRange(NetworkScore.RANGE_MEDIUM) + assertParcelSane(builder.build(), 7) + builder.clearPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI) + val ns = builder.build() + assertParcelSane(ns, 7) + assertFalse(ns.hasPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI)) + assertTrue(ns.hasPolicy(NetworkScore.POLICY_DEFAULT_SUBSCRIPTION)) - @Test - fun testRemoveExtension() { - val networkScore = NetworkScore() - val defaultCap = NetworkCapabilities() - networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) - networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) - assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES)) - assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) - networkScore.removeExtension(KEY_DEFAULT_CAPABILITIES) - networkScore.removeExtension(NetworkScore.LEGACY_SCORE) - val result: Parcelable? = networkScore.getExtension(KEY_DEFAULT_CAPABILITIES) - assertEquals(null, result) - assertEquals(0, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE)) + val exitingNs = ns.withExiting(true) + assertNotEquals(ns.isExiting, exitingNs.isExiting) + assertNotEquals(ns, exitingNs) + assertParcelSane(exitingNs, 7) } @Test fun testEqualsNetworkScore() { - val ns1 = NetworkScore() - val ns2 = NetworkScore() - assertTrue(ns1.equals(ns2)) - assertEquals(ns1.hashCode(), ns2.hashCode()) - - ns1.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) - assertFalse(ns1.equals(ns2)) - assertNotEquals(ns1.hashCode(), ns2.hashCode()) - ns2.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE) - assertTrue(ns1.equals(ns2)) - assertEquals(ns1.hashCode(), ns2.hashCode()) - - val defaultCap = NetworkCapabilities() - ns1.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) - assertFalse(ns1.equals(ns2)) - assertNotEquals(ns1.hashCode(), ns2.hashCode()) - ns2.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap) - assertTrue(ns1.equals(ns2)) - assertEquals(ns1.hashCode(), ns2.hashCode()) + val builder1 = NetworkScore.Builder() + val builder2 = NetworkScore.Builder() + assertTrue(builder1.build().equals(builder2.build())) + assertEquals(builder1.build().hashCode(), builder2.build().hashCode()) - ns1.putIntExtension(null, 10) - assertFalse(ns1.equals(ns2)) - assertNotEquals(ns1.hashCode(), ns2.hashCode()) - ns2.putIntExtension(null, 10) - assertTrue(ns1.equals(ns2)) - assertEquals(ns1.hashCode(), ns2.hashCode()) + builder1.setLegacyScore(TEST_SCORE) + assertFalse(builder1.build().equals(builder2.build())) + assertNotEquals(builder1.hashCode(), builder2.hashCode()) + builder2.setLegacyScore(TEST_SCORE) + assertTrue(builder1.build().equals(builder2.build())) + assertEquals(builder1.build().hashCode(), builder2.build().hashCode()) } } diff --git a/tests/net/deflake/Android.bp b/tests/net/deflake/Android.bp index 1c48c749aacc..b1b017131c64 100644 --- a/tests/net/deflake/Android.bp +++ b/tests/net/deflake/Android.bp @@ -26,4 +26,5 @@ java_test_host { "net-host-tests-utils", ], data: [":FrameworksNetTests"], -}
\ No newline at end of file + test_suites: ["device-tests"], +} diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index a35fb407bca9..7ae9e95a520f 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -40,6 +40,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; import android.net.UidRange; @@ -155,9 +156,13 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } } + private NetworkScore makeNetworkScore(final int legacyScore) { + return new NetworkScore.Builder().setLegacyScore(legacyScore).build(); + } + public void adjustScore(int change) { mScore += change; - mNetworkAgent.sendNetworkScore(mScore); + mNetworkAgent.sendNetworkScore(makeNetworkScore(mScore)); } public int getScore() { diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index e863266c4b49..25e9057fd13c 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -353,8 +353,7 @@ public class LingerMonitorTest { NetworkCapabilities caps = new NetworkCapabilities(); caps.addCapability(0); caps.addTransportType(transport); - NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); + NetworkScore ns = new NetworkScore.Builder().setLegacyScore(50).build(); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.h b/tools/hiddenapi/Android.bp index f650fccc447e..e0eb06cbea7f 100644 --- a/cmds/statsd/src/external/ResourceHealthManagerPuller.h +++ b/tools/hiddenapi/Android.bp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -14,26 +14,17 @@ * limitations under the License. */ -#pragma once - -#include <utils/String16.h> -#include "StatsPuller.h" - -namespace android { -namespace os { -namespace statsd { - -/** - * Reads Ihealth.hal - */ -class ResourceHealthManagerPuller : public StatsPuller { -public: - explicit ResourceHealthManagerPuller(int tagId); - -private: - bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override; -}; - -} // namespace statsd -} // namespace os -} // namespace android +python_binary_host { + name: "merge_csv", + main: "merge_csv.py", + srcs: ["merge_csv.py"], + version: { + py2: { + enabled: false, + }, + py3: { + enabled: true, + embedded_launcher: true + }, + }, +} diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py index 48c07553ffef..96619273af8d 100755 --- a/tools/hiddenapi/merge_csv.py +++ b/tools/hiddenapi/merge_csv.py @@ -21,20 +21,19 @@ import csv import sys csv_readers = [ - csv.DictReader(open(csv_file, 'rb'), delimiter=',', quotechar='|') + csv.DictReader(open(csv_file, 'r'), delimiter=',', quotechar='|') for csv_file in sys.argv[1:] ] # Build union of all columns from source files: headers = set() for reader in csv_readers: - headers = headers.union(reader.fieldnames) + headers = headers.union(reader.fieldnames) # Concatenate all files to output: -out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', fieldnames = sorted(headers)) +out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL, + dialect='unix', fieldnames=sorted(headers)) out.writeheader() for reader in csv_readers: - for row in reader: - out.writerow(row) - - + for row in reader: + out.writerow(row) diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp index 1259a68e9624..a68c3a208869 100644 --- a/tools/stats_log_api_gen/java_writer_q.cpp +++ b/tools/stats_log_api_gen/java_writer_q.cpp @@ -577,6 +577,50 @@ void write_java_helpers_for_q_schema_methods( } } +// This method is called in main.cpp to generate StatsLog for modules that's compatible with +// Q at compile-time. +int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, + const AtomDecl &attributionDecl, const string& moduleName, + const string& javaClass, const string& javaPackage, + const bool supportWorkSource) { + // Print prelude + fprintf(out, "// This file is autogenerated\n"); + fprintf(out, "\n"); + fprintf(out, "package %s;\n", javaPackage.c_str()); + fprintf(out, "\n"); + fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n"); + fprintf(out, "\n"); + fprintf(out, "import android.util.StatsLog;\n"); + fprintf(out, "import android.os.SystemClock;\n"); + fprintf(out, "\n"); + fprintf(out, "\n"); + fprintf(out, "/**\n"); + fprintf(out, " * Utility class for logging statistics events.\n"); + fprintf(out, " */\n"); + fprintf(out, "public class %s {\n", javaClass.c_str()); + + write_java_q_logging_constants(out, " "); + + write_java_atom_codes(out, atoms, moduleName); + + write_java_enum_values(out, atoms, moduleName); + + int errors = 0; + // Print write methods + fprintf(out, " // Write methods\n"); + errors += write_java_methods_q_schema(out, atoms.signatures_to_modules, attributionDecl, + moduleName, " "); + errors += write_java_non_chained_methods(out, atoms.non_chained_signatures_to_modules, + moduleName); + if (supportWorkSource) { + errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName); + } + + fprintf(out, "}\n"); + + return errors; +} + #if defined(STATS_SCHEMA_LEGACY) static void write_java_method( FILE* out, @@ -639,48 +683,6 @@ int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attrib return 0; } - -int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, - const AtomDecl &attributionDecl, const string& moduleName, - const string& javaClass, const string& javaPackage, - const bool supportWorkSource) { - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - fprintf(out, "package %s;\n", javaPackage.c_str()); - fprintf(out, "\n"); - fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n"); - fprintf(out, "\n"); - fprintf(out, "import android.util.StatsLog;\n"); - fprintf(out, "import android.os.SystemClock;\n"); - fprintf(out, "\n"); - fprintf(out, "\n"); - fprintf(out, "/**\n"); - fprintf(out, " * Utility class for logging statistics events.\n"); - fprintf(out, " */\n"); - fprintf(out, "public class %s {\n", javaClass.c_str()); - - write_java_q_logging_constants(out, " "); - - write_java_atom_codes(out, atoms, moduleName); - - write_java_enum_values(out, atoms, moduleName); - - int errors = 0; - // Print write methods - fprintf(out, " // Write methods\n"); - errors += write_java_methods_q_schema(out, atoms.signatures_to_modules, attributionDecl, - moduleName, " "); - errors += write_java_non_chained_methods(out, atoms.non_chained_signatures_to_modules, - moduleName); - if (supportWorkSource) { - errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName); - } - - fprintf(out, "}\n"); - - return errors; -} #endif } // namespace stats_log_api_gen diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h index 36df1d8edbee..7d734df1e118 100644 --- a/tools/stats_log_api_gen/java_writer_q.h +++ b/tools/stats_log_api_gen/java_writer_q.h @@ -45,13 +45,13 @@ void write_java_helpers_for_q_schema_methods( const int requiredHelpers, const string& indent); -#if defined(STATS_SCHEMA_LEGACY) -int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl, - const bool supportWorkSource); - int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass, const string& javaPackage, const bool supportWorkSource); + +#if defined(STATS_SCHEMA_LEGACY) +int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl, + const bool supportWorkSource); #endif } // namespace stats_log_api_gen } // namespace android diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index 6089532e1ca4..ddbf22c7f12a 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -511,8 +511,10 @@ print_usage() fprintf(stderr, " --javaClass CLASS the class name of the java class.\n"); fprintf(stderr, " Optional for Java with module.\n"); fprintf(stderr, " Default is \"StatsLogInternal\"\n"); - fprintf(stderr, " --supportQ Include support for Android Q.\n"); + fprintf(stderr, " --supportQ Include runtime support for Android Q.\n"); fprintf(stderr, " --worksource Include support for logging WorkSource objects.\n"); + fprintf(stderr, " --compileQ Include compile-time support for Android Q " + "(Java only).\n"); } /** @@ -536,6 +538,7 @@ run(int argc, char const*const* argv) string javaClass = DEFAULT_JAVA_CLASS; bool supportQ = false; bool supportWorkSource = false; + bool compileQ = false; int index = 1; while (index < argc) { @@ -630,6 +633,8 @@ run(int argc, char const*const* argv) supportQ = true; } else if (0 == strcmp("--worksource", argv[index])) { supportWorkSource = true; + } else if (0 == strcmp("--compileQ", argv[index])) { + compileQ = true; } index++; @@ -645,12 +650,18 @@ run(int argc, char const*const* argv) return 1; } - if (DEFAULT_MODULE_NAME == moduleName && supportQ) { + if (DEFAULT_MODULE_NAME == moduleName && (supportQ || compileQ)) { // Support for Q schema is not needed for default module. fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str()); return 1; } + if (supportQ && compileQ) { + // Runtime Q support is redundant if compile-time Q support is required. + fprintf(stderr, "Cannot specify compileQ and supportQ simultaneously.\n"); + return 1; + } + // Collate the parameters Atoms atoms; int errorCount = collate_atoms(Atom::descriptor(), &atoms); @@ -748,9 +759,15 @@ run(int argc, char const*const* argv) javaClass = "StatsLogInternal"; javaPackage = "android.util"; } - errorCount = android::stats_log_api_gen::write_stats_log_java( - out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ, - supportWorkSource); + if (compileQ) { + errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module( + out, atoms, attributionDecl, moduleName, javaClass, javaPackage, + supportWorkSource); + } else { + errorCount = android::stats_log_api_gen::write_stats_log_java( + out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ, + supportWorkSource); + } #endif fclose(out); diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 31b3a5064932..1f1c0c12cf21 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -123,8 +123,6 @@ interface IWifiManager boolean isWifiStandardSupported(int standard); - boolean needs5GHzToAnyApBandConversion(); - DhcpInfo getDhcpInfo(); boolean isScanAlwaysAvailable(); diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 0ef224a5f8ee..372af42a3d14 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -373,6 +373,7 @@ public class WifiConfiguration implements Parcelable { * ECDHE_ECDSA * ECDHE_RSA * </pre> + * @hide */ public static class SuiteBCipher { private SuiteBCipher() { } @@ -715,8 +716,8 @@ public class WifiConfiguration implements Parcelable { public BitSet allowedGroupManagementCiphers; /** * The set of SuiteB ciphers supported by this configuration. - * To be used for WPA3-Enterprise mode. - * See {@link SuiteBCipher} for descriptions of the values. + * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the + * certificate type that is used in this configuration. */ @NonNull public BitSet allowedSuiteBCiphers; diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index f8d48c5403f7..7c031eaaeaf4 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -889,6 +889,13 @@ public class WifiInfo implements Parcelable { */ @Nullable @SystemApi + public static String sanitizeSsid(@Nullable String string) { + return removeDoubleQuotes(string); + } + + /** @hide */ + @UnsupportedAppUsage + @Nullable public static String removeDoubleQuotes(@Nullable String string) { if (string == null) return null; final int length = string.length(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 9a251062cd9e..76f97164032c 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2802,29 +2802,6 @@ public class WifiManager { } /** - * Check if the device is dual mode capable i.e. supports concurrent STA + Soft AP. - * - * If the device is dual mode capable, it may require conversion of the user's Soft AP band - * selection {@link SoftApConfiguration#mBand} from {@link SoftApConfiguration#BAND_5GHZ} to - * include also {@link SoftApConfiguration#BAND_2GHZ}, since if the device is connected to a - * 5GHz DFS channel as a STA, it may be unable to honor a request to start Soft AP on the same - * DFS channel. - * - * @return {@code true} if dual mode STA + AP is supported by this device, {@code false} - * otherwise. - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public boolean isDualModeSupported() { - try { - return mService.needs5GHzToAnyApBandConversion(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Return the DHCP-assigned addresses from the last successful DHCP request, * if any. * @return the DHCP information diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java index 3a0d080594c8..756d679b8f21 100644 --- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java @@ -19,6 +19,7 @@ package android.net.wifi.hotspot2; import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE; import static android.net.wifi.WifiConfiguration.MeteredOverride; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.wifi.hotspot2.pps.Credential; @@ -895,4 +896,18 @@ public final class PasspointConfiguration implements Parcelable { public boolean isOsuProvisioned() { return getUpdateIdentifier() != Integer.MIN_VALUE; } + + /** + * Get a unique identifier for a PasspointConfiguration object. + * + * @return A unique identifier + * @throws IllegalStateException if Credential or HomeSP nodes are not initialized + */ + public @NonNull String getUniqueId() throws IllegalStateException { + if (mCredential == null || mHomeSp == null || TextUtils.isEmpty(mHomeSp.getFqdn())) { + throw new IllegalStateException("Credential or HomeSP are not initialized"); + } + + return mHomeSp.getFqdn(); + } } diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java index b46755349ad7..060c85cac209 100644 --- a/wifi/java/com/android/server/wifi/BaseWifiService.java +++ b/wifi/java/com/android/server/wifi/BaseWifiService.java @@ -38,6 +38,7 @@ import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; @@ -268,7 +269,8 @@ public class BaseWifiService extends IWifiManager.Stub { throw new UnsupportedOperationException(); } - @Override + /** @deprecated use {@link WifiManager#isStaApConcurrencySupported()} */ + @Deprecated public boolean needs5GHzToAnyApBandConversion() { throw new UnsupportedOperationException(); } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 0c2876e340c1..a189d507a32a 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -1928,16 +1928,6 @@ public class WifiManagerTest { } /** - * Test behavior of {@link WifiManager#isDualModeSupported()} ()} - */ - @Test - public void testIsDualModeSupported() throws Exception { - when(mWifiService.needs5GHzToAnyApBandConversion()).thenReturn(true); - assertTrue(mWifiManager.isDualModeSupported()); - verify(mWifiService).needs5GHzToAnyApBandConversion(); - } - - /** * Test behavior of {@link WifiManager#is5GHzBandSupported()} */ @Test diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java index 654154d77b0d..e78c5bf992f3 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java @@ -18,6 +18,7 @@ package android.net.wifi.hotspot2; import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -364,4 +365,54 @@ public class PasspointConfigurationTest { assertTrue(config.validateForR2()); assertTrue(config.isOsuProvisioned()); } + + /** + * Verify that the unique identifier generated is correct. + * + * @throws Exception + */ + @Test + public void validateUniqueId() throws Exception { + PasspointConfiguration config = PasspointTestUtils.createConfig(); + String uniqueId; + uniqueId = config.getUniqueId(); + assertEquals(uniqueId, config.getHomeSp().getFqdn()); + } + + /** + * Verify that the unique identifier API generates an exception if HomeSP is not initialized. + * + * @throws Exception + */ + @Test + public void validateUniqueIdExceptionWithEmptyHomeSp() throws Exception { + PasspointConfiguration config = PasspointTestUtils.createConfig(); + config.setHomeSp(null); + boolean exceptionCaught = false; + try { + String uniqueId = config.getUniqueId(); + } catch (IllegalStateException e) { + exceptionCaught = true; + } + assertTrue(exceptionCaught); + } + + /** + * Verify that the unique identifier API generates an exception if Credential is not + * initialized. + * + * @throws Exception + */ + @Test + public void validateUniqueIdExceptionWithEmptyCredential() throws Exception { + PasspointConfiguration config = PasspointTestUtils.createConfig(); + config.setCredential(null); + boolean exceptionCaught = false; + try { + String uniqueId = config.getUniqueId(); + } catch (IllegalStateException e) { + exceptionCaught = true; + } + assertTrue(exceptionCaught); + } } |