summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt4
-rw-r--r--core/java/android/app/Notification.java4
-rw-r--r--core/java/android/app/time/TimeZoneCapabilities.java61
-rw-r--r--core/java/android/app/time/TimeZoneConfiguration.java50
-rw-r--r--core/java/android/provider/Settings.java10
-rw-r--r--core/java/android/window/WindowOnBackInvokedDispatcher.java16
-rw-r--r--core/java/com/android/internal/notification/SystemNotificationChannels.java7
-rw-r--r--core/res/res/layout/notification_2025_conversation_header.xml24
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_base.xml4
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_media.xml4
-rw-r--r--core/res/res/layout/notification_2025_template_collapsed_messaging.xml4
-rw-r--r--core/res/res/layout/notification_2025_template_header.xml2
-rw-r--r--core/res/res/layout/notification_2025_template_heads_up_base.xml2
-rw-r--r--core/res/res/layout/notification_2025_top_line_views.xml159
-rw-r--r--core/res/res/values-watch/config.xml11
-rw-r--r--core/res/res/values/config.xml12
-rw-r--r--core/res/res/values/dimens.xml17
-rw-r--r--core/res/res/values/strings.xml9
-rw-r--r--core/res/res/values/symbols.xml7
-rw-r--r--core/tests/timetests/src/android/app/time/TimeZoneCapabilitiesTest.java44
-rw-r--r--core/tests/timetests/src/android/app/time/TimeZoneConfigurationTest.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java66
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java51
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java24
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt9
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt10
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt7
-rw-r--r--packages/SystemUI/proguard_common.flags8
-rw-r--r--packages/SystemUI/res/values/strings.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/data/model/NotifStats.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt27
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java18
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java44
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerShellCommand.java15
-rw-r--r--services/core/java/com/android/server/display/ExternalDisplayPolicy.java42
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java54
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java10
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig8
-rw-r--r--services/core/java/com/android/server/flags/services.aconfig8
-rw-r--r--services/core/java/com/android/server/pm/SharedLibrariesImpl.java2
-rw-r--r--services/core/java/com/android/server/timedetector/ServerFlags.java31
-rw-r--r--services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java3
-rw-r--r--services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java104
-rw-r--r--services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java85
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneChangeListener.java106
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java4
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java22
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java52
-rw-r--r--services/core/java/com/android/server/vibrator/BasicToPwleSegmentAdapter.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/AppCompatController.java12
-rw-r--r--services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java14
-rw-r--r--services/core/java/com/android/server/wm/AppCompatOverrides.java10
-rw-r--r--services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java6
-rw-r--r--services/core/java/com/android/server/wm/AppCompatUtils.java2
-rw-r--r--services/core/java/com/android/server/wm/ContentRecorder.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java55
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java28
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java16
-rw-r--r--services/tests/timetests/src/com/android/server/timezonedetector/ConfigInternalForTests.java108
-rw-r--r--services/tests/timetests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java2
-rw-r--r--services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java143
-rw-r--r--services/tests/vibrator/src/com/android/server/vibrator/BasicToPwleSegmentAdapterTest.java158
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java34
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java18
91 files changed, 1389 insertions, 714 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 22af517900d2..93f311969c1e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -18570,13 +18570,13 @@ package android.telephony.satellite {
@FlaggedApi("com.android.internal.telephony.flags.satellite_state_change_listener") public final class SatelliteManager {
method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void addAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
+ method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void deprovisionService(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.Set<java.lang.Integer> getAttachRestrictionReasonsForCarrier(int);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int[] getSatelliteDisallowedReasons();
method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @NonNull @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public java.util.List<java.lang.String> getSatellitePlmnsForCarrier(int);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingDatagrams(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
- method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>);
+ method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telephony.satellite.SatelliteManager.SatelliteException>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback);
method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCommunicationAccessStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCommunicationAccessStateCallback);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 614e2aaf42e8..5176aee9051f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5856,7 +5856,9 @@ public class Notification implements Parcelable
return null;
}
final int size = mContext.getResources().getDimensionPixelSize(
- R.dimen.notification_badge_size);
+ Flags.notificationsRedesignTemplates()
+ ? R.dimen.notification_2025_badge_size
+ : R.dimen.notification_badge_size);
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
badge.setBounds(0, 0, size, size);
diff --git a/core/java/android/app/time/TimeZoneCapabilities.java b/core/java/android/app/time/TimeZoneCapabilities.java
index 4dee15988795..929f66079a3d 100644
--- a/core/java/android/app/time/TimeZoneCapabilities.java
+++ b/core/java/android/app/time/TimeZoneCapabilities.java
@@ -55,7 +55,8 @@ public final class TimeZoneCapabilities implements Parcelable {
* The user the capabilities are for. This is used for object equality and debugging but there
* is no accessor.
*/
- @NonNull private final UserHandle mUserHandle;
+ @NonNull
+ private final UserHandle mUserHandle;
private final @CapabilityState int mConfigureAutoDetectionEnabledCapability;
/**
@@ -69,6 +70,7 @@ public final class TimeZoneCapabilities implements Parcelable {
private final @CapabilityState int mConfigureGeoDetectionEnabledCapability;
private final @CapabilityState int mSetManualTimeZoneCapability;
+ private final @CapabilityState int mConfigureNotificationsEnabledCapability;
private TimeZoneCapabilities(@NonNull Builder builder) {
this.mUserHandle = Objects.requireNonNull(builder.mUserHandle);
@@ -78,6 +80,8 @@ public final class TimeZoneCapabilities implements Parcelable {
this.mConfigureGeoDetectionEnabledCapability =
builder.mConfigureGeoDetectionEnabledCapability;
this.mSetManualTimeZoneCapability = builder.mSetManualTimeZoneCapability;
+ this.mConfigureNotificationsEnabledCapability =
+ builder.mConfigureNotificationsEnabledCapability;
}
@NonNull
@@ -88,6 +92,7 @@ public final class TimeZoneCapabilities implements Parcelable {
.setUseLocationEnabled(in.readBoolean())
.setConfigureGeoDetectionEnabledCapability(in.readInt())
.setSetManualTimeZoneCapability(in.readInt())
+ .setConfigureNotificationsEnabledCapability(in.readInt())
.build();
}
@@ -98,6 +103,7 @@ public final class TimeZoneCapabilities implements Parcelable {
dest.writeBoolean(mUseLocationEnabled);
dest.writeInt(mConfigureGeoDetectionEnabledCapability);
dest.writeInt(mSetManualTimeZoneCapability);
+ dest.writeInt(mConfigureNotificationsEnabledCapability);
}
/**
@@ -117,8 +123,8 @@ public final class TimeZoneCapabilities implements Parcelable {
*
* Not part of the SDK API because it is intended for use by SettingsUI, which can display
* text about needing it to be on for location-based time zone detection.
- * @hide
*
+ * @hide
*/
public boolean isUseLocationEnabled() {
return mUseLocationEnabled;
@@ -148,6 +154,18 @@ public final class TimeZoneCapabilities implements Parcelable {
}
/**
+ * Returns the capability state associated with the user's ability to modify the time zone
+ * notification setting. The setting can be updated via {@link
+ * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)}.
+ *
+ * @hide
+ */
+ @CapabilityState
+ public int getConfigureNotificationsEnabledCapability() {
+ return mConfigureNotificationsEnabledCapability;
+ }
+
+ /**
* Tries to create a new {@link TimeZoneConfiguration} from the {@code config} and the set of
* {@code requestedChanges}, if {@code this} capabilities allow. The new configuration is
* returned. If the capabilities do not permit one or more of the requested changes then {@code
@@ -174,6 +192,12 @@ public final class TimeZoneCapabilities implements Parcelable {
newConfigBuilder.setGeoDetectionEnabled(requestedChanges.isGeoDetectionEnabled());
}
+ if (requestedChanges.hasIsNotificationsEnabled()) {
+ if (this.getConfigureNotificationsEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
+ return null;
+ }
+ newConfigBuilder.setNotificationsEnabled(requestedChanges.areNotificationsEnabled());
+ }
return newConfigBuilder.build();
}
@@ -197,13 +221,16 @@ public final class TimeZoneCapabilities implements Parcelable {
&& mUseLocationEnabled == that.mUseLocationEnabled
&& mConfigureGeoDetectionEnabledCapability
== that.mConfigureGeoDetectionEnabledCapability
- && mSetManualTimeZoneCapability == that.mSetManualTimeZoneCapability;
+ && mSetManualTimeZoneCapability == that.mSetManualTimeZoneCapability
+ && mConfigureNotificationsEnabledCapability
+ == that.mConfigureNotificationsEnabledCapability;
}
@Override
public int hashCode() {
return Objects.hash(mUserHandle, mConfigureAutoDetectionEnabledCapability,
- mConfigureGeoDetectionEnabledCapability, mSetManualTimeZoneCapability);
+ mConfigureGeoDetectionEnabledCapability, mSetManualTimeZoneCapability,
+ mConfigureNotificationsEnabledCapability);
}
@Override
@@ -216,6 +243,8 @@ public final class TimeZoneCapabilities implements Parcelable {
+ ", mConfigureGeoDetectionEnabledCapability="
+ mConfigureGeoDetectionEnabledCapability
+ ", mSetManualTimeZoneCapability=" + mSetManualTimeZoneCapability
+ + ", mConfigureNotificationsEnabledCapability="
+ + mConfigureNotificationsEnabledCapability
+ '}';
}
@@ -226,11 +255,13 @@ public final class TimeZoneCapabilities implements Parcelable {
*/
public static class Builder {
- @NonNull private UserHandle mUserHandle;
+ @NonNull
+ private UserHandle mUserHandle;
private @CapabilityState int mConfigureAutoDetectionEnabledCapability;
private Boolean mUseLocationEnabled;
private @CapabilityState int mConfigureGeoDetectionEnabledCapability;
private @CapabilityState int mSetManualTimeZoneCapability;
+ private @CapabilityState int mConfigureNotificationsEnabledCapability;
public Builder(@NonNull UserHandle userHandle) {
mUserHandle = Objects.requireNonNull(userHandle);
@@ -240,12 +271,14 @@ public final class TimeZoneCapabilities implements Parcelable {
Objects.requireNonNull(capabilitiesToCopy);
mUserHandle = capabilitiesToCopy.mUserHandle;
mConfigureAutoDetectionEnabledCapability =
- capabilitiesToCopy.mConfigureAutoDetectionEnabledCapability;
+ capabilitiesToCopy.mConfigureAutoDetectionEnabledCapability;
mUseLocationEnabled = capabilitiesToCopy.mUseLocationEnabled;
mConfigureGeoDetectionEnabledCapability =
- capabilitiesToCopy.mConfigureGeoDetectionEnabledCapability;
+ capabilitiesToCopy.mConfigureGeoDetectionEnabledCapability;
mSetManualTimeZoneCapability =
- capabilitiesToCopy.mSetManualTimeZoneCapability;
+ capabilitiesToCopy.mSetManualTimeZoneCapability;
+ mConfigureNotificationsEnabledCapability =
+ capabilitiesToCopy.mConfigureNotificationsEnabledCapability;
}
/** Sets the value for the "configure automatic time zone detection enabled" capability. */
@@ -274,6 +307,14 @@ public final class TimeZoneCapabilities implements Parcelable {
return this;
}
+ /**
+ * Sets the value for the "configure time notifications enabled" capability.
+ */
+ public Builder setConfigureNotificationsEnabledCapability(@CapabilityState int value) {
+ this.mConfigureNotificationsEnabledCapability = value;
+ return this;
+ }
+
/** Returns the {@link TimeZoneCapabilities}. */
@NonNull
public TimeZoneCapabilities build() {
@@ -283,7 +324,9 @@ public final class TimeZoneCapabilities implements Parcelable {
verifyCapabilitySet(mConfigureGeoDetectionEnabledCapability,
"configureGeoDetectionEnabledCapability");
verifyCapabilitySet(mSetManualTimeZoneCapability,
- "mSetManualTimeZoneCapability");
+ "setManualTimeZoneCapability");
+ verifyCapabilitySet(mConfigureNotificationsEnabledCapability,
+ "configureNotificationsEnabledCapability");
return new TimeZoneCapabilities(this);
}
diff --git a/core/java/android/app/time/TimeZoneConfiguration.java b/core/java/android/app/time/TimeZoneConfiguration.java
index 7403c129f4dc..68c090f6dde3 100644
--- a/core/java/android/app/time/TimeZoneConfiguration.java
+++ b/core/java/android/app/time/TimeZoneConfiguration.java
@@ -62,7 +62,8 @@ public final class TimeZoneConfiguration implements Parcelable {
*
* @hide
*/
- @StringDef({ SETTING_AUTO_DETECTION_ENABLED, SETTING_GEO_DETECTION_ENABLED })
+ @StringDef({SETTING_AUTO_DETECTION_ENABLED, SETTING_GEO_DETECTION_ENABLED,
+ SETTING_NOTIFICATIONS_ENABLED})
@Retention(RetentionPolicy.SOURCE)
@interface Setting {}
@@ -74,6 +75,10 @@ public final class TimeZoneConfiguration implements Parcelable {
@Setting
private static final String SETTING_GEO_DETECTION_ENABLED = "geoDetectionEnabled";
+ /** See {@link TimeZoneConfiguration#areNotificationsEnabled()} for details. */
+ @Setting
+ private static final String SETTING_NOTIFICATIONS_ENABLED = "notificationsEnabled";
+
@NonNull private final Bundle mBundle;
private TimeZoneConfiguration(Builder builder) {
@@ -98,7 +103,8 @@ public final class TimeZoneConfiguration implements Parcelable {
*/
public boolean isComplete() {
return hasIsAutoDetectionEnabled()
- && hasIsGeoDetectionEnabled();
+ && hasIsGeoDetectionEnabled()
+ && hasIsNotificationsEnabled();
}
/**
@@ -128,8 +134,7 @@ public final class TimeZoneConfiguration implements Parcelable {
/**
* Returns the value of the {@link #SETTING_GEO_DETECTION_ENABLED} setting. This
* controls whether the device can use geolocation to determine time zone. This value may only
- * be used by Android under some circumstances. For example, it is not used when
- * {@link #isGeoDetectionEnabled()} is {@code false}.
+ * be used by Android under some circumstances.
*
* <p>See {@link TimeZoneCapabilities#getConfigureGeoDetectionEnabledCapability()} for how to
* tell if the setting is meaningful for the current user at this time.
@@ -150,6 +155,32 @@ public final class TimeZoneConfiguration implements Parcelable {
return mBundle.containsKey(SETTING_GEO_DETECTION_ENABLED);
}
+ /**
+ * Returns the value of the {@link #SETTING_NOTIFICATIONS_ENABLED} setting. This controls
+ * whether the device can send time and time zone related notifications. This value may only
+ * be used by Android under some circumstances.
+ *
+ * <p>See {@link TimeZoneCapabilities#getConfigureNotificationsEnabledCapability()} ()} for how
+ * to tell if the setting is meaningful for the current user at this time.
+ *
+ * @throws IllegalStateException if the setting is not present
+ *
+ * @hide
+ */
+ public boolean areNotificationsEnabled() {
+ enforceSettingPresent(SETTING_NOTIFICATIONS_ENABLED);
+ return mBundle.getBoolean(SETTING_NOTIFICATIONS_ENABLED);
+ }
+
+ /**
+ * Returns {@code true} if the {@link #areNotificationsEnabled()} setting is present.
+ *
+ * @hide
+ */
+ public boolean hasIsNotificationsEnabled() {
+ return mBundle.containsKey(SETTING_NOTIFICATIONS_ENABLED);
+ }
+
@Override
public int describeContents() {
return 0;
@@ -244,6 +275,17 @@ public final class TimeZoneConfiguration implements Parcelable {
return this;
}
+ /**
+ * Sets the state of the {@link #SETTING_NOTIFICATIONS_ENABLED} setting. *
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setNotificationsEnabled(boolean enabled) {
+ this.mBundle.putBoolean(SETTING_NOTIFICATIONS_ENABLED, enabled);
+ return this;
+ }
+
/** Returns the {@link TimeZoneConfiguration}. */
@NonNull
public TimeZoneConfiguration build() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ec58eff92410..11dddfb24ad5 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13328,6 +13328,16 @@ public final class Settings {
public static final String AUTO_TIME_ZONE_EXPLICIT = "auto_time_zone_explicit";
/**
+ * Value to specify if the device should send notifications when {@link #AUTO_TIME_ZONE} is
+ * on and the device's time zone changes.
+ *
+ * <p>1=yes, 0=no.
+ *
+ * @hide
+ */
+ public static final String TIME_ZONE_NOTIFICATIONS = "time_zone_notifications";
+
+ /**
* URI for the car dock "in" event sound.
* @hide
*/
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 20e3f6b93bd0..2911b0a6643d 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -464,7 +464,12 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
* Returns false if the legacy back behavior should be used.
*/
public boolean isOnBackInvokedCallbackEnabled() {
- return isOnBackInvokedCallbackEnabled(mChecker.getContext());
+ final Context hostContext = mChecker.getContext();
+ if (hostContext == null) {
+ Log.w(TAG, "OnBackInvokedCallback is disabled, host context is removed!");
+ return false;
+ }
+ return isOnBackInvokedCallbackEnabled(hostContext);
}
/**
@@ -695,7 +700,12 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
*/
public boolean checkApplicationCallbackRegistration(int priority,
OnBackInvokedCallback callback) {
- if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(getContext())
+ final Context hostContext = getContext();
+ if (hostContext == null) {
+ Log.w(TAG, "OnBackInvokedCallback is disabled, host context is removed!");
+ return false;
+ }
+ if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(hostContext)
&& !(callback instanceof CompatOnBackInvokedCallback)) {
Log.w(TAG,
"OnBackInvokedCallback is not enabled for the application."
@@ -720,7 +730,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
return true;
}
- private Context getContext() {
+ @Nullable private Context getContext() {
return mContext.get();
}
}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 5635943cb76e..972c2ea403e0 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -49,6 +49,7 @@ public class SystemNotificationChannels {
public static final String NETWORK_ALERTS = "NETWORK_ALERTS";
public static final String NETWORK_AVAILABLE = "NETWORK_AVAILABLE";
public static final String VPN = "VPN";
+ public static final String TIME = "TIME";
/**
* @deprecated Legacy device admin channel with low importance which is no longer used,
* Use the high importance {@link #DEVICE_ADMIN} channel instead.
@@ -146,6 +147,12 @@ public class SystemNotificationChannels {
NotificationManager.IMPORTANCE_LOW);
channelsList.add(vpn);
+ final NotificationChannel time = new NotificationChannel(
+ TIME,
+ context.getString(R.string.notification_channel_system_time),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ channelsList.add(time);
+
final NotificationChannel deviceAdmin = new NotificationChannel(
DEVICE_ADMIN,
getDeviceAdminNotificationChannelName(context),
diff --git a/core/res/res/layout/notification_2025_conversation_header.xml b/core/res/res/layout/notification_2025_conversation_header.xml
index db79e79c96df..1bde17358825 100644
--- a/core/res/res/layout/notification_2025_conversation_header.xml
+++ b/core/res/res/layout/notification_2025_conversation_header.xml
@@ -136,10 +136,10 @@
<ImageView
android:id="@+id/phishing_alert"
- android:layout_width="@dimen/notification_phishing_alert_size"
- android:layout_height="@dimen/notification_phishing_alert_size"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:baseline="10dp"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
android:scaleType="fitCenter"
android:src="@drawable/ic_dialog_alert_material"
android:visibility="gone"
@@ -148,10 +148,10 @@
<ImageView
android:id="@+id/profile_badge"
- android:layout_width="@dimen/notification_badge_size"
- android:layout_height="@dimen/notification_badge_size"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:baseline="10dp"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
android:scaleType="fitCenter"
android:visibility="gone"
android:contentDescription="@string/notification_work_profile_content_description"
@@ -159,10 +159,10 @@
<ImageView
android:id="@+id/alerted_icon"
- android:layout_width="@dimen/notification_alerted_size"
- android:layout_height="@dimen/notification_alerted_size"
- android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
- android:baseline="10dp"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
android:contentDescription="@string/notification_alerted_content_description"
android:scaleType="fitCenter"
android:src="@drawable/ic_notifications_alerted"
diff --git a/core/res/res/layout/notification_2025_template_collapsed_base.xml b/core/res/res/layout/notification_2025_template_collapsed_base.xml
index f108ce5bd1b9..d29b7af9e24e 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_base.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_base.xml
@@ -87,7 +87,7 @@
>
<!--
- NOTE: The notification_top_line_views layout contains the app_name_text.
+ NOTE: The notification_2025_top_line_views layout contains the app_name_text.
In order to include the title view at the beginning, the Notification.Builder
has logic to hide that view whenever this title view is to be visible.
-->
@@ -104,7 +104,7 @@
android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
/>
- <include layout="@layout/notification_top_line_views" />
+ <include layout="@layout/notification_2025_top_line_views" />
</NotificationTopLineView>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_media.xml b/core/res/res/layout/notification_2025_template_collapsed_media.xml
index bd17a3a0a74e..5beab508aecf 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_media.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_media.xml
@@ -89,7 +89,7 @@
>
<!--
- NOTE: The notification_top_line_views layout contains the app_name_text.
+ NOTE: The notification_2025_top_line_views layout contains the app_name_text.
In order to include the title view at the beginning, the Notification.Builder
has logic to hide that view whenever this title view is to be visible.
-->
@@ -106,7 +106,7 @@
android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
/>
- <include layout="@layout/notification_top_line_views" />
+ <include layout="@layout/notification_2025_top_line_views" />
</NotificationTopLineView>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
index edbebb17f825..d7c3263904d4 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
@@ -115,7 +115,7 @@
>
<!--
- NOTE: The notification_top_line_views layout contains the app_name_text.
+ NOTE: The notification_2025_top_line_views layout contains the app_name_text.
In order to include the title view at the beginning, the Notification.Builder
has logic to hide that view whenever this title view is to be visible.
-->
@@ -132,7 +132,7 @@
android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
/>
- <include layout="@layout/notification_top_line_views" />
+ <include layout="@layout/notification_2025_top_line_views" />
</NotificationTopLineView>
diff --git a/core/res/res/layout/notification_2025_template_header.xml b/core/res/res/layout/notification_2025_template_header.xml
index 0c07053d428a..72b3798e0780 100644
--- a/core/res/res/layout/notification_2025_template_header.xml
+++ b/core/res/res/layout/notification_2025_template_header.xml
@@ -68,7 +68,7 @@
android:theme="@style/Theme.DeviceDefault.Notification"
>
- <include layout="@layout/notification_top_line_views" />
+ <include layout="@layout/notification_2025_top_line_views" />
</NotificationTopLineView>
diff --git a/core/res/res/layout/notification_2025_template_heads_up_base.xml b/core/res/res/layout/notification_2025_template_heads_up_base.xml
index e4ff835a3524..084ec7daa683 100644
--- a/core/res/res/layout/notification_2025_template_heads_up_base.xml
+++ b/core/res/res/layout/notification_2025_template_heads_up_base.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ Copyright (C) 2024 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
diff --git a/core/res/res/layout/notification_2025_top_line_views.xml b/core/res/res/layout/notification_2025_top_line_views.xml
new file mode 100644
index 000000000000..74873463391e
--- /dev/null
+++ b/core/res/res/layout/notification_2025_top_line_views.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2025 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<!--
+ This layout file should be included inside a NotificationTopLineView, sometimes after a
+ <TextView android:id="@+id/title"/>
+-->
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <TextView
+ android:id="@+id/app_name_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:visibility="?attr/notificationHeaderAppNameVisibility"
+ />
+
+ <TextView
+ android:id="@+id/header_text_secondary_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:visibility="gone"
+ />
+
+ <TextView
+ android:id="@+id/header_text_secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:visibility="gone"
+ android:singleLine="true"
+ />
+
+ <TextView
+ android:id="@+id/header_text_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:visibility="gone"
+ />
+
+ <TextView
+ android:id="@+id/header_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:visibility="gone"
+ android:singleLine="true"
+ />
+
+ <TextView
+ android:id="@+id/time_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:singleLine="true"
+ android:visibility="gone"
+ />
+
+ <DateTimeView
+ android:id="@+id/time"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:showRelative="true"
+ android:singleLine="true"
+ android:visibility="gone"
+ />
+
+ <ViewStub
+ android:id="@+id/chronometer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:layout="@layout/notification_template_part_chronometer"
+ android:visibility="gone"
+ />
+
+ <ImageButton
+ android:id="@+id/feedback"
+ android:layout_width="@dimen/notification_feedback_size"
+ android:layout_height="@dimen/notification_feedback_size"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:baseline="13dp"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_feedback_indicator"
+ android:background="?android:selectableItemBackgroundBorderless"
+ android:visibility="gone"
+ android:contentDescription="@string/notification_feedback_indicator"
+ />
+
+ <ImageView
+ android:id="@+id/phishing_alert"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_dialog_alert_material"
+ android:visibility="gone"
+ android:contentDescription="@string/notification_phishing_alert_content_description"
+ />
+
+ <ImageView
+ android:id="@+id/profile_badge"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ android:contentDescription="@string/notification_work_profile_content_description"
+ />
+
+ <ImageView
+ android:id="@+id/alerted_icon"
+ android:layout_width="@dimen/notification_2025_badge_size"
+ android:layout_height="@dimen/notification_2025_badge_size"
+ android:layout_marginStart="@dimen/notification_2025_badge_margin"
+ android:baseline="@dimen/notification_2025_badge_baseline"
+ android:contentDescription="@string/notification_alerted_content_description"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_notifications_alerted"
+ android:visibility="gone"
+ />
+</merge>
+
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index e6295ea06177..4ff3f8825cc4 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -101,6 +101,13 @@
P.S this is a change only intended for wear devices. -->
<bool name="config_enableViewGroupScalingFading">true</bool>
- <!-- Allow the gesture to double tap the power button to trigger a target action. -->
- <bool name="config_doubleTapPowerGestureEnabled">false</bool>
+ <!-- Controls the double tap power button gesture to trigger a target action.
+ 0: Gesture is disabled
+ 1: Launch camera mode, allowing the user to disable/enable the double tap power gesture
+ from launching the camera application.
+ 2: Multi target mode, allowing the user to select one of the targets defined in
+ config_doubleTapPowerGestureMultiTargetDefaultAction and to disable/enable the double
+ tap power gesture from triggering the selected target action.
+ -->
+ <integer name="config_doubleTapPowerGestureMode">0</integer>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c50c5e9d3341..ce9a0c636d62 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2083,6 +2083,18 @@
See com.android.server.timezonedetector.TimeZoneDetectorStrategy for more information. -->
<bool name="config_supportTelephonyTimeZoneFallback" translatable="false">true</bool>
+ <!-- Whether the time notifications feature is enabled. Settings this to false means the feature
+ cannot be used. Setting this to true means the feature can be enabled on the device. -->
+ <bool name="config_enableTimeZoneNotificationsSupported" translatable="false">true</bool>
+
+ <!-- Whether the time zone notifications tracking feature is enabled. Settings this to false
+ means the feature cannot be used. -->
+ <bool name="config_enableTimeZoneNotificationsTrackingSupported" translatable="false">true</bool>
+
+ <!-- Whether the time zone manual change tracking feature is enabled. Settings this to false
+ means the feature cannot be used. -->
+ <bool name="config_enableTimeZoneManualChangeTrackingSupported" translatable="false">true</bool>
+
<!-- Whether to enable network location overlay which allows network location provider to be
replaced by an app at run-time. When disabled, only the
config_networkLocationProviderPackageName package will be searched for network location
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2adb79118ed9..4f7351c7cc4d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -608,12 +608,23 @@
<!-- Size of the feedback indicator for notifications -->
<dimen name="notification_feedback_size">20dp</dimen>
+ <!-- Size of the (work) profile badge for notifications -->
+ <dimen name="notification_badge_size">12dp</dimen>
+
+ <!-- Size of the (work) profile badge for notifications (2025 redesign version).
+ Scales with font size. Chosen to look good alongside notification_subtext_size text. -->
+ <dimen name="notification_2025_badge_size">14sp</dimen>
+
+ <!-- Baseline for aligning icons in the top line (like the work profile icon or alerting icon)
+ to the text properly. This is equal to notification_2025_badge_size - 2sp. -->
+ <dimen name="notification_2025_badge_baseline">12sp</dimen>
+
+ <!-- Spacing for the top line icons (e.g. the work profile badge). -->
+ <dimen name="notification_2025_badge_margin">4dp</dimen>
+
<!-- Size of the phishing alert for notifications -->
<dimen name="notification_phishing_alert_size">@dimen/notification_badge_size</dimen>
- <!-- Size of the profile badge for notifications -->
- <dimen name="notification_badge_size">12dp</dimen>
-
<!-- Size of the alerted icon for notifications -->
<dimen name="notification_alerted_size">@dimen/notification_badge_size</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ad9e7252c6a8..debc5e9a0dce 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -853,6 +853,9 @@
<!-- Text shown when viewing channel settings for notifications related to vpn status -->
<string name="notification_channel_vpn">VPN status</string>
+ <!-- Text shown when viewing channel settings for notifications related to system time -->
+ <string name="notification_channel_system_time">Time and time zones</string>
+
<!-- Notification channel name. This channel sends high-priority alerts from the user's IT admin for key updates about the user's work device or work profile. -->
<string name="notification_channel_device_admin">Alerts from your IT admin</string>
@@ -3879,6 +3882,12 @@
<string name="carrier_app_notification_title">New SIM inserted</string>
<string name="carrier_app_notification_text">Tap to set it up</string>
+ <!-- Time zone notification strings -->
+ <!-- Title for time zone change notifications -->
+ <string name="time_zone_change_notification_title">Your time zone changed</string>
+ <!-- Body for time zone change notifications -->
+ <string name="time_zone_change_notification_body">You\'re now in <xliff:g id="time_zone_display_name">%1$s</xliff:g> (<xliff:g id="time_zone_offset">%2$s</xliff:g>)</string>
+
<!-- Date/Time picker dialogs strings -->
<!-- The title of the time picker dialog. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d20b95f59b0c..f89ca44cce30 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -575,6 +575,7 @@
<java-symbol type="dimen" name="notification_top_pad_large_text" />
<java-symbol type="dimen" name="notification_top_pad_large_text_narrow" />
<java-symbol type="dimen" name="notification_badge_size" />
+ <java-symbol type="dimen" name="notification_2025_badge_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
<java-symbol type="dimen" name="accessibility_magnification_indicator_width" />
<java-symbol type="dimen" name="circular_display_mask_thickness" />
@@ -2377,6 +2378,9 @@
<java-symbol type="string" name="config_secondaryLocationTimeZoneProviderPackageName" />
<java-symbol type="bool" name="config_enableTelephonyTimeZoneDetection" />
<java-symbol type="bool" name="config_supportTelephonyTimeZoneFallback" />
+ <java-symbol type="bool" name="config_enableTimeZoneNotificationsSupported" />
+ <java-symbol type="bool" name="config_enableTimeZoneNotificationsTrackingSupported" />
+ <java-symbol type="bool" name="config_enableTimeZoneManualChangeTrackingSupported" />
<java-symbol type="bool" name="config_autoResetAirplaneMode" />
<java-symbol type="string" name="config_notificationAccessConfirmationActivity" />
<java-symbol type="bool" name="config_preventImeStartupUnlessTextEditor" />
@@ -4025,6 +4029,7 @@
<java-symbol type="string" name="notification_channel_network_available" />
<java-symbol type="array" name="config_defaultCloudSearchServices" />
<java-symbol type="string" name="notification_channel_vpn" />
+ <java-symbol type="string" name="notification_channel_system_time" />
<java-symbol type="string" name="notification_channel_device_admin" />
<java-symbol type="string" name="notification_channel_alerts" />
<java-symbol type="string" name="notification_channel_retail_mode" />
@@ -4035,6 +4040,8 @@
<java-symbol type="string" name="notification_channel_accessibility_hearing_device" />
<java-symbol type="string" name="notification_channel_accessibility_security_policy" />
<java-symbol type="string" name="notification_channel_display" />
+ <java-symbol type="string" name="time_zone_change_notification_title" />
+ <java-symbol type="string" name="time_zone_change_notification_body" />
<java-symbol type="string" name="config_defaultAutofillService" />
<java-symbol type="string" name="config_defaultFieldClassificationService" />
<java-symbol type="string" name="config_defaultOnDeviceSpeechRecognitionService" />
diff --git a/core/tests/timetests/src/android/app/time/TimeZoneCapabilitiesTest.java b/core/tests/timetests/src/android/app/time/TimeZoneCapabilitiesTest.java
index e368d2815855..cb8b5ce245b6 100644
--- a/core/tests/timetests/src/android/app/time/TimeZoneCapabilitiesTest.java
+++ b/core/tests/timetests/src/android/app/time/TimeZoneCapabilitiesTest.java
@@ -48,12 +48,14 @@ public class TimeZoneCapabilitiesTest {
.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
- .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED);
TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
- .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED);
{
TimeZoneCapabilities one = builder1.build();
TimeZoneCapabilities two = builder2.build();
@@ -115,6 +117,13 @@ public class TimeZoneCapabilitiesTest {
TimeZoneCapabilities two = builder2.build();
assertEquals(one, two);
}
+
+ builder1.setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
}
@Test
@@ -123,7 +132,8 @@ public class TimeZoneCapabilitiesTest {
.setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
- .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED);
+ .setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED);
assertRoundTripParcelable(builder.build());
builder.setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED);
@@ -137,6 +147,9 @@ public class TimeZoneCapabilitiesTest {
builder.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED);
assertRoundTripParcelable(builder.build());
+
+ builder.setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED);
+ assertRoundTripParcelable(builder.build());
}
@Test
@@ -151,6 +164,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED)
.build();
TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder()
@@ -175,6 +189,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
.build();
TimeZoneConfiguration configChange = new TimeZoneConfiguration.Builder()
@@ -191,6 +206,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
.build();
{
@@ -204,6 +220,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
.build();
assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
@@ -221,6 +238,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(false)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
.build();
assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
@@ -238,6 +256,7 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_POSSESSED)
.setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
.build();
assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
@@ -255,6 +274,25 @@ public class TimeZoneCapabilitiesTest {
.setUseLocationEnabled(true)
.setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
.setSetManualTimeZoneCapability(CAPABILITY_POSSESSED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .build();
+
+ assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
+ }
+
+ {
+ TimeZoneCapabilities updatedCapabilities =
+ new TimeZoneCapabilities.Builder(capabilities)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED)
+ .build();
+
+ TimeZoneCapabilities expectedCapabilities =
+ new TimeZoneCapabilities.Builder(TEST_USER_HANDLE)
+ .setConfigureAutoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setUseLocationEnabled(true)
+ .setConfigureGeoDetectionEnabledCapability(CAPABILITY_NOT_ALLOWED)
+ .setSetManualTimeZoneCapability(CAPABILITY_NOT_ALLOWED)
+ .setConfigureNotificationsEnabledCapability(CAPABILITY_POSSESSED)
.build();
assertThat(updatedCapabilities).isEqualTo(expectedCapabilities);
diff --git a/core/tests/timetests/src/android/app/time/TimeZoneConfigurationTest.java b/core/tests/timetests/src/android/app/time/TimeZoneConfigurationTest.java
index 4ad3e41383aa..345e91268253 100644
--- a/core/tests/timetests/src/android/app/time/TimeZoneConfigurationTest.java
+++ b/core/tests/timetests/src/android/app/time/TimeZoneConfigurationTest.java
@@ -43,9 +43,11 @@ public class TimeZoneConfigurationTest {
TimeZoneConfiguration completeConfig = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(true)
+ .setNotificationsEnabled(true)
.build();
assertTrue(completeConfig.isComplete());
assertTrue(completeConfig.hasIsGeoDetectionEnabled());
+ assertTrue(completeConfig.hasIsNotificationsEnabled());
}
@Test
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index 4569cf31dab1..b9fccc1c4147 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -106,11 +106,12 @@ public class BackAnimationRunner {
private Runnable mFinishedCallback;
private RemoteAnimationTarget[] mApps;
- private IRemoteAnimationFinishedCallback mRemoteCallback;
+ private RemoteAnimationFinishedStub mRemoteCallback;
private static class RemoteAnimationFinishedStub extends IRemoteAnimationFinishedCallback.Stub {
//the binder callback should not hold strong reference to it to avoid memory leak.
- private WeakReference<BackAnimationRunner> mRunnerRef;
+ private final WeakReference<BackAnimationRunner> mRunnerRef;
+ private boolean mAbandoned;
private RemoteAnimationFinishedStub(BackAnimationRunner runner) {
mRunnerRef = new WeakReference<>(runner);
@@ -118,23 +119,29 @@ public class BackAnimationRunner {
@Override
public void onAnimationFinished() {
- BackAnimationRunner runner = mRunnerRef.get();
+ synchronized (this) {
+ if (mAbandoned) {
+ return;
+ }
+ }
+ final BackAnimationRunner runner = mRunnerRef.get();
if (runner == null) {
return;
}
- if (runner.shouldMonitorCUJ(runner.mApps)) {
- InteractionJankMonitor.getInstance().end(runner.mCujType);
- }
+ runner.onAnimationFinish(this);
+ }
- runner.mFinishedCallback.run();
- for (int i = runner.mApps.length - 1; i >= 0; --i) {
- SurfaceControl sc = runner.mApps[i].leash;
- if (sc != null && sc.isValid()) {
- sc.release();
- }
+ void abandon() {
+ synchronized (this) {
+ mAbandoned = true;
+ final BackAnimationRunner runner = mRunnerRef.get();
+ if (runner == null) {
+ return;
+ }
+ if (runner.shouldMonitorCUJ(runner.mApps)) {
+ InteractionJankMonitor.getInstance().end(runner.mCujType);
+ }
}
- runner.mApps = null;
- runner.mFinishedCallback = null;
}
}
@@ -144,13 +151,16 @@ public class BackAnimationRunner {
*/
void startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, Runnable finishedCallback) {
- InteractionJankMonitor interactionJankMonitor = InteractionJankMonitor.getInstance();
+ if (mRemoteCallback != null) {
+ mRemoteCallback.abandon();
+ mRemoteCallback = null;
+ }
+ mRemoteCallback = new RemoteAnimationFinishedStub(this);
mFinishedCallback = finishedCallback;
mApps = apps;
- if (mRemoteCallback == null) mRemoteCallback = new RemoteAnimationFinishedStub(this);
mWaitingAnimation = false;
if (shouldMonitorCUJ(apps)) {
- interactionJankMonitor.begin(
+ InteractionJankMonitor.getInstance().begin(
apps[0].leash, mContext, mHandler, mCujType);
}
try {
@@ -161,6 +171,28 @@ public class BackAnimationRunner {
}
}
+ void onAnimationFinish(RemoteAnimationFinishedStub finished) {
+ mHandler.post(() -> {
+ if (mRemoteCallback != null && finished != mRemoteCallback) {
+ return;
+ }
+ if (shouldMonitorCUJ(mApps)) {
+ InteractionJankMonitor.getInstance().end(mCujType);
+ }
+
+ mFinishedCallback.run();
+ for (int i = mApps.length - 1; i >= 0; --i) {
+ final SurfaceControl sc = mApps[i].leash;
+ if (sc != null && sc.isValid()) {
+ sc.release();
+ }
+ }
+ mApps = null;
+ mFinishedCallback = null;
+ mRemoteCallback = null;
+ });
+ }
+
@VisibleForTesting
boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) {
return apps.length > 0 && mCujType != NO_CUJ;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index b796b411dd1a..1323fe0fa9ca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -20,7 +20,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -60,7 +59,6 @@ import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import dagger.Lazy;
@@ -73,6 +71,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.IntPredicate;
import java.util.function.Predicate;
/**
@@ -198,9 +197,6 @@ public class CompatUIController implements OnDisplaysChangedListener,
private final CompatUIStatusManager mCompatUIStatusManager;
@NonNull
- private final FocusTransitionObserver mFocusTransitionObserver;
-
- @NonNull
private final Optional<DesktopUserRepositories> mDesktopUserRepositories;
public CompatUIController(@NonNull Context context,
@@ -217,8 +213,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
@NonNull CompatUIShellCommandHandler compatUIShellCommandHandler,
@NonNull AccessibilityManager accessibilityManager,
@NonNull CompatUIStatusManager compatUIStatusManager,
- @NonNull Optional<DesktopUserRepositories> desktopUserRepositories,
- @NonNull FocusTransitionObserver focusTransitionObserver) {
+ @NonNull Optional<DesktopUserRepositories> desktopUserRepositories) {
mContext = context;
mShellController = shellController;
mDisplayController = displayController;
@@ -235,7 +230,6 @@ public class CompatUIController implements OnDisplaysChangedListener,
DISAPPEAR_DELAY_MS, flags);
mCompatUIStatusManager = compatUIStatusManager;
mDesktopUserRepositories = desktopUserRepositories;
- mFocusTransitionObserver = focusTransitionObserver;
shellInit.addInitCallback(this::onInit, this);
}
@@ -412,8 +406,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
// start tracking the buttons visibility for this task.
if (mTopActivityTaskId != taskInfo.taskId
&& !taskInfo.isTopActivityTransparent
- && taskInfo.isVisible
- && mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)) {
+ && taskInfo.isVisible && taskInfo.isFocused) {
mTopActivityTaskId = taskInfo.taskId;
setHasShownUserAspectRatioSettingsButton(false);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 2600bcc18f72..23a0f4adb6d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -272,8 +272,7 @@ public abstract class WMShellBaseModule {
@NonNull CompatUIState compatUIState,
@NonNull CompatUIComponentIdGenerator componentIdGenerator,
@NonNull CompatUIComponentFactory compatUIComponentFactory,
- CompatUIStatusManager compatUIStatusManager,
- @NonNull FocusTransitionObserver focusTransitionObserver) {
+ CompatUIStatusManager compatUIStatusManager) {
if (!context.getResources().getBoolean(R.bool.config_enableCompatUIController)) {
return Optional.empty();
}
@@ -298,8 +297,7 @@ public abstract class WMShellBaseModule {
compatUIShellCommandHandler.get(),
accessibilityManager.get(),
compatUIStatusManager,
- desktopUserRepositories,
- focusTransitionObserver));
+ desktopUserRepositories));
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index 784e1907894d..b5c9fa151dac 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -62,11 +62,12 @@ import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopUserRepositories;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
-import com.android.wm.shell.transition.FocusTransitionObserver;
import com.android.wm.shell.transition.Transitions;
import dagger.Lazy;
+import java.util.Optional;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -76,8 +77,6 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Optional;
-
/**
* Tests for {@link CompatUIController}.
*
@@ -128,8 +127,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
private DesktopUserRepositories mDesktopUserRepositories;
@Mock
private DesktopRepository mDesktopRepository;
- @Mock
- private FocusTransitionObserver mFocusTransitionObserver;
@Captor
ArgumentCaptor<OnInsetsChangedListener> mOnInsetsChangedListenerCaptor;
@@ -165,8 +162,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
mMockDisplayController, mMockDisplayInsetsController, mMockImeController,
mMockSyncQueue, mMockExecutor, mMockTransitionsLazy, mDockStateReader,
mCompatUIConfiguration, mCompatUIShellCommandHandler, mAccessibilityManager,
- mCompatUIStatusManager, Optional.of(mDesktopUserRepositories),
- mFocusTransitionObserver) {
+ mCompatUIStatusManager, Optional.of(mDesktopUserRepositories)) {
@Override
CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
@@ -284,7 +280,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
doReturn(false).when(mMockRestartDialogLayout).updateCompatInfo(any(), any(), anyBoolean());
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener));
@@ -416,7 +411,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Verify button remains hidden while IME is showing.
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
/* canShow= */ false);
@@ -449,7 +443,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Verify button remains hidden while keyguard is showing.
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
/* canShow= */ false);
@@ -530,7 +523,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testRestartLayoutRecreatedIfNeeded() {
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
doReturn(true).when(mMockRestartDialogLayout)
.needsToBeRecreated(any(TaskInfo.class),
any(ShellTaskOrganizer.TaskListener.class));
@@ -546,7 +538,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
@RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testRestartLayoutNotRecreatedIfNotNeeded() {
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
doReturn(false).when(mMockRestartDialogLayout)
.needsToBeRecreated(any(TaskInfo.class),
any(ShellTaskOrganizer.TaskListener.class));
@@ -567,8 +558,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Create new task
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- /* isVisible */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -584,8 +574,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testUpdateActiveTaskInfo_newTask_notVisibleOrFocused_notUpdated() {
// Create new task
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- /* isVisible */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ true, /* isFocused */ true);
// Simulate task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -603,8 +592,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Create visible but NOT focused task
final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
- /* isVisible */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
+ /* isVisible */ true, /* isFocused */ false);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo1);
@@ -616,8 +604,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Create focused but NOT visible task
final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
- /* isVisible */ false);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ false, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo2);
@@ -629,8 +616,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Create NOT focused but NOT visible task
final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
- /* isVisible */ false);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
+ /* isVisible */ false, /* isFocused */ false);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo3);
@@ -646,8 +632,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testUpdateActiveTaskInfo_sameTask_notUpdated() {
// Create new task
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- /* isVisible */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -675,8 +660,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testUpdateActiveTaskInfo_transparentTask_notUpdated() {
// Create new task
final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
- /* isVisible */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ true, /* isFocused */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo);
@@ -694,8 +678,7 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
// Create transparent task
final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
- /* isVisible */ true, /* isTopActivityTransparent */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
+ /* isVisible */ true, /* isFocused */ true, /* isTopActivityTransparent */ true);
// Simulate new task being shown
mController.updateActiveTaskInfo(taskInfo1);
@@ -711,7 +694,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testLetterboxEduLayout_notCreatedWhenLetterboxEducationIsDisabled() {
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
taskInfo.appCompatTaskInfo.setLetterboxEducationEnabled(false);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
@@ -725,7 +707,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagEnabled() {
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
@@ -744,7 +725,6 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagDisabled() {
when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
- when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
@@ -759,22 +739,23 @@ public class CompatUIControllerTest extends CompatUIShellTestCase {
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat) {
return createTaskInfo(displayId, taskId, hasSizeCompat, /* isVisible */ false,
- /* isTopActivityTransparent */ false);
+ /* isFocused */ false, /* isTopActivityTransparent */ false);
}
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
- boolean isVisible) {
+ boolean isVisible, boolean isFocused) {
return createTaskInfo(displayId, taskId, hasSizeCompat,
- isVisible, /* isTopActivityTransparent */ false);
+ isVisible, isFocused, /* isTopActivityTransparent */ false);
}
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
- boolean isVisible, boolean isTopActivityTransparent) {
+ boolean isVisible, boolean isFocused, boolean isTopActivityTransparent) {
RunningTaskInfo taskInfo = new RunningTaskInfo();
taskInfo.taskId = taskId;
taskInfo.displayId = displayId;
taskInfo.appCompatTaskInfo.setTopActivityInSizeCompat(hasSizeCompat);
taskInfo.isVisible = isVisible;
+ taskInfo.isFocused = isFocused;
taskInfo.isTopActivityTransparent = isTopActivityTransparent;
taskInfo.appCompatTaskInfo.setLetterboxEducationEnabled(true);
taskInfo.appCompatTaskInfo.setTopActivityLetterboxed(true);
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 4125a81f9bbc..fc61b1e875f3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -46,6 +46,7 @@ public class GlobalSettings {
Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
Settings.Global.AUTO_TIME,
Settings.Global.AUTO_TIME_ZONE,
+ Settings.Global.TIME_ZONE_NOTIFICATIONS,
Settings.Global.POWER_SOUNDS_ENABLED,
Settings.Global.DOCK_SOUNDS_ENABLED,
Settings.Global.CHARGING_SOUNDS_ENABLED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 32d4580f67ec..c0e266fa269f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -102,6 +102,7 @@ public class GlobalSettingsValidators {
});
VALIDATORS.put(Global.AUTO_TIME, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.AUTO_TIME_ZONE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.TIME_ZONE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.POWER_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.DOCK_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index ef0bc3b100e0..f79a60f5be96 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -212,10 +212,6 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private static final String ERROR_IO_EXCEPTION = "io_exception";
private static final String ERROR_FAILED_TO_RESTORE_SOFTAP_CONFIG =
"failed_to_restore_softap_config";
- private static final String ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES =
- "failed_to_convert_network_policies";
- private static final String ERROR_UNKNOWN_BACKUP_SERIALIZATION_VERSION =
- "unknown_backup_serialization_version";
// Name of the temporary file we use during full backup/restore. This is
@@ -1438,7 +1434,6 @@ public class SettingsBackupAgent extends BackupAgentHelper {
try {
out.writeInt(NETWORK_POLICIES_BACKUP_VERSION);
out.writeInt(policies.length);
- int numberOfPoliciesBackedUp = 0;
for (NetworkPolicy policy : policies) {
// We purposefully only backup policies that the user has
// defined; any inferred policies might include
@@ -1448,23 +1443,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
out.writeByte(BackupUtils.NOT_NULL);
out.writeInt(marshaledPolicy.length);
out.write(marshaledPolicy);
- if (areAgentMetricsEnabled) {
- numberOfPoliciesBackedUp++;
- }
} else {
out.writeByte(BackupUtils.NULL);
}
}
- if (areAgentMetricsEnabled) {
- numberOfSettingsPerKey.put(KEY_NETWORK_POLICIES, numberOfPoliciesBackedUp);
- }
} catch (IOException ioe) {
Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage());
baos.reset();
- mBackupRestoreEventLogger.logItemsBackupFailed(
- KEY_NETWORK_POLICIES,
- policies.length,
- ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES);
}
}
return baos.toByteArray();
@@ -1498,10 +1483,6 @@ public class SettingsBackupAgent extends BackupAgentHelper {
try {
int version = in.readInt();
if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) {
- mBackupRestoreEventLogger.logItemsRestoreFailed(
- KEY_NETWORK_POLICIES,
- /* count= */ 1,
- ERROR_UNKNOWN_BACKUP_SERIALIZATION_VERSION);
throw new BackupUtils.BadVersionException(
"Unknown Backup Serialization Version");
}
@@ -1518,15 +1499,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
// Only set the policies if there was no error in the restore operation
networkPolicyManager.setNetworkPolicies(policies);
- mBackupRestoreEventLogger.logItemsRestored(KEY_NETWORK_POLICIES, policies.length);
} catch (NullPointerException | IOException | BackupUtils.BadVersionException
| DateTimeException e) {
// NPE can be thrown when trying to instantiate a NetworkPolicy
Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage());
- mBackupRestoreEventLogger.logItemsRestoreFailed(
- KEY_NETWORK_POLICIES,
- /* count= */ 1,
- ERROR_FAILED_TO_CONVERT_NETWORK_POLICIES);
}
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
index 912633c874ed..e6fbc725af04 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
@@ -101,7 +101,6 @@ class RenderStageManagerTest : SysuiTestCase() {
// VERIFY that the renderer is not queried for group or row controllers
inOrder(spyViewRenderer).apply {
verify(spyViewRenderer, times(1)).onRenderList(any())
- verify(spyViewRenderer, times(1)).getStackController()
verify(spyViewRenderer, never()).getGroupController(any())
verify(spyViewRenderer, never()).getRowController(any())
verify(spyViewRenderer, times(1)).onDispatchComplete()
@@ -121,7 +120,6 @@ class RenderStageManagerTest : SysuiTestCase() {
// VERIFY that the renderer is queried once per group/entry
inOrder(spyViewRenderer).apply {
verify(spyViewRenderer, times(1)).onRenderList(any())
- verify(spyViewRenderer, times(1)).getStackController()
verify(spyViewRenderer, times(2)).getGroupController(any())
verify(spyViewRenderer, times(8)).getRowController(any())
verify(spyViewRenderer, times(1)).onDispatchComplete()
@@ -144,7 +142,6 @@ class RenderStageManagerTest : SysuiTestCase() {
// VERIFY that the renderer is queried once per group/entry
inOrder(spyViewRenderer).apply {
verify(spyViewRenderer, times(1)).onRenderList(any())
- verify(spyViewRenderer, times(1)).getStackController()
verify(spyViewRenderer, times(2)).getGroupController(any())
verify(spyViewRenderer, times(8)).getRowController(any())
verify(spyViewRenderer, times(1)).onDispatchComplete()
@@ -162,7 +159,7 @@ class RenderStageManagerTest : SysuiTestCase() {
onRenderListListener.onRenderList(listWith2Groups8Entries())
// VERIFY that the listeners are invoked once per group and once per entry
- verify(onAfterRenderListListener, times(1)).onAfterRenderList(any(), any())
+ verify(onAfterRenderListListener, times(1)).onAfterRenderList(any())
verify(onAfterRenderGroupListener, times(2)).onAfterRenderGroup(any(), any())
verify(onAfterRenderEntryListener, times(8)).onAfterRenderEntry(any(), any())
verifyNoMoreInteractions(
@@ -182,7 +179,7 @@ class RenderStageManagerTest : SysuiTestCase() {
onRenderListListener.onRenderList(listOf())
// VERIFY that the stack listener is invoked once but other listeners are not
- verify(onAfterRenderListListener, times(1)).onAfterRenderList(any(), any())
+ verify(onAfterRenderListListener, times(1)).onAfterRenderList(any())
verify(onAfterRenderGroupListener, never()).onAfterRenderGroup(any(), any())
verify(onAfterRenderEntryListener, never()).onAfterRenderEntry(any(), any())
verifyNoMoreInteractions(
@@ -203,8 +200,6 @@ class RenderStageManagerTest : SysuiTestCase() {
private class FakeNotifViewRenderer : NotifViewRenderer {
override fun onRenderList(notifList: List<ListEntry>) {}
- override fun getStackController(): NotifStackController = mock()
-
override fun getGroupController(group: GroupEntry): NotifGroupController = mock()
override fun getRowController(entry: NotificationEntry): NotifRowController = mock()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
index 54ce88b40c11..83c61507a506 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractorTest.kt
@@ -26,7 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
@@ -275,7 +275,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
@@ -293,7 +292,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
@@ -311,7 +309,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 0,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
@@ -329,7 +326,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
@@ -347,7 +343,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = true,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = true,
@@ -365,7 +360,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
@@ -383,7 +377,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = true,
@@ -401,7 +394,6 @@ class ActiveNotificationsInteractorTest : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
index 06b1c432955a..b3a60b052d08 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/footer/ui/viewmodel/FooterViewModelTest.kt
@@ -37,7 +37,7 @@ import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.res.R
import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.notification.footer.shared.NotifRedesignFooter
@@ -115,7 +115,6 @@ class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
@@ -133,7 +132,6 @@ class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
@@ -151,7 +149,6 @@ class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
@@ -183,7 +180,6 @@ class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
// AND there are clearable notifications
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
@@ -217,7 +213,6 @@ class FooterViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
// AND there are clearable notifications
activeNotificationListRepository.notifStats.value =
NotifStats(
- numActiveNotifs = 2,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
diff --git a/packages/SystemUI/proguard_common.flags b/packages/SystemUI/proguard_common.flags
index 162d8aebfc62..02b2bcf8e40d 100644
--- a/packages/SystemUI/proguard_common.flags
+++ b/packages/SystemUI/proguard_common.flags
@@ -1,5 +1,11 @@
-include proguard_kotlin.flags
--keep class com.android.systemui.VendorServices
+
+# VendorServices implements CoreStartable and may be instantiated reflectively in
+# SystemUIApplication#startAdditionalStartable.
+# TODO(b/373579455): Rewrite this to a @UsesReflection keep annotation.
+-keep class com.android.systemui.VendorServices {
+ public void <init>();
+}
# Needed to ensure callback field references are kept in their respective
# owning classes when the downstream callback registrars only store weak refs.
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a01ff3d5258f..d445ed927a25 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3919,6 +3919,16 @@
The helper is a component that shows the user which keyboard shortcuts they can use.
[CHAR LIMIT=NONE] -->
<string name="shortcut_helper_plus_symbol">+</string>
+ <!-- Accessibility label for the plus icon on a shortcut in shortcut helper that allows the user
+ to add a new custom shortcut.
+ The helper is a component that shows the user which keyboard shortcuts they can use.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_add_shortcut_button_label">Add shortcut</string>
+ <!-- Accessibility label for the bin(trash) icon on a shortcut in shortcut helper that allows the
+ user to delete an existing custom shortcut.
+ The helper is a component that shows the user which keyboard shortcuts they can use.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_delete_shortcut_button_label">Delete shortcut</string>
<!-- Keyboard touchpad tutorial scheduler-->
<!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index aea583d67289..ba31d08c9c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -729,6 +729,7 @@ private fun AddShortcutButton(onClick: () -> Unit) {
contentColor = MaterialTheme.colorScheme.primary,
contentPaddingVertical = 0.dp,
contentPaddingHorizontal = 0.dp,
+ contentDescription = stringResource(R.string.shortcut_helper_add_shortcut_button_label),
)
}
@@ -749,6 +750,7 @@ private fun DeleteShortcutButton(onClick: () -> Unit) {
contentColor = MaterialTheme.colorScheme.primary,
contentPaddingVertical = 0.dp,
contentPaddingHorizontal = 0.dp,
+ contentDescription = stringResource(R.string.shortcut_helper_delete_shortcut_button_label),
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
index 55c0fe297bcb..9a380f495176 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/Surfaces.kt
@@ -230,6 +230,7 @@ fun ShortcutHelperButton(
contentPaddingVertical: Dp = 10.dp,
enabled: Boolean = true,
border: BorderStroke? = null,
+ contentDescription: String? = null,
) {
ShortcutHelperButtonSurface(
onClick = onClick,
@@ -254,8 +255,7 @@ fun ShortcutHelperButton(
Icon(
tint = contentColor,
imageVector = iconSource.imageVector,
- contentDescription =
- null, // TODO this probably should not be null for accessibility.
+ contentDescription = contentDescription,
modifier = Modifier.size(20.dp).wrapContentSize(Alignment.Center),
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
index 90212ed5b5f7..034a4fd2af72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
@@ -36,7 +36,7 @@ class DataStoreCoordinator
internal constructor(private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl) : CoreCoordinator {
override fun attach(pipeline: NotifPipeline) {
- pipeline.addOnAfterRenderListListener { entries, _ -> onAfterRenderList(entries) }
+ pipeline.addOnAfterRenderListListener { entries -> onAfterRenderList(entries) }
}
override fun dumpPipeline(d: PipelineDumper) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index d4d3cdf42fb1..1cb2366a16fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -23,8 +23,7 @@ import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
@@ -51,8 +50,7 @@ internal constructor(
groupExpansionManagerImpl.attach(pipeline)
}
- // TODO: b/293167744 - Remove controller param.
- private fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) =
+ private fun onAfterRenderList(entries: List<ListEntry>) =
traceSection("StackCoordinator.onAfterRenderList") {
val notifStats = calculateNotifStats(entries)
activeNotificationsInteractor.setNotifStats(notifStats)
@@ -84,7 +82,6 @@ internal constructor(
}
}
return NotifStats(
- numActiveNotifs = entries.size,
hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
hasClearableAlertingNotifs = hasClearableAlertingNotifs,
hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index a34d033afcaa..c58b3febe54b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -33,7 +33,6 @@ import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
import com.android.systemui.statusbar.notification.collection.render.RenderStageManager;
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager;
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManagerFactory;
@@ -89,8 +88,7 @@ public class NotifPipelineInitializer implements Dumpable, PipelineDumpable {
public void initialize(
NotificationListener notificationService,
NotificationRowBinderImpl rowBinder,
- NotificationListContainer listContainer,
- NotifStackController stackController) {
+ NotificationListContainer listContainer) {
mDumpManager.registerDumpable("NotifPipeline", this);
mNotificationService = notificationService;
@@ -102,7 +100,7 @@ public class NotifPipelineInitializer implements Dumpable, PipelineDumpable {
mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
- mShadeViewManager = mShadeViewManagerFactory.create(listContainer, stackController);
+ mShadeViewManager = mShadeViewManagerFactory.create(listContainer);
mShadeViewManager.attach(mRenderStageManager);
mRenderStageManager.attach(mListBuilder);
mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
index b5a0f7ae169d..ac450c03b850 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
@@ -20,7 +20,6 @@ import androidx.annotation.NonNull;
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
import java.util.List;
@@ -31,9 +30,6 @@ public interface OnAfterRenderListListener {
*
* @param entries The current list of top-level entries. Note that this is a live view into the
* current list and will change whenever the pipeline is rerun.
- * @param controller An object for setting state on the shade.
*/
- void onAfterRenderList(
- @NonNull List<ListEntry> entries,
- @NonNull NotifStackController controller);
+ void onAfterRenderList(@NonNull List<ListEntry> entries);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
deleted file mode 100644
index a37937a6c495..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection.render
-
-import javax.inject.Inject
-
-/** An interface by which the pipeline can make updates to the notification root view. */
-interface NotifStackController {
- /** Provides stats about the list of notifications attached to the shade */
- fun setNotifStats(stats: NotifStats)
-}
-
-/** Data provided to the NotificationRootController whenever the pipeline runs */
-data class NotifStats(
- // TODO(b/293167744): The count can be removed from here when we remove the FooterView flag.
- val numActiveNotifs: Int,
- val hasNonClearableAlertingNotifs: Boolean,
- val hasClearableAlertingNotifs: Boolean,
- val hasNonClearableSilentNotifs: Boolean,
- val hasClearableSilentNotifs: Boolean
-) {
- companion object {
- @JvmStatic val empty = NotifStats(0, false, false, false, false)
- }
-}
-
-/**
- * An implementation of NotifStackController which provides default, no-op implementations of each
- * method. This is used by ArcSystemUI so that that implementation can opt-in to overriding methods,
- * rather than forcing us to add no-op implementations in their implementation every time a method
- * is added.
- */
-open class DefaultNotifStackController @Inject constructor() : NotifStackController {
- override fun setNotifStats(stats: NotifStats) {}
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
index 410b78b9d3bf..8284022c7270 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
@@ -37,12 +37,6 @@ interface NotifViewRenderer {
fun onRenderList(notifList: List<ListEntry>)
/**
- * Provides an interface for the pipeline to update the overall shade. This will be called at
- * most once for each time [onRenderList] is called.
- */
- fun getStackController(): NotifStackController
-
- /**
* Provides an interface for the pipeline to update individual groups. This will be called at
* most once for each group in the most recent call to [onRenderList].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
index 9d3b098fa966..21e68376031c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
@@ -50,7 +50,7 @@ class RenderStageManager @Inject constructor() : PipelineDumpable {
traceSection("RenderStageManager.onRenderList") {
val viewRenderer = viewRenderer ?: return
viewRenderer.onRenderList(notifList)
- dispatchOnAfterRenderList(viewRenderer, notifList)
+ dispatchOnAfterRenderList(notifList)
dispatchOnAfterRenderGroups(viewRenderer, notifList)
dispatchOnAfterRenderEntries(viewRenderer, notifList)
viewRenderer.onDispatchComplete()
@@ -85,15 +85,9 @@ class RenderStageManager @Inject constructor() : PipelineDumpable {
dump("onAfterRenderEntryListeners", onAfterRenderEntryListeners)
}
- private fun dispatchOnAfterRenderList(
- viewRenderer: NotifViewRenderer,
- entries: List<ListEntry>,
- ) {
+ private fun dispatchOnAfterRenderList(entries: List<ListEntry>) {
traceSection("RenderStageManager.dispatchOnAfterRenderList") {
- val stackController = viewRenderer.getStackController()
- onAfterRenderListListeners.forEach { listener ->
- listener.onAfterRenderList(entries, stackController)
- }
+ onAfterRenderListListeners.forEach { listener -> listener.onAfterRenderList(entries) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 3c838e5b707e..72316bf14c9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -41,7 +41,6 @@ class ShadeViewManager
constructor(
@ShadeDisplayAware context: Context,
@Assisted listContainer: NotificationListContainer,
- @Assisted private val stackController: NotifStackController,
mediaContainerController: MediaContainerController,
featureManager: NotificationSectionsFeatureManager,
sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
@@ -83,8 +82,6 @@ constructor(
}
}
- override fun getStackController(): NotifStackController = stackController
-
override fun getGroupController(group: GroupEntry): NotifGroupController =
viewBarn.requireGroupController(group.requireSummary)
@@ -95,8 +92,5 @@ constructor(
@AssistedFactory
interface ShadeViewManagerFactory {
- fun create(
- listContainer: NotificationListContainer,
- stackController: NotifStackController,
- ): ShadeViewManager
+ fun create(listContainer: NotificationListContainer): ShadeViewManager
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/model/NotifStats.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/model/NotifStats.kt
new file mode 100644
index 000000000000..d7fd7025a94f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/model/NotifStats.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.data.model
+
+/** Information about the current list of notifications. */
+data class NotifStats(
+ val hasNonClearableAlertingNotifs: Boolean,
+ val hasClearableAlertingNotifs: Boolean,
+ val hasNonClearableSilentNotifs: Boolean,
+ val hasClearableSilentNotifs: Boolean,
+) {
+ companion object {
+ @JvmStatic
+ val empty =
+ NotifStats(
+ hasNonClearableAlertingNotifs = false,
+ hasClearableAlertingNotifs = false,
+ hasNonClearableSilentNotifs = false,
+ hasClearableSilentNotifs = false,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
index 2b9e49372a63..70f06ebe8468 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.data.repository
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore.Key
import com.android.systemui.statusbar.notification.shared.ActiveNotificationEntryModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
index 6b93ee1c435e..0c040c855368 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.notification.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
index 2c5d9c2e449b..3c2051f0b153 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
@@ -20,7 +20,6 @@ import android.service.notification.StatusBarNotification
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.notification.NotificationActivityStarter
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
/**
@@ -33,7 +32,6 @@ interface NotificationsController {
fun initialize(
presenter: NotificationPresenter,
listContainer: NotificationListContainer,
- stackController: NotifStackController,
notificationActivityStarter: NotificationActivityStarter,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index ea6a60bd7a1c..0a9899e88d24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -34,7 +34,6 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.logging.NotificationLogger
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
@@ -76,7 +75,6 @@ constructor(
override fun initialize(
presenter: NotificationPresenter,
listContainer: NotificationListContainer,
- stackController: NotifStackController,
notificationActivityStarter: NotificationActivityStarter,
) {
notificationListener.registerAsSystemService()
@@ -101,7 +99,7 @@ constructor(
notifPipelineInitializer
.get()
- .initialize(notificationListener, notificationRowBinder, listContainer, stackController)
+ .initialize(notificationListener, notificationRowBinder, listContainer)
targetSdkResolver.initialize(notifPipeline.get())
notificationsMediaManager.setUpWithPresenter(presenter)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
index 148b3f021643..92d96f9e899b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
@@ -21,7 +21,6 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.Snoo
import com.android.systemui.statusbar.NotificationListener
import com.android.systemui.statusbar.NotificationPresenter
import com.android.systemui.statusbar.notification.NotificationActivityStarter
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import javax.inject.Inject
@@ -35,7 +34,6 @@ constructor(private val notificationListener: NotificationListener) : Notificati
override fun initialize(
presenter: NotificationPresenter,
listContainer: NotificationListContainer,
- stackController: NotifStackController,
notificationActivityStarter: NotificationActivityStarter,
) {
// Always connect the listener even if notification-handling is disabled. Being a listener
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index b892bebb3120..e752e6581421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -103,9 +103,7 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Di
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
-import com.android.systemui.statusbar.notification.collection.render.DefaultNotifStackController;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.headsup.HeadsUpNotificationViewControllerEmptyImpl;
@@ -211,9 +209,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
private final NotificationListContainerImpl mNotificationListContainer =
new NotificationListContainerImpl();
- // TODO: b/293167744 - Remove this.
- private final NotifStackController mNotifStackController =
- new DefaultNotifStackController();
@VisibleForTesting
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
@@ -1469,10 +1464,6 @@ public class NotificationStackScrollLayoutController implements Dumpable {
return mNotificationListContainer;
}
- public NotifStackController getNotifStackController() {
- return mNotifStackController;
- }
-
public void resetCheckSnoozeLeavebehind() {
mView.resetCheckSnoozeLeavebehind();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 3d6cd7e49dfe..b146b92ed110 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1492,7 +1492,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mNotificationsController.initialize(
mPresenterLazy.get(),
mNotifListContainer,
- mStackScrollerController.getNotifStackController(),
mNotificationActivityStarterLazy.get());
mWindowRootViewVisibilityInteractor.setUp(mPresenterLazy.get(), mNotificationsController);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
index a3c518128b47..f31d49094ac4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
@@ -26,7 +26,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -48,7 +47,6 @@ class DataStoreCoordinatorTest : SysuiTestCase() {
private val pipeline: NotifPipeline = mock()
private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl = mock()
- private val stackController: NotifStackController = mock()
private val section: NotifSection = mock()
@Before
@@ -63,7 +61,7 @@ class DataStoreCoordinatorTest : SysuiTestCase() {
@Test
fun testUpdateDataStore_withOneEntry() {
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(notifLiveDataStoreImpl).setActiveNotifList(eq(listOf(entry)))
verifyNoMoreInteractions(notifLiveDataStoreImpl)
}
@@ -86,8 +84,7 @@ class DataStoreCoordinatorTest : SysuiTestCase() {
.setSection(section)
.build(),
notificationEntry("baz", 1),
- ),
- stackController,
+ )
)
val list: List<NotificationEntry> = withArgCaptor {
verify(notifLiveDataStoreImpl).setActiveNotifList(capture())
@@ -111,7 +108,7 @@ class DataStoreCoordinatorTest : SysuiTestCase() {
@Test
fun testUpdateDataStore_withZeroEntries_whenNewPipelineEnabled() {
- afterRenderListListener.onAfterRenderList(listOf(), stackController)
+ afterRenderListListener.onAfterRenderList(listOf())
verify(notifLiveDataStoreImpl).setActiveNotifList(eq(listOf()))
verifyNoMoreInteractions(notifLiveDataStoreImpl)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
index 77bac59b9dcd..97e99b95f80e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -28,8 +28,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl
-import com.android.systemui.statusbar.notification.collection.render.NotifStackController
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.data.model.NotifStats
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.RenderNotificationListInteractor
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -43,7 +42,6 @@ import org.junit.runner.RunWith
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
-import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
@SmallTest
@@ -61,7 +59,6 @@ class StackCoordinatorTest : SysuiTestCase() {
private val sensitiveNotificationProtectionController:
SensitiveNotificationProtectionController =
mock()
- private val stackController: NotifStackController = mock()
private val section: NotifSection = mock()
private val row: ExpandableNotificationRow = mock()
@@ -87,25 +84,23 @@ class StackCoordinatorTest : SysuiTestCase() {
@Test
fun testSetRenderedListOnInteractor() {
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(renderListInteractor).setRenderedList(eq(listOf(entry)))
}
@Test
fun testSetNotificationStats_clearableAlerting() {
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
- 1,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = true,
hasNonClearableSilentNotifs = false,
hasClearableSilentNotifs = false,
)
)
- verifyNoMoreInteractions(stackController)
}
@Test
@@ -113,35 +108,31 @@ class StackCoordinatorTest : SysuiTestCase() {
fun testSetNotificationStats_isSensitiveStateActive_nonClearableAlerting() {
whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
- 1,
hasNonClearableAlertingNotifs = true,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
hasClearableSilentNotifs = false,
)
)
- verifyNoMoreInteractions(stackController)
}
@Test
fun testSetNotificationStats_clearableSilent() {
whenever(section.bucket).thenReturn(BUCKET_SILENT)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
- 1,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
hasClearableSilentNotifs = true,
)
)
- verifyNoMoreInteractions(stackController)
}
@Test
@@ -149,35 +140,31 @@ class StackCoordinatorTest : SysuiTestCase() {
fun testSetNotificationStats_isSensitiveStateActive_nonClearableSilent() {
whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
whenever(section.bucket).thenReturn(BUCKET_SILENT)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
- 1,
hasNonClearableAlertingNotifs = false,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = true,
hasClearableSilentNotifs = false,
)
)
- verifyNoMoreInteractions(stackController)
}
@Test
fun testSetNotificationStats_nonClearableRedacted() {
entry.setSensitive(true, true)
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
- afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ afterRenderListListener.onAfterRenderList(listOf(entry))
verify(activeNotificationsInteractor)
.setNotifStats(
NotifStats(
- 1,
hasNonClearableAlertingNotifs = true,
hasClearableAlertingNotifs = false,
hasNonClearableSilentNotifs = false,
hasClearableSilentNotifs = false,
)
)
- verifyNoMoreInteractions(stackController)
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bd2714211796..3f6484f0f58e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8571,6 +8571,12 @@ public class AudioService extends IAudioService.Stub
return true;
}
+ private boolean shouldPreserveVolume(boolean userSwitch, VolumeGroupState vgs) {
+ // as for STREAM_MUSIC, preserve volume from one user to the next except
+ // Android Automotive platform
+ return (userSwitch && vgs.isMusic()) && !isPlatformAutomotive();
+ }
+
private void readVolumeGroupsSettings(boolean userSwitch) {
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) {
@@ -8579,8 +8585,7 @@ public class AudioService extends IAudioService.Stub
}
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- // as for STREAM_MUSIC, preserve volume from one user to the next.
- if (!(userSwitch && vgs.isMusic())) {
+ if (!shouldPreserveVolume(userSwitch, vgs)) {
vgs.clearIndexCache();
vgs.readSettings();
}
@@ -9019,6 +9024,11 @@ public class AudioService extends IAudioService.Stub
mIndexMap.clear();
}
+ private @UserIdInt int getVolumePersistenceUserId() {
+ return isMusic() && !isPlatformAutomotive()
+ ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT;
+ }
+
private void persistVolumeGroup(int device) {
// No need to persist the index if the volume group is backed up
// by a public stream type as this is redundant
@@ -9036,7 +9046,7 @@ public class AudioService extends IAudioService.Stub
boolean success = mSettings.putSystemIntForUser(mContentResolver,
getSettingNameForDevice(device),
getIndex(device),
- isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
+ getVolumePersistenceUserId());
if (!success) {
Log.e(TAG, "persistVolumeGroup failed for group " + mAudioVolumeGroup.name());
}
@@ -9059,7 +9069,7 @@ public class AudioService extends IAudioService.Stub
String name = getSettingNameForDevice(device);
index = mSettings.getSystemIntForUser(
mContentResolver, name, defaultIndex,
- isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
+ getVolumePersistenceUserId());
if (index == -1) {
continue;
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index c8192e534f5c..b530da2a5f5e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2246,10 +2246,6 @@ public final class DisplayManagerService extends SystemService {
@GuardedBy("mSyncRoot")
private void handleLogicalDisplayDisconnectedLocked(LogicalDisplay display) {
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- Slog.e(TAG, "DisplayDisconnected shouldn't be received when the flag is off");
- return;
- }
releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED);
mExternalDisplayPolicy.handleLogicalDisplayDisconnectedLocked(display);
}
@@ -2315,11 +2311,6 @@ public final class DisplayManagerService extends SystemService {
@SuppressLint("AndroidFrameworkRequiresPermission")
private void handleLogicalDisplayConnectedLocked(LogicalDisplay display) {
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- Slog.e(TAG, "DisplayConnected shouldn't be received when the flag is off");
- return;
- }
-
setupLogicalDisplay(display);
if (ExternalDisplayPolicy.isExternalDisplayLocked(display)) {
@@ -2346,9 +2337,6 @@ public final class DisplayManagerService extends SystemService {
private void handleLogicalDisplayAddedLocked(LogicalDisplay display) {
final int displayId = display.getDisplayIdLocked();
final boolean isDefault = displayId == Display.DEFAULT_DISPLAY;
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- setupLogicalDisplay(display);
- }
// Wake up waitForDefaultDisplay.
if (isDefault) {
@@ -2443,21 +2431,17 @@ public final class DisplayManagerService extends SystemService {
}
private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
- // With display management, the display is removed when disabled, and it might still exist.
+ // The display is removed when disabled, and it might still exist.
// Resources must only be released when the disconnected signal is received.
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- if (display.isValidLocked()) {
- updateViewportPowerStateLocked(display);
- }
+ if (display.isValidLocked()) {
+ updateViewportPowerStateLocked(display);
+ }
- // Note: This method is only called if the display was enabled before being removed.
- sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ // Note: This method is only called if the display was enabled before being removed.
+ sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
- if (display.isValidLocked()) {
- applyDisplayChangedLocked(display);
- }
- } else {
- releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ if (display.isValidLocked()) {
+ applyDisplayChangedLocked(display);
}
if (mDisplayTopologyCoordinator != null) {
mDisplayTopologyCoordinator.onDisplayRemoved(display.getDisplayIdLocked());
@@ -4565,13 +4549,11 @@ public final class DisplayManagerService extends SystemService {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- if ((internalEventFlagsMask
- & DisplayManagerGlobal
- .INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
- mContext.enforceCallingOrSelfPermission(MANAGE_DISPLAYS,
- "Permission required to get signals about connection events.");
- }
+ if ((internalEventFlagsMask
+ & DisplayManagerGlobal
+ .INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_DISPLAYS,
+ "Permission required to get signals about connection events.");
}
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index e46397bc8ab7..f6b2591ea440 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -179,12 +179,10 @@ class DisplayManagerShellCommand extends ShellCommand {
pw.println(" Sets brightness to docked + idle screen brightness mode");
pw.println(" undock");
pw.println(" Sets brightness to active (normal) screen brightness mode");
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- pw.println(" enable-display DISPLAY_ID");
- pw.println(" Enable the DISPLAY_ID. Only possible if this is a connected display.");
- pw.println(" disable-display DISPLAY_ID");
- pw.println(" Disable the DISPLAY_ID. Only possible if this is a connected display.");
- }
+ pw.println(" enable-display DISPLAY_ID");
+ pw.println(" Enable the DISPLAY_ID. Only possible if this is a connected display.");
+ pw.println(" disable-display DISPLAY_ID");
+ pw.println(" Disable the DISPLAY_ID. Only possible if this is a connected display.");
pw.println(" power-reset DISPLAY_ID");
pw.println(" Turn the DISPLAY_ID power to a state the display supposed to have.");
pw.println(" power-off DISPLAY_ID");
@@ -601,11 +599,6 @@ class DisplayManagerShellCommand extends ShellCommand {
}
private int setDisplayEnabled(boolean enable) {
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- getErrPrintWriter()
- .println("Error: external display management is not available on this device.");
- return 1;
- }
final String displayIdText = getNextArg();
if (displayIdText == null) {
getErrPrintWriter().println("Error: no displayId specified");
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
index 519763a1c3db..a47853c8e555 100644
--- a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
+++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
@@ -142,14 +142,6 @@ class ExternalDisplayPolicy {
mDisplayIdsWaitingForBootCompletion.clear();
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- if (DEBUG) {
- Slog.d(TAG, "External display management is not enabled on your device:"
- + " cannot register thermal listener.");
- }
- return;
- }
-
if (!mFlags.isConnectedDisplayErrorHandlingEnabled()) {
if (DEBUG) {
Slog.d(TAG, "ConnectedDisplayErrorHandlingEnabled is not enabled on your device:"
@@ -173,14 +165,6 @@ class ExternalDisplayPolicy {
return;
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- if (DEBUG) {
- Slog.d(TAG, "setExternalDisplayEnabledLocked: External display management is not"
- + " enabled on your device, cannot enable/disable display.");
- }
- return;
- }
-
if (enabled && !isExternalDisplayAllowed()) {
Slog.w(TAG, "setExternalDisplayEnabledLocked: External display can not be enabled"
+ " because it is currently not allowed.");
@@ -202,14 +186,6 @@ class ExternalDisplayPolicy {
return;
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- if (DEBUG) {
- Slog.d(TAG, "handleExternalDisplayConnectedLocked connected display management"
- + " flag is off");
- }
- return;
- }
-
if (!mIsBootCompleted) {
mDisplayIdsWaitingForBootCompletion.add(logicalDisplay.getDisplayIdLocked());
return;
@@ -251,10 +227,6 @@ class ExternalDisplayPolicy {
void handleLogicalDisplayDisconnectedLocked(@NonNull final LogicalDisplay logicalDisplay) {
// Type of the display here is always UNKNOWN, so we can't verify it is an external display
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- return;
- }
-
var displayId = logicalDisplay.getDisplayIdLocked();
if (mDisplayIdsWaitingForBootCompletion.remove(displayId)) {
return;
@@ -271,10 +243,6 @@ class ExternalDisplayPolicy {
return;
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- return;
- }
-
mExternalDisplayStatsService.onDisplayAdded(logicalDisplay.getDisplayIdLocked());
}
@@ -289,10 +257,6 @@ class ExternalDisplayPolicy {
}
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- return;
- }
-
if (isShown) {
mExternalDisplayStatsService.onPresentationWindowAdded(displayId);
} else {
@@ -306,12 +270,6 @@ class ExternalDisplayPolicy {
return;
}
- if (!mFlags.isConnectedDisplayManagementEnabled()) {
- Slog.e(TAG, "disableExternalDisplayLocked shouldn't be called when the"
- + " connected display management flag is off");
- return;
- }
-
if (!mFlags.isConnectedDisplayErrorHandlingEnabled()) {
if (DEBUG) {
Slog.d(TAG, "disableExternalDisplayLocked shouldn't be called when the"
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 006921572977..ecc8896b69c6 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -823,18 +823,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
if (wasPreviouslyUpdated) {
// The display isn't actually removed from our internal data structures until
// after the notification is sent; see {@link #sendUpdatesForDisplaysLocked}.
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- if (mDisplaysEnabledCache.get(displayId)) {
- // We still need to send LOGICAL_DISPLAY_EVENT_DISCONNECTED
- reloop = true;
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_REMOVED;
- } else {
- mUpdatedLogicalDisplays.delete(displayId);
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_DISCONNECTED;
- }
+ if (mDisplaysEnabledCache.get(displayId)) {
+ // We still need to send LOGICAL_DISPLAY_EVENT_DISCONNECTED
+ reloop = true;
+ logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_REMOVED;
} else {
mUpdatedLogicalDisplays.delete(displayId);
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_REMOVED;
+ logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_DISCONNECTED;
}
} else {
// This display never left this class, safe to remove without notification
@@ -845,20 +840,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
// The display is new.
} else if (!wasPreviouslyUpdated) {
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- // We still need to send LOGICAL_DISPLAY_EVENT_ADDED
- reloop = true;
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_CONNECTED;
- } else {
- logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_ADDED;
- }
+ // We still need to send LOGICAL_DISPLAY_EVENT_ADDED
+ reloop = true;
+ logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_CONNECTED;
// Underlying displays device has changed to a different one.
} else if (!TextUtils.equals(mTempDisplayInfo.uniqueId, newDisplayInfo.uniqueId)) {
logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_SWAPPED;
// Something about the display device has changed.
- } else if (mFlags.isConnectedDisplayManagementEnabled()
- && wasPreviouslyEnabled != isCurrentlyEnabled) {
+ } else if (wasPreviouslyEnabled != isCurrentlyEnabled) {
int event = isCurrentlyEnabled ? LOGICAL_DISPLAY_EVENT_ADDED :
LOGICAL_DISPLAY_EVENT_REMOVED;
logicalDisplayEventMask |= event;
@@ -936,17 +926,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED);
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DISCONNECTED);
- }
+ sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DISCONNECTED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_BASIC_CHANGED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_STATE_CHANGED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED);
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CONNECTED);
- }
+ sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CONNECTED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED);
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED);
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED);
@@ -996,23 +982,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
+ "display=" + id + " with device=" + uniqueId);
}
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_ADDED) {
- mDisplaysEnabledCache.put(id, true);
- } else if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_REMOVED) {
- mDisplaysEnabledCache.delete(id);
- }
+ if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_ADDED) {
+ mDisplaysEnabledCache.put(id, true);
+ } else if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_REMOVED) {
+ mDisplaysEnabledCache.delete(id);
}
mListener.onLogicalDisplayEventLocked(display, logicalDisplayEvent);
- if (mFlags.isConnectedDisplayManagementEnabled()) {
- if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_DISCONNECTED) {
- mLogicalDisplays.delete(id);
- }
- } else if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_REMOVED) {
- // We wait until we sent the EVENT_REMOVED event before actually removing the
- // display.
+ if (logicalDisplayEvent == LOGICAL_DISPLAY_EVENT_DISCONNECTED) {
mLogicalDisplays.delete(id);
}
}
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index addfbf1833b9..4e57d6791ff6 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -42,10 +42,6 @@ public class DisplayManagerFlags {
Flags.FLAG_ENABLE_PORT_IN_DISPLAY_LAYOUT,
Flags::enablePortInDisplayLayout);
- private final FlagState mConnectedDisplayManagementFlagState = new FlagState(
- Flags.FLAG_ENABLE_CONNECTED_DISPLAY_MANAGEMENT,
- Flags::enableConnectedDisplayManagement);
-
private final FlagState mAdaptiveToneImprovements1 = new FlagState(
Flags.FLAG_ENABLE_ADAPTIVE_TONE_IMPROVEMENTS_1,
Flags::enableAdaptiveToneImprovements1);
@@ -269,11 +265,6 @@ public class DisplayManagerFlags {
return mPortInDisplayLayoutFlagState.isEnabled();
}
- /** Returns whether connected display management is enabled or not. */
- public boolean isConnectedDisplayManagementEnabled() {
- return mConnectedDisplayManagementFlagState.isEnabled();
- }
-
/** Returns whether power throttling clamper is enabled on not. */
public boolean isPowerThrottlingClamperEnabled() {
return mPowerThrottlingClamperFlagState.isEnabled();
@@ -572,7 +563,6 @@ public class DisplayManagerFlags {
pw.println(" " + mAdaptiveToneImprovements2);
pw.println(" " + mBackUpSmoothDisplayAndForcePeakRefreshRateFlagState);
pw.println(" " + mConnectedDisplayErrorHandlingFlagState);
- pw.println(" " + mConnectedDisplayManagementFlagState);
pw.println(" " + mDisplayOffloadFlagState);
pw.println(" " + mExternalDisplayLimitModeState);
pw.println(" " + mDisplayTopology);
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index eccbbb14c4ea..afae07c88f8d 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -29,14 +29,6 @@ flag {
}
flag {
- name: "enable_connected_display_management"
- namespace: "display_manager"
- description: "Feature flag for Connected Display management"
- bug: "280739508"
- is_fixed_read_only: true
-}
-
-flag {
name: "enable_power_throttling_clamper"
namespace: "display_manager"
description: "Feature flag for Power Throttling Clamper"
diff --git a/services/core/java/com/android/server/flags/services.aconfig b/services/core/java/com/android/server/flags/services.aconfig
index eea5c982c537..4505d0e2d799 100644
--- a/services/core/java/com/android/server/flags/services.aconfig
+++ b/services/core/java/com/android/server/flags/services.aconfig
@@ -78,3 +78,11 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "datetime_notifications"
+ # "location" is used by the Android System Time team for feature flags.
+ namespace: "location"
+ description: "Enable the time notifications feature, a toggle to enable/disable time-related notifications in Date & Time Settings"
+ bug: "283267917"
+}
diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
index 17d7a14d9129..e1b76222072e 100644
--- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
+++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java
@@ -612,7 +612,7 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable
final PackageSetting staticLibPkgSetting =
mPm.getPackageSettingForMutation(sharedLibraryInfo.getPackageName());
if (staticLibPkgSetting == null) {
- Slog.wtf(TAG, "Shared lib without setting: " + sharedLibraryInfo);
+ Slog.w(TAG, "Shared lib without setting: " + sharedLibraryInfo);
continue;
}
for (int u = 0; u < installedUserCount; u++) {
diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java
index 2049a0288f5a..b651c7ba34c3 100644
--- a/services/core/java/com/android/server/timedetector/ServerFlags.java
+++ b/services/core/java/com/android/server/timedetector/ServerFlags.java
@@ -72,8 +72,12 @@ public final class ServerFlags {
KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT,
KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
KEY_ENHANCED_METRICS_COLLECTION_ENABLED,
+ KEY_TIME_ZONE_NOTIFICATIONS_SUPPORTED,
+ KEY_TIME_ZONE_NOTIFICATIONS_ENABLED_DEFAULT,
+ KEY_TIME_ZONE_NOTIFICATIONS_TRACKING_SUPPORTED,
+ KEY_TIME_ZONE_MANUAL_CHANGE_TRACKING_SUPPORTED
})
- @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+ @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
@Retention(RetentionPolicy.SOURCE)
@interface DeviceConfigKey {}
@@ -192,6 +196,31 @@ public final class ServerFlags {
"enhanced_metrics_collection_enabled";
/**
+ * The key to control support for time zone notifications under certain circumstances.
+ */
+ public static final @DeviceConfigKey String KEY_TIME_ZONE_NOTIFICATIONS_SUPPORTED =
+ "time_zone_notifications_supported";
+
+ /**
+ * The key for the default value used to determine whether time zone notifications is enabled
+ * when the user hasn't explicitly set it yet.
+ */
+ public static final @DeviceConfigKey String KEY_TIME_ZONE_NOTIFICATIONS_ENABLED_DEFAULT =
+ "time_zone_notifications_enabled_default";
+
+ /**
+ * The key to control support for time zone notifications tracking under certain circumstances.
+ */
+ public static final @DeviceConfigKey String KEY_TIME_ZONE_NOTIFICATIONS_TRACKING_SUPPORTED =
+ "time_zone_notifications_tracking_supported";
+
+ /**
+ * The key to control support for time zone manual change tracking under certain circumstances.
+ */
+ public static final @DeviceConfigKey String KEY_TIME_ZONE_MANUAL_CHANGE_TRACKING_SUPPORTED =
+ "time_zone_manual_change_tracking_supported";
+
+ /**
* The registered listeners and the keys to trigger on. The value is explicitly a HashSet to
* ensure O(1) lookup performance when working out whether a listener should trigger.
*/
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index 3579246b660f..0495f54cb154 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -286,7 +286,8 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
// This check is racey, but the whole settings update process is racey. This check prevents
// a ConfigurationChangeListener callback triggering due to ContentObserver's still
// triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
- // for stable behavior during tests.
+ // for stable behavior during tests. This behavior is copied from
+ // setAutoDetectionEnabledIfRequired and assumed to be the correct way.
if (getAutoDetectionEnabledSetting() != enabled) {
Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME, enabled ? 1 : 0);
}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index fc659c5cb627..c4c86a429dd6 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -65,6 +65,10 @@ public final class ConfigurationInternal {
private final boolean mUserConfigAllowed;
private final boolean mLocationEnabledSetting;
private final boolean mGeoDetectionEnabledSetting;
+ private final boolean mNotificationsSupported;
+ private final boolean mNotificationsEnabledSetting;
+ private final boolean mNotificationTrackingSupported;
+ private final boolean mManualChangeTrackingSupported;
private ConfigurationInternal(Builder builder) {
mTelephonyDetectionSupported = builder.mTelephonyDetectionSupported;
@@ -78,6 +82,10 @@ public final class ConfigurationInternal {
mUserConfigAllowed = builder.mUserConfigAllowed;
mLocationEnabledSetting = builder.mLocationEnabledSetting;
mGeoDetectionEnabledSetting = builder.mGeoDetectionEnabledSetting;
+ mNotificationsSupported = builder.mNotificationsSupported;
+ mNotificationsEnabledSetting = builder.mNotificationsEnabledSetting;
+ mNotificationTrackingSupported = builder.mNotificationsTrackingSupported;
+ mManualChangeTrackingSupported = builder.mManualChangeTrackingSupported;
}
/** Returns true if the device supports any form of auto time zone detection. */
@@ -104,6 +112,27 @@ public final class ConfigurationInternal {
}
/**
+ * Returns true if the device supports time-related notifications.
+ */
+ public boolean areNotificationsSupported() {
+ return mNotificationsSupported;
+ }
+
+ /**
+ * Returns true if the device supports tracking of time-related notifications.
+ */
+ public boolean isNotificationTrackingSupported() {
+ return areNotificationsSupported() && mNotificationTrackingSupported;
+ }
+
+ /**
+ * Returns true if the device supports tracking of time zone manual changes.
+ */
+ public boolean isManualChangeTrackingSupported() {
+ return mManualChangeTrackingSupported;
+ }
+
+ /**
* Returns {@code true} if location time zone detection should run when auto time zone detection
* is enabled on supported devices, even when the user has not enabled the algorithm explicitly
* in settings. Enabled for internal testing only. See {@link #isGeoDetectionExecutionEnabled()}
@@ -223,6 +252,15 @@ public final class ConfigurationInternal {
&& getGeoDetectionRunInBackgroundEnabledSetting();
}
+ /** Returns true if time-related notifications can be shown on this device. */
+ public boolean getNotificationsEnabledBehavior() {
+ return areNotificationsSupported() && getNotificationsEnabledSetting();
+ }
+
+ private boolean getNotificationsEnabledSetting() {
+ return mNotificationsEnabledSetting;
+ }
+
@NonNull
public TimeZoneCapabilities asCapabilities(boolean bypassUserPolicyChecks) {
UserHandle userHandle = UserHandle.of(mUserId);
@@ -283,6 +321,14 @@ public final class ConfigurationInternal {
}
builder.setSetManualTimeZoneCapability(suggestManualTimeZoneCapability);
+ final @CapabilityState int configureNotificationsEnabledCapability;
+ if (areNotificationsSupported()) {
+ configureNotificationsEnabledCapability = CAPABILITY_POSSESSED;
+ } else {
+ configureNotificationsEnabledCapability = CAPABILITY_NOT_SUPPORTED;
+ }
+ builder.setConfigureNotificationsEnabledCapability(configureNotificationsEnabledCapability);
+
return builder.build();
}
@@ -291,6 +337,7 @@ public final class ConfigurationInternal {
return new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(getAutoDetectionEnabledSetting())
.setGeoDetectionEnabled(getGeoDetectionEnabledSetting())
+ .setNotificationsEnabled(getNotificationsEnabledSetting())
.build();
}
@@ -307,6 +354,9 @@ public final class ConfigurationInternal {
if (newConfiguration.hasIsGeoDetectionEnabled()) {
builder.setGeoDetectionEnabledSetting(newConfiguration.isGeoDetectionEnabled());
}
+ if (newConfiguration.hasIsNotificationsEnabled()) {
+ builder.setNotificationsEnabledSetting(newConfiguration.areNotificationsEnabled());
+ }
return builder.build();
}
@@ -328,7 +378,11 @@ public final class ConfigurationInternal {
&& mEnhancedMetricsCollectionEnabled == that.mEnhancedMetricsCollectionEnabled
&& mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
&& mLocationEnabledSetting == that.mLocationEnabledSetting
- && mGeoDetectionEnabledSetting == that.mGeoDetectionEnabledSetting;
+ && mGeoDetectionEnabledSetting == that.mGeoDetectionEnabledSetting
+ && mNotificationsSupported == that.mNotificationsSupported
+ && mNotificationsEnabledSetting == that.mNotificationsEnabledSetting
+ && mNotificationTrackingSupported == that.mNotificationTrackingSupported
+ && mManualChangeTrackingSupported == that.mManualChangeTrackingSupported;
}
@Override
@@ -336,7 +390,9 @@ public final class ConfigurationInternal {
return Objects.hash(mUserId, mUserConfigAllowed, mTelephonyDetectionSupported,
mGeoDetectionSupported, mTelephonyFallbackSupported,
mGeoDetectionRunInBackgroundEnabled, mEnhancedMetricsCollectionEnabled,
- mAutoDetectionEnabledSetting, mLocationEnabledSetting, mGeoDetectionEnabledSetting);
+ mAutoDetectionEnabledSetting, mLocationEnabledSetting, mGeoDetectionEnabledSetting,
+ mNotificationsSupported, mNotificationsEnabledSetting,
+ mNotificationTrackingSupported, mManualChangeTrackingSupported);
}
@Override
@@ -352,6 +408,10 @@ public final class ConfigurationInternal {
+ ", mAutoDetectionEnabledSetting=" + mAutoDetectionEnabledSetting
+ ", mLocationEnabledSetting=" + mLocationEnabledSetting
+ ", mGeoDetectionEnabledSetting=" + mGeoDetectionEnabledSetting
+ + ", mNotificationsSupported=" + mNotificationsSupported
+ + ", mNotificationsEnabledSetting=" + mNotificationsEnabledSetting
+ + ", mNotificationTrackingSupported=" + mNotificationTrackingSupported
+ + ", mManualChangeTrackingSupported=" + mManualChangeTrackingSupported
+ '}';
}
@@ -370,6 +430,10 @@ public final class ConfigurationInternal {
private boolean mAutoDetectionEnabledSetting;
private boolean mLocationEnabledSetting;
private boolean mGeoDetectionEnabledSetting;
+ private boolean mNotificationsSupported;
+ private boolean mNotificationsEnabledSetting;
+ private boolean mNotificationsTrackingSupported;
+ private boolean mManualChangeTrackingSupported;
/**
* Creates a new Builder.
@@ -390,6 +454,10 @@ public final class ConfigurationInternal {
this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
this.mLocationEnabledSetting = toCopy.mLocationEnabledSetting;
this.mGeoDetectionEnabledSetting = toCopy.mGeoDetectionEnabledSetting;
+ this.mNotificationsSupported = toCopy.mNotificationsSupported;
+ this.mNotificationsEnabledSetting = toCopy.mNotificationsEnabledSetting;
+ this.mNotificationsTrackingSupported = toCopy.mNotificationTrackingSupported;
+ this.mManualChangeTrackingSupported = toCopy.mManualChangeTrackingSupported;
}
/**
@@ -475,6 +543,38 @@ public final class ConfigurationInternal {
return this;
}
+ /**
+ * Sets the value of the time notification setting for this user.
+ */
+ public Builder setNotificationsEnabledSetting(boolean enabled) {
+ mNotificationsEnabledSetting = enabled;
+ return this;
+ }
+
+ /**
+ * Sets whether time zone notifications are supported on this device.
+ */
+ public Builder setNotificationsSupported(boolean enabled) {
+ mNotificationsSupported = enabled;
+ return this;
+ }
+
+ /**
+ * Sets whether time zone notification tracking is supported on this device.
+ */
+ public Builder setNotificationsTrackingSupported(boolean supported) {
+ mNotificationsTrackingSupported = supported;
+ return this;
+ }
+
+ /**
+ * Sets whether time zone manual change tracking are supported on this device.
+ */
+ public Builder setManualChangeTrackingSupported(boolean supported) {
+ mManualChangeTrackingSupported = supported;
+ return this;
+ }
+
/** Returns a new {@link ConfigurationInternal}. */
@NonNull
public ConfigurationInternal build() {
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
index f1248a3f5f0e..d809fc6b6eea 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
@@ -68,7 +68,11 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
ServerFlags.KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT,
- ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED
+ ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_SUPPORTED,
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_ENABLED_DEFAULT,
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_TRACKING_SUPPORTED,
+ ServerFlags.KEY_TIME_ZONE_MANUAL_CHANGE_TRACKING_SUPPORTED
);
/**
@@ -100,11 +104,16 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
@Nullable
private static ServiceConfigAccessor sInstance;
- @NonNull private final Context mContext;
- @NonNull private final ServerFlags mServerFlags;
- @NonNull private final ContentResolver mCr;
- @NonNull private final UserManager mUserManager;
- @NonNull private final LocationManager mLocationManager;
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final ServerFlags mServerFlags;
+ @NonNull
+ private final ContentResolver mCr;
+ @NonNull
+ private final UserManager mUserManager;
+ @NonNull
+ private final LocationManager mLocationManager;
@GuardedBy("this")
@NonNull
@@ -193,6 +202,9 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
contentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE_EXPLICIT), true,
contentObserver);
+ contentResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.TIME_ZONE_NOTIFICATIONS), true,
+ contentObserver);
// Add async callbacks for user scoped location settings being changed.
contentResolver.registerContentObserver(
@@ -331,6 +343,14 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
setGeoDetectionEnabledSettingIfRequired(userId, geoDetectionEnabledSetting);
}
}
+
+ if (areNotificationsSupported()) {
+ if (requestedConfigurationUpdates.hasIsNotificationsEnabled()) {
+ setNotificationsEnabledSetting(
+ requestedConfigurationUpdates.areNotificationsEnabled());
+ }
+ setNotificationsEnabledIfRequired(newConfiguration.areNotificationsEnabled());
+ }
}
@Override
@@ -348,6 +368,10 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
.setUserConfigAllowed(isUserConfigAllowed(userId))
.setLocationEnabledSetting(getLocationEnabledSetting(userId))
.setGeoDetectionEnabledSetting(getGeoDetectionEnabledSetting(userId))
+ .setNotificationsSupported(areNotificationsSupported())
+ .setNotificationsEnabledSetting(getNotificationsEnabledSetting())
+ .setNotificationsTrackingSupported(isNotificationTrackingSupported())
+ .setManualChangeTrackingSupported(isManualChangeTrackingSupported())
.build();
}
@@ -421,6 +445,49 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
}
}
+ private boolean areNotificationsSupported() {
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_SUPPORTED,
+ getConfigBoolean(R.bool.config_enableTimeZoneNotificationsSupported));
+ }
+
+ private boolean isNotificationTrackingSupported() {
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_TRACKING_SUPPORTED,
+ getConfigBoolean(R.bool.config_enableTimeZoneNotificationsTrackingSupported));
+ }
+
+ private boolean isManualChangeTrackingSupported() {
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_TIME_ZONE_MANUAL_CHANGE_TRACKING_SUPPORTED,
+ getConfigBoolean(R.bool.config_enableTimeZoneManualChangeTrackingSupported));
+ }
+
+ private boolean getNotificationsEnabledSetting() {
+ final boolean notificationsEnabledByDefault = areNotificationsEnabledByDefault();
+ return Settings.Global.getInt(mCr, Settings.Global.TIME_ZONE_NOTIFICATIONS,
+ (notificationsEnabledByDefault ? 1 : 0) /* defaultValue */) != 0;
+ }
+
+ private boolean areNotificationsEnabledByDefault() {
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_TIME_ZONE_NOTIFICATIONS_ENABLED_DEFAULT, true);
+ }
+
+ private void setNotificationsEnabledSetting(boolean enabled) {
+ Settings.Global.putInt(mCr, Settings.Global.TIME_ZONE_NOTIFICATIONS, enabled ? 1 : 0);
+ }
+
+ private void setNotificationsEnabledIfRequired(boolean enabled) {
+ // This check is racey, but the whole settings update process is racey. This check prevents
+ // a ConfigurationChangeListener callback triggering due to ContentObserver's still
+ // triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
+ // for stable behavior during tests.
+ if (getNotificationsEnabledSetting() != enabled) {
+ Settings.Global.putInt(mCr, Settings.Global.TIME_ZONE_NOTIFICATIONS, enabled ? 1 : 0);
+ }
+ }
+
@Override
public void addLocationTimeZoneManagerConfigListener(
@NonNull StateChangeListener listener) {
@@ -441,8 +508,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
@Override
public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
- return mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection);
+ return getConfigBoolean(R.bool.config_enableGeolocationTimeZoneDetection);
}
@Override
@@ -660,8 +726,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
private boolean isTelephonyFallbackSupported() {
return mServerFlags.getBoolean(
ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
- getConfigBoolean(
- com.android.internal.R.bool.config_supportTelephonyTimeZoneFallback));
+ getConfigBoolean(R.bool.config_supportTelephonyTimeZoneFallback));
}
private boolean getConfigBoolean(int providerEnabledConfigId) {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneChangeListener.java b/services/core/java/com/android/server/timezonedetector/TimeZoneChangeListener.java
new file mode 100644
index 000000000000..e14326cc2d53
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneChangeListener.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezonedetector;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.util.IndentingPrintWriter;
+
+import com.android.server.SystemTimeZone.TimeZoneConfidence;
+import com.android.server.timezonedetector.TimeZoneDetectorStrategy.Origin;
+
+import java.util.Objects;
+
+public interface TimeZoneChangeListener {
+
+ /** Record a time zone change. */
+ void process(TimeZoneChangeEvent event);
+
+ /** Dump internal state. */
+ void dump(IndentingPrintWriter ipw);
+
+ class TimeZoneChangeEvent {
+
+ private final @ElapsedRealtimeLong long mElapsedRealtimeMillis;
+ private final @CurrentTimeMillisLong long mUnixEpochTimeMillis;
+ private final @Origin int mOrigin;
+ private final @UserIdInt int mUserId;
+ private final String mOldZoneId;
+ private final String mNewZoneId;
+ private final @TimeZoneConfidence int mNewConfidence;
+ private final String mCause;
+
+ public TimeZoneChangeEvent(@ElapsedRealtimeLong long elapsedRealtimeMillis,
+ @CurrentTimeMillisLong long unixEpochTimeMillis,
+ @Origin int origin, @UserIdInt int userId, @NonNull String oldZoneId,
+ @NonNull String newZoneId, int newConfidence, @NonNull String cause) {
+ mElapsedRealtimeMillis = elapsedRealtimeMillis;
+ mUnixEpochTimeMillis = unixEpochTimeMillis;
+ mOrigin = origin;
+ mUserId = userId;
+ mOldZoneId = Objects.requireNonNull(oldZoneId);
+ mNewZoneId = Objects.requireNonNull(newZoneId);
+ mNewConfidence = newConfidence;
+ mCause = Objects.requireNonNull(cause);
+ }
+
+ public @ElapsedRealtimeLong long getElapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ public @CurrentTimeMillisLong long getUnixEpochTimeMillis() {
+ return mUnixEpochTimeMillis;
+ }
+
+ public @Origin int getOrigin() {
+ return mOrigin;
+ }
+
+ /**
+ * The ID of the user that triggered the change.
+ *
+ * <p>If automatic time zone is turned on, the user ID returned is the system's user id.
+ */
+ public @UserIdInt int getUserId() {
+ return mUserId;
+ }
+
+ public String getOldZoneId() {
+ return mOldZoneId;
+ }
+
+ public String getNewZoneId() {
+ return mNewZoneId;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneChangeEvent{"
+ + "mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+ + ", mUnixEpochTimeMillis=" + mUnixEpochTimeMillis
+ + ", mOrigin=" + mOrigin
+ + ", mUserId=" + mUserId
+ + ", mOldZoneId='" + mOldZoneId + '\''
+ + ", mNewZoneId='" + mNewZoneId + '\''
+ + ", mNewConfidence=" + mNewConfidence
+ + ", mCause='" + mCause + '\''
+ + '}';
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index d914544566ff..af02ad88ad6a 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -18,6 +18,7 @@ package com.android.server.timezonedetector;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.time.ITimeZoneDetectorListener;
import android.app.time.TimeZoneCapabilitiesAndConfig;
@@ -73,6 +74,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
}
@Override
+ @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL")
public void onStart() {
// Obtain / create the shared dependencies.
Context context = getContext();
@@ -81,7 +83,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
ServiceConfigAccessor serviceConfigAccessor =
ServiceConfigAccessorImpl.getInstance(context);
TimeZoneDetectorStrategy timeZoneDetectorStrategy =
- TimeZoneDetectorStrategyImpl.create(handler, serviceConfigAccessor);
+ TimeZoneDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
DeviceActivityMonitor deviceActivityMonitor =
DeviceActivityMonitorImpl.create(context, handler);
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 37e67c921634..8cfbe9daa970 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -15,6 +15,7 @@
*/
package com.android.server.timezonedetector;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.time.TimeZoneCapabilitiesAndConfig;
@@ -24,6 +25,11 @@ import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.util.IndentingPrintWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
/**
* The interface for the class that is responsible for setting the time zone on a device, used by
* {@link TimeZoneDetectorService} and {@link TimeZoneDetectorInternal}.
@@ -97,6 +103,22 @@ import android.util.IndentingPrintWriter;
* @hide
*/
public interface TimeZoneDetectorStrategy extends Dumpable {
+ @IntDef({ ORIGIN_UNKNOWN, ORIGIN_MANUAL, ORIGIN_TELEPHONY, ORIGIN_LOCATION })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+ @interface Origin {}
+
+ /** Used when the origin of the time zone value cannot be inferred. */
+ @Origin int ORIGIN_UNKNOWN = 0;
+
+ /** Used when a time zone value originated from a user / manual settings. */
+ @Origin int ORIGIN_MANUAL = 1;
+
+ /** Used when a time zone value originated from a telephony signal. */
+ @Origin int ORIGIN_TELEPHONY = 2;
+
+ /** Used when a time zone value originated from a location signal. */
+ @Origin int ORIGIN_LOCATION = 3;
/**
* Adds a listener that will be triggered when something changes that could affect the result
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index dddb46f80724..19a28ddcdaeb 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -28,6 +28,7 @@ import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_LOW;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.time.DetectorStatusTypes;
import android.app.time.LocationTimeZoneAlgorithmStatus;
@@ -39,8 +40,10 @@ import android.app.time.TimeZoneDetectorStatus;
import android.app.time.TimeZoneState;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
+import android.content.Context;
import android.os.Handler;
import android.os.TimestampedValue;
+import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -72,12 +75,14 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* Returns the device's currently configured time zone. May return an empty string.
*/
- @NonNull String getDeviceTimeZone();
+ @NonNull
+ String getDeviceTimeZone();
/**
* Returns the confidence of the device's current time zone.
*/
- @TimeZoneConfidence int getDeviceTimeZoneConfidence();
+ @TimeZoneConfidence
+ int getDeviceTimeZoneConfidence();
/**
* Sets the device's time zone, associated confidence, and records a debug log entry.
@@ -115,7 +120,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* The abstract score for an empty or invalid telephony suggestion.
*
- * Used to score telephony suggestions where there is no zone.
+ * <p>Used to score telephony suggestions where there is no zone.
*/
@VisibleForTesting
public static final int TELEPHONY_SCORE_NONE = 0;
@@ -123,11 +128,11 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* The abstract score for a low quality telephony suggestion.
*
- * Used to score suggestions where:
- * The suggested zone ID is one of several possibilities, and the possibilities have different
- * offsets.
+ * <p>Used to score suggestions where:
+ * The suggested zone ID is one of several possibilities,
+ * and the possibilities have different offsets.
*
- * You would have to be quite desperate to want to use this choice.
+ * <p>You would have to be quite desperate to want to use this choice.
*/
@VisibleForTesting
public static final int TELEPHONY_SCORE_LOW = 1;
@@ -135,7 +140,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* The abstract score for a medium quality telephony suggestion.
*
- * Used for:
+ * <p>Used for:
* The suggested zone ID is one of several possibilities but at least the possibilities have the
* same offset. Users would get the correct time but for the wrong reason. i.e. their device may
* switch to DST at the wrong time and (for example) their calendar events.
@@ -146,7 +151,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* The abstract score for a high quality telephony suggestion.
*
- * Used for:
+ * <p>Used for:
* The suggestion was for one zone ID and the answer was unambiguous and likely correct given
* the info available.
*/
@@ -156,7 +161,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* The abstract score for a highest quality telephony suggestion.
*
- * Used for:
+ * <p>Used for:
* Suggestions that must "win" because they constitute test or emulator zone ID.
*/
@VisibleForTesting
@@ -206,7 +211,8 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
private final ServiceConfigAccessor mServiceConfigAccessor;
@GuardedBy("this")
- @NonNull private final List<StateChangeListener> mStateChangeListeners = new ArrayList<>();
+ @NonNull
+ private final List<StateChangeListener> mStateChangeListeners = new ArrayList<>();
/**
* A snapshot of the current detector status. A local copy is cached because it is relatively
@@ -244,8 +250,10 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
/**
* Creates a new instance of {@link TimeZoneDetectorStrategyImpl}.
*/
+ @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL")
public static TimeZoneDetectorStrategyImpl create(
- @NonNull Handler handler, @NonNull ServiceConfigAccessor serviceConfigAccessor) {
+ @NonNull Context context, @NonNull Handler handler,
+ @NonNull ServiceConfigAccessor serviceConfigAccessor) {
Environment environment = new EnvironmentImpl(handler);
return new TimeZoneDetectorStrategyImpl(serviceConfigAccessor, environment);
@@ -468,7 +476,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// later disables automatic time zone detection.
mLatestManualSuggestion.set(suggestion);
- setDeviceTimeZoneIfRequired(timeZoneId, cause);
+ setDeviceTimeZoneIfRequired(timeZoneId, ORIGIN_MANUAL, userId, cause);
return true;
}
@@ -685,7 +693,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// GeolocationTimeZoneSuggestion has no measure of quality. We assume all suggestions are
// reliable.
- String zoneId;
+ String timeZoneId;
// Introduce bias towards the device's current zone when there are multiple zone suggested.
String deviceTimeZone = mEnvironment.getDeviceTimeZone();
@@ -694,11 +702,12 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
Slog.d(LOG_TAG,
"Geo tz suggestion contains current device time zone. Applying bias.");
}
- zoneId = deviceTimeZone;
+ timeZoneId = deviceTimeZone;
} else {
- zoneId = zoneIds.get(0);
+ timeZoneId = zoneIds.get(0);
}
- setDeviceTimeZoneIfRequired(zoneId, detectionReason);
+ setDeviceTimeZoneIfRequired(timeZoneId, ORIGIN_LOCATION, UserHandle.USER_SYSTEM,
+ detectionReason);
return true;
}
@@ -779,8 +788,8 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// Paranoia: Every suggestion above the SCORE_USAGE_THRESHOLD should have a non-null time
// zone ID.
- String zoneId = bestTelephonySuggestion.suggestion.getZoneId();
- if (zoneId == null) {
+ String timeZoneId = bestTelephonySuggestion.suggestion.getZoneId();
+ if (timeZoneId == null) {
Slog.w(LOG_TAG, "Empty zone suggestion scored higher than expected. This is an error:"
+ " bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason);
@@ -790,11 +799,12 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
String cause = "Found good suggestion:"
+ " bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason;
- setDeviceTimeZoneIfRequired(zoneId, cause);
+ setDeviceTimeZoneIfRequired(timeZoneId, ORIGIN_TELEPHONY, UserHandle.USER_SYSTEM, cause);
}
@GuardedBy("this")
- private void setDeviceTimeZoneIfRequired(@NonNull String newZoneId, @NonNull String cause) {
+ private void setDeviceTimeZoneIfRequired(@NonNull String newZoneId, @Origin int origin,
+ @UserIdInt int userId, @NonNull String cause) {
String currentZoneId = mEnvironment.getDeviceTimeZone();
// All manual and automatic suggestions are considered high confidence as low-quality
// suggestions are not currently passed on.
diff --git a/services/core/java/com/android/server/vibrator/BasicToPwleSegmentAdapter.java b/services/core/java/com/android/server/vibrator/BasicToPwleSegmentAdapter.java
index 54ae047a2858..0b676ff7d590 100644
--- a/services/core/java/com/android/server/vibrator/BasicToPwleSegmentAdapter.java
+++ b/services/core/java/com/android/server/vibrator/BasicToPwleSegmentAdapter.java
@@ -100,6 +100,11 @@ final class BasicToPwleSegmentAdapter implements VibrationSegmentsAdapter {
}
VibratorInfo.FrequencyProfile frequencyProfile = info.getFrequencyProfile();
+ if (frequencyProfile.isEmpty()) {
+ // The frequency profile has an invalid frequency range, so keep the segments unchanged.
+ return repeatIndex;
+ }
+
float[] frequenciesHz = frequencyProfile.getFrequenciesHz();
float[] accelerationsGs = frequencyProfile.getOutputAccelerationsGs();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 89c7a3d89a54..6f308aa9b706 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -1631,7 +1631,7 @@ class ActivityMetricsLogger {
int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__NOT_LETTERBOXED_POSITION;
if (isAppCompateStateChangedToLetterboxed(state)) {
- positionToLog = activity.mAppCompatController.getAppCompatReachabilityOverrides()
+ positionToLog = activity.mAppCompatController.getReachabilityOverrides()
.getLetterboxPositionForLogging();
}
FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPAT_STATE_CHANGED,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 29f1f93a844f..3e6315635571 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -8744,7 +8744,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
navBarInsets = Insets.NONE;
}
final AppCompatReachabilityOverrides reachabilityOverrides =
- mAppCompatController.getAppCompatReachabilityOverrides();
+ mAppCompatController.getReachabilityOverrides();
// Horizontal position
int offsetX = 0;
if (parentBounds.width() != screenResolvedBoundsWidth) {
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index 0967078deac3..c748264a833e 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -33,7 +33,7 @@ class AppCompatController {
@NonNull
private final AppCompatAspectRatioPolicy mAppCompatAspectRatioPolicy;
@NonNull
- private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy;
+ private final AppCompatReachabilityPolicy mReachabilityPolicy;
@NonNull
private final DesktopAppCompatAspectRatioPolicy mDesktopAppCompatAspectRatioPolicy;
@NonNull
@@ -58,7 +58,7 @@ class AppCompatController {
mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord, mAppCompatOverrides);
mAppCompatAspectRatioPolicy = new AppCompatAspectRatioPolicy(activityRecord,
mTransparentPolicy, mAppCompatOverrides);
- mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(activityRecord,
+ mReachabilityPolicy = new AppCompatReachabilityPolicy(activityRecord,
wmService.mAppCompatConfiguration);
mAppCompatLetterboxPolicy = new AppCompatLetterboxPolicy(activityRecord,
wmService.mAppCompatConfiguration);
@@ -109,8 +109,8 @@ class AppCompatController {
}
@NonNull
- AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() {
- return mAppCompatReachabilityPolicy;
+ AppCompatReachabilityPolicy getReachabilityPolicy() {
+ return mReachabilityPolicy;
}
@NonNull
@@ -124,8 +124,8 @@ class AppCompatController {
}
@NonNull
- AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
- return mAppCompatOverrides.getAppCompatReachabilityOverrides();
+ AppCompatReachabilityOverrides getReachabilityOverrides() {
+ return mAppCompatOverrides.getReachabilityOverrides();
}
@NonNull
diff --git a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
index e929fb414340..8866e39fecc9 100644
--- a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
@@ -205,7 +205,7 @@ class AppCompatLetterboxPolicy {
}
pw.println(prefix + " letterboxReason="
+ AppCompatUtils.getLetterboxReasonString(mActivityRecord, mainWin));
- mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy().dump(pw, prefix);
+ mActivityRecord.mAppCompatController.getReachabilityPolicy().dump(pw, prefix);
final AppCompatLetterboxOverrides letterboxOverride = mActivityRecord.mAppCompatController
.getAppCompatLetterboxOverrides();
pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString(
@@ -276,12 +276,12 @@ class AppCompatLetterboxPolicy {
final AppCompatLetterboxOverrides letterboxOverrides = mActivityRecord
.mAppCompatController.getAppCompatLetterboxOverrides();
final AppCompatReachabilityPolicy reachabilityPolicy = mActivityRecord
- .mAppCompatController.getAppCompatReachabilityPolicy();
+ .mAppCompatController.getReachabilityPolicy();
mLetterbox = new Letterbox(() -> mActivityRecord.makeChildSurface(null),
mActivityRecord.mWmService.mTransactionFactory,
reachabilityPolicy, letterboxOverrides,
this::getLetterboxParentSurface);
- mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivityRecord.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(mLetterbox::getInnerFrame);
}
final Point letterboxPosition = new Point();
@@ -291,7 +291,7 @@ class AppCompatLetterboxPolicy {
final Rect innerFrame = new Rect();
calculateLetterboxInnerBounds(mActivityRecord, w, innerFrame);
mLetterbox.layout(spaceToFill, innerFrame, letterboxPosition);
- if (mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides()
+ if (mActivityRecord.mAppCompatController.getReachabilityOverrides()
.isDoubleTapEvent()) {
// We need to notify Shell that letterbox position has changed.
mActivityRecord.getTask().dispatchTaskInfoChangedIfNeeded(true /* force */);
@@ -321,7 +321,7 @@ class AppCompatLetterboxPolicy {
mLetterbox.destroy();
mLetterbox = null;
}
- mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivityRecord.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(null);
}
@@ -415,7 +415,7 @@ class AppCompatLetterboxPolicy {
calculateLetterboxPosition(mActivityRecord, mLetterboxPosition);
calculateLetterboxOuterBounds(mActivityRecord, mOuterBounds);
calculateLetterboxInnerBounds(mActivityRecord, w, mInnerBounds);
- mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivityRecord.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(() -> mInnerBounds);
}
@@ -438,7 +438,7 @@ class AppCompatLetterboxPolicy {
mLetterboxPosition.set(0, 0);
mInnerBounds.setEmpty();
mOuterBounds.setEmpty();
- mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivityRecord.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(null);
}
diff --git a/services/core/java/com/android/server/wm/AppCompatOverrides.java b/services/core/java/com/android/server/wm/AppCompatOverrides.java
index 58b37becc373..9effae6aa640 100644
--- a/services/core/java/com/android/server/wm/AppCompatOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatOverrides.java
@@ -37,7 +37,7 @@ public class AppCompatOverrides {
@NonNull
private final AppCompatResizeOverrides mResizeOverrides;
@NonNull
- private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
+ private final AppCompatReachabilityOverrides mReachabilityOverrides;
@NonNull
private final AppCompatLetterboxOverrides mAppCompatLetterboxOverrides;
@@ -50,11 +50,11 @@ public class AppCompatOverrides {
appCompatConfiguration, optPropBuilder);
mAppCompatOrientationOverrides = new AppCompatOrientationOverrides(activityRecord,
appCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides);
- mAppCompatReachabilityOverrides = new AppCompatReachabilityOverrides(activityRecord,
+ mReachabilityOverrides = new AppCompatReachabilityOverrides(activityRecord,
appCompatConfiguration, appCompatDeviceStateQuery);
mAppCompatAspectRatioOverrides = new AppCompatAspectRatioOverrides(activityRecord,
appCompatConfiguration, optPropBuilder, appCompatDeviceStateQuery,
- mAppCompatReachabilityOverrides);
+ mReachabilityOverrides);
mAppCompatFocusOverrides = new AppCompatFocusOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
mResizeOverrides = new AppCompatResizeOverrides(activityRecord, packageManager,
@@ -89,8 +89,8 @@ public class AppCompatOverrides {
}
@NonNull
- AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
- return mAppCompatReachabilityOverrides;
+ AppCompatReachabilityOverrides getReachabilityOverrides() {
+ return mReachabilityOverrides;
}
@NonNull
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
index d03a80387657..087edc184b6f 100644
--- a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
@@ -77,7 +77,7 @@ class AppCompatReachabilityPolicy {
void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
final AppCompatReachabilityOverrides reachabilityOverrides =
- mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ mActivityRecord.mAppCompatController.getReachabilityOverrides();
pw.println(prefix + " isVerticalThinLetterboxed=" + reachabilityOverrides
.isVerticalThinLetterboxed());
pw.println(prefix + " isHorizontalThinLetterboxed=" + reachabilityOverrides
@@ -96,7 +96,7 @@ class AppCompatReachabilityPolicy {
private void handleHorizontalDoubleTap(int x) {
final AppCompatReachabilityOverrides reachabilityOverrides =
- mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ mActivityRecord.mAppCompatController.getReachabilityOverrides();
if (!reachabilityOverrides.isHorizontalReachabilityEnabled()
|| mActivityRecord.isInTransition()) {
return;
@@ -142,7 +142,7 @@ class AppCompatReachabilityPolicy {
private void handleVerticalDoubleTap(int y) {
final AppCompatReachabilityOverrides reachabilityOverrides =
- mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ mActivityRecord.mAppCompatController.getReachabilityOverrides();
if (!reachabilityOverrides.isVerticalReachabilityEnabled()
|| mActivityRecord.isInTransition()) {
return;
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index 9f88bc952351..e28dddc496e1 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -138,7 +138,7 @@ final class AppCompatUtils {
return;
}
final AppCompatReachabilityOverrides reachabilityOverrides = top.mAppCompatController
- .getAppCompatReachabilityOverrides();
+ .getReachabilityOverrides();
final boolean isTopActivityResumed = top.getOrganizedTask() == task && top.isState(RESUMED);
final boolean isTopActivityVisible = top.getOrganizedTask() == task && top.isVisible();
// Whether the direct top activity is in size compat mode.
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index a4e58ef923b8..d6ae65193121 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -108,9 +108,7 @@ final class ContentRecorder implements WindowContainerListener {
ContentRecorder(@NonNull DisplayContent displayContent) {
this(displayContent, new RemoteMediaProjectionManagerWrapper(displayContent.mDisplayId),
- new DisplayManagerFlags().isConnectedDisplayManagementEnabled()
- && !new DisplayManagerFlags()
- .isPixelAnisotropyCorrectionInLogicalDisplayEnabled()
+ !new DisplayManagerFlags().isPixelAnisotropyCorrectionInLogicalDisplayEnabled()
&& displayContent.getDisplayInfo().type == Display.TYPE_EXTERNAL);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 3c6778ecbb30..92e0931993d1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -10177,9 +10177,10 @@ public class WindowManagerService extends IWindowManager.Stub
throw new SecurityException("Access denied to process: " + pid
+ ", must have permission " + Manifest.permission.ACCESS_FPS_COUNTER);
}
-
- if (mRoot.anyTaskForId(taskId) == null) {
- throw new IllegalArgumentException("no task with taskId: " + taskId);
+ synchronized (mGlobalLock) {
+ if (mRoot.anyTaskForId(taskId) == null) {
+ throw new IllegalArgumentException("no task with taskId: " + taskId);
+ }
}
mTaskFpsCallbackController.registerListener(taskId, callback);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index a9ad435762ad..02e5470e8673 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -415,7 +415,6 @@ public class DisplayManagerServiceTest {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
mLocalServiceKeeperRule.overrideLocalService(
InputManagerInternal.class, mMockInputManagerInternal);
@@ -2797,30 +2796,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testConnectExternalDisplay_withoutDisplayManagement_shouldAddDisplay() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
- manageDisplaysPermission(/* granted= */ true);
- DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
- DisplayManagerService.BinderService bs = displayManager.new BinderService();
- LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
- FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
- callback.expectsEvent(EVENT_DISPLAY_ADDED);
-
- FakeDisplayDevice displayDevice =
- createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
- callback.waitForExpectedEvent();
-
- LogicalDisplay display =
- logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ true);
- assertThat(display.isEnabledLocked()).isTrue();
- assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_ADDED);
-
- }
-
- @Test
- public void testConnectExternalDisplay_withDisplayManagement_shouldDisableDisplay() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testConnectExternalDisplay_shouldDisableDisplay() {
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -2849,9 +2825,8 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testConnectExternalDisplay_withDisplayManagementAndSysprop_shouldEnableDisplay() {
+ public void testConnectExternalDisplay_withSysprop_shouldEnableDisplay() {
Assume.assumeTrue(Build.IS_ENG || Build.IS_USERDEBUG);
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
doAnswer((Answer<Boolean>) invocationOnMock -> true)
.when(() -> SystemProperties.getBoolean(ENABLE_ON_CONNECT, false));
manageDisplaysPermission(/* granted= */ true);
@@ -2883,8 +2858,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testConnectExternalDisplay_withDisplayManagement_allowsEnableAndDisableDisplay() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testConnectExternalDisplay_allowsEnableAndDisableDisplay() {
when(mMockFlags.isApplyDisplayChangedDuringDisplayAddedEnabled()).thenReturn(true);
manageDisplaysPermission(/* granted= */ true);
LocalServices.addService(WindowManagerPolicy.class, mMockedWindowManagerPolicy);
@@ -2955,8 +2929,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testConnectInternalDisplay_withDisplayManagement_shouldConnectAndAddDisplay() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testConnectInternalDisplay_shouldConnectAndAddDisplay() {
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
@@ -3011,7 +2984,7 @@ public class DisplayManagerServiceTest {
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
- bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+ bs.registerCallbackWithEventMask(callback, STANDARD_DISPLAY_EVENTS);
callback.expectsEvent(EVENT_DISPLAY_ADDED);
FakeDisplayDevice displayDevice =
@@ -3032,8 +3005,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testEnableExternalDisplay_withDisplayManagement_shouldSignalDisplayAdded() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testEnableExternalDisplay_shouldSignalDisplayAdded() {
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -3062,8 +3034,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testEnableExternalDisplay_withoutPermission_shouldThrowException() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testEnableExternalDisplay_shouldThrowException() {
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
@@ -3087,8 +3058,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testEnableInternalDisplay_withManageDisplays_shouldSignalAdded() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testEnableInternalDisplay_shouldSignalAdded() {
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
@@ -3115,8 +3085,7 @@ public class DisplayManagerServiceTest {
}
@Test
- public void testDisableInternalDisplay_withDisplayManagement_shouldSignalRemove() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testDisableInternalDisplay_shouldSignalRemove() {
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
@@ -3140,7 +3109,6 @@ public class DisplayManagerServiceTest {
@Test
public void testDisableExternalDisplay_shouldSignalDisplayRemoved() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
@@ -3181,7 +3149,6 @@ public class DisplayManagerServiceTest {
@Test
public void testDisableExternalDisplay_withoutPermission_shouldThrowException() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
@@ -3207,7 +3174,6 @@ public class DisplayManagerServiceTest {
@Test
public void testRemoveExternalDisplay_whenDisabled_shouldSignalDisconnected() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -3244,7 +3210,6 @@ public class DisplayManagerServiceTest {
@Test
public void testRegisterCallback_withoutPermission_shouldThrow() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
@@ -3255,7 +3220,6 @@ public class DisplayManagerServiceTest {
@Test
public void testRemoveExternalDisplay_whenEnabled_shouldSignalRemovedAndDisconnected() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -3288,7 +3252,6 @@ public class DisplayManagerServiceTest {
@Test
public void testRemoveInternalDisplay_whenEnabled_shouldSignalRemovedAndDisconnected() {
- when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
manageDisplaysPermission(/* granted= */ true);
DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
DisplayManagerService.BinderService bs = displayManager.new BinderService();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
index 782262d3f7c9..a48a88cecbc2 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
@@ -22,7 +22,6 @@ import static android.view.Display.TYPE_INTERNAL;
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -47,7 +46,6 @@ import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.notifications.DisplayNotificationManager;
import com.android.server.testutils.TestHandler;
-import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import org.junit.Before;
@@ -124,7 +122,6 @@ public class ExternalDisplayPolicyTest {
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mHandler = new TestHandler(/*callback=*/ null);
- when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
when(mMockedFlags.isConnectedDisplayErrorHandlingEnabled()).thenReturn(true);
when(mMockedInjector.getFlags()).thenReturn(mMockedFlags);
when(mMockedInjector.getLogicalDisplayMapper()).thenReturn(mMockedLogicalDisplayMapper);
@@ -173,16 +170,6 @@ public class ExternalDisplayPolicyTest {
}
@Test
- public void testTryEnableExternalDisplay_featureDisabled(@TestParameter final boolean enable) {
- when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
- mExternalDisplayPolicy.setExternalDisplayEnabledLocked(mMockedLogicalDisplay, enable);
- mHandler.flush();
- verify(mMockedLogicalDisplayMapper, never()).setDisplayEnabledLocked(any(), anyBoolean());
- verify(mMockedDisplayNotificationManager, never())
- .onHighTemperatureExternalDisplayNotAllowed();
- }
-
- @Test
public void testTryDisableExternalDisplay_criticalThermalCondition() throws RemoteException {
// Disallow external displays due to thermals.
setTemperature(registerThermalListener(), List.of(CRITICAL_TEMPERATURE));
@@ -278,21 +265,6 @@ public class ExternalDisplayPolicyTest {
}
@Test
- public void testNoThermalListenerRegistered_featureDisabled(
- @TestParameter final boolean isConnectedDisplayManagementEnabled,
- @TestParameter final boolean isErrorHandlingEnabled) throws RemoteException {
- assumeFalse(isConnectedDisplayManagementEnabled && isErrorHandlingEnabled);
- when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(
- isConnectedDisplayManagementEnabled);
- when(mMockedFlags.isConnectedDisplayErrorHandlingEnabled()).thenReturn(
- isErrorHandlingEnabled);
-
- mExternalDisplayPolicy.onBootCompleted();
- verify(mMockedThermalService, never()).registerThermalEventListenerWithType(
- any(), anyInt());
- }
-
- @Test
public void testOnCriticalTemperature_disallowAndAllowExternalDisplay() throws RemoteException {
final var thermalListener = registerThermalListener();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 0dbb6ba58b3c..7d3cd8a8a9ae 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -222,7 +222,6 @@ public class LogicalDisplayMapperTest {
when(mSyntheticModeManagerMock.createAppSupportedModes(any(), any(), anyBoolean()))
.thenAnswer(AdditionalAnswers.returnsSecondArg());
- when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(false);
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
@@ -351,8 +350,7 @@ public class LogicalDisplayMapperTest {
}
@Test
- public void testDisplayDeviceAddAndRemove_withDisplayManagement() {
- when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testDisplayDeviceAddAndRemove() {
DisplayDevice device = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
@@ -390,8 +388,7 @@ public class LogicalDisplayMapperTest {
}
@Test
- public void testDisplayDisableEnable_withDisplayManagement() {
- when(mFlagsMock.isConnectedDisplayManagementEnabled()).thenReturn(true);
+ public void testDisplayDisableEnable() {
DisplayDevice device = createDisplayDevice(TYPE_INTERNAL, 600, 800,
FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
LogicalDisplay displayAdded = add(device);
@@ -1350,9 +1347,14 @@ public class LogicalDisplayMapperTest {
ArgumentCaptor<LogicalDisplay> displayCaptor =
ArgumentCaptor.forClass(LogicalDisplay.class);
verify(mListenerMock).onLogicalDisplayEventLocked(
- displayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_ADDED));
+ displayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_CONNECTED));
+ LogicalDisplay display = displayCaptor.getValue();
+ if (display.isEnabledLocked()) {
+ verify(mListenerMock).onLogicalDisplayEventLocked(
+ eq(display), eq(LOGICAL_DISPLAY_EVENT_ADDED));
+ }
clearInvocations(mListenerMock);
- return displayCaptor.getValue();
+ return display;
}
private void testDisplayDeviceAddAndRemove_NonInternal(int type) {
diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/ConfigInternalForTests.java b/services/tests/timetests/src/com/android/server/timezonedetector/ConfigInternalForTests.java
new file mode 100644
index 000000000000..47e3dc85f6d0
--- /dev/null
+++ b/services/tests/timetests/src/com/android/server/timezonedetector/ConfigInternalForTests.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.timezonedetector;
+
+import android.annotation.UserIdInt;
+
+public final class ConfigInternalForTests {
+
+ static final @UserIdInt int USER_ID = 9876;
+
+ static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_DISABLED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(false)
+ .setAutoDetectionEnabledSetting(false)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(false)
+ .build();
+
+ static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_ENABLED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(false)
+ .setAutoDetectionEnabledSetting(true)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(true)
+ .build();
+
+ static final ConfigurationInternal CONFIG_AUTO_DETECT_NOT_SUPPORTED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(false)
+ .setGeoDetectionFeatureSupported(false)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionEnabledSetting(false)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(false)
+ .build();
+
+ static final ConfigurationInternal CONFIG_AUTO_DISABLED_GEO_DISABLED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionEnabledSetting(false)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(false)
+ .build();
+
+ static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_DISABLED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionEnabledSetting(true)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(false)
+ .build();
+
+ static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_ENABLED =
+ new ConfigurationInternal.Builder()
+ .setUserId(USER_ID)
+ .setTelephonyDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
+ .setTelephonyFallbackSupported(false)
+ .setGeoDetectionRunInBackgroundEnabled(false)
+ .setEnhancedMetricsCollectionEnabled(false)
+ .setUserConfigAllowed(true)
+ .setAutoDetectionEnabledSetting(true)
+ .setLocationEnabledSetting(true)
+ .setGeoDetectionEnabledSetting(true)
+ .build();
+}
diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java b/services/tests/timetests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
index fc6afe486187..aeb4d9a19ff0 100644
--- a/services/tests/timetests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
+++ b/services/tests/timetests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
@@ -31,7 +31,7 @@ import java.util.Optional;
/**
* A partially implemented, fake implementation of ServiceConfigAccessor for tests.
*
- * <p>This class has rudamentary support for multiple users, but unlike the real thing, it doesn't
+ * <p>This class has rudimentary support for multiple users, but unlike the real thing, it doesn't
* simulate that some settings are global and shared between users. It also delivers config updates
* synchronously.
*/
diff --git a/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index e52e8b60a61d..47a9b2c47173 100644
--- a/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/timetests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -35,6 +35,12 @@ import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_U
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_LOW;
+import static com.android.server.timezonedetector.ConfigInternalForTests.CONFIG_AUTO_DETECT_NOT_SUPPORTED;
+import static com.android.server.timezonedetector.ConfigInternalForTests.CONFIG_AUTO_DISABLED_GEO_DISABLED;
+import static com.android.server.timezonedetector.ConfigInternalForTests.CONFIG_AUTO_ENABLED_GEO_DISABLED;
+import static com.android.server.timezonedetector.ConfigInternalForTests.CONFIG_AUTO_ENABLED_GEO_ENABLED;
+import static com.android.server.timezonedetector.ConfigInternalForTests.CONFIG_USER_RESTRICTED_AUTO_ENABLED;
+import static com.android.server.timezonedetector.ConfigInternalForTests.USER_ID;
import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_HIGH;
import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_HIGHEST;
import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_LOW;
@@ -68,6 +74,7 @@ import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
import android.service.timezone.TimeZoneProviderStatus;
+import android.util.IndentingPrintWriter;
import com.android.server.SystemTimeZone.TimeZoneConfidence;
import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
@@ -82,6 +89,7 @@ import org.junit.runner.RunWith;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
@@ -92,7 +100,6 @@ import java.util.function.Function;
@RunWith(JUnitParamsRunner.class)
public class TimeZoneDetectorStrategyImplTest {
- private static final @UserIdInt int USER_ID = 9876;
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234;
/** A time zone used for initialization that does not occur elsewhere in tests. */
private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC";
@@ -101,7 +108,7 @@ public class TimeZoneDetectorStrategyImplTest {
// Telephony test cases are ordered so that each successive one is of the same or higher score
// than the previous.
- private static final TelephonyTestCase[] TELEPHONY_TEST_CASES = new TelephonyTestCase[] {
+ private static final TelephonyTestCase[] TELEPHONY_TEST_CASES = new TelephonyTestCase[]{
newTelephonyTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, TELEPHONY_SCORE_LOW),
newTelephonyTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
@@ -118,90 +125,6 @@ public class TimeZoneDetectorStrategyImplTest {
TELEPHONY_SCORE_HIGHEST),
};
- private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_DISABLED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(true)
- .setGeoDetectionFeatureSupported(true)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(false)
- .setAutoDetectionEnabledSetting(false)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(false)
- .build();
-
- private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_ENABLED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(true)
- .setGeoDetectionFeatureSupported(true)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(false)
- .setAutoDetectionEnabledSetting(true)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(true)
- .build();
-
- private static final ConfigurationInternal CONFIG_AUTO_DETECT_NOT_SUPPORTED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(false)
- .setGeoDetectionFeatureSupported(false)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(true)
- .setAutoDetectionEnabledSetting(false)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(false)
- .build();
-
- private static final ConfigurationInternal CONFIG_AUTO_DISABLED_GEO_DISABLED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(true)
- .setGeoDetectionFeatureSupported(true)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(true)
- .setAutoDetectionEnabledSetting(false)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(false)
- .build();
-
- private static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_DISABLED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(true)
- .setGeoDetectionFeatureSupported(true)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(true)
- .setAutoDetectionEnabledSetting(true)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(false)
- .build();
-
- private static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_ENABLED =
- new ConfigurationInternal.Builder()
- .setUserId(USER_ID)
- .setTelephonyDetectionFeatureSupported(true)
- .setGeoDetectionFeatureSupported(true)
- .setTelephonyFallbackSupported(false)
- .setGeoDetectionRunInBackgroundEnabled(false)
- .setEnhancedMetricsCollectionEnabled(false)
- .setUserConfigAllowed(true)
- .setAutoDetectionEnabledSetting(true)
- .setLocationEnabledSetting(true)
- .setGeoDetectionEnabledSetting(true)
- .build();
-
private static final TelephonyTimeZoneAlgorithmStatus TELEPHONY_ALGORITHM_RUNNING_STATUS =
new TelephonyTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING);
@@ -421,7 +344,7 @@ public class TimeZoneDetectorStrategyImplTest {
new QualifiedTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion,
TELEPHONY_SCORE_NONE);
script.verifyLatestQualifiedTelephonySuggestionReceived(
- SLOT_INDEX1, expectedSlotIndex1ScoredSuggestion)
+ SLOT_INDEX1, expectedSlotIndex1ScoredSuggestion)
.verifyLatestQualifiedTelephonySuggestionReceived(SLOT_INDEX2, null);
assertEquals(expectedSlotIndex1ScoredSuggestion,
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
@@ -629,7 +552,7 @@ public class TimeZoneDetectorStrategyImplTest {
*/
@Test
public void testTelephonySuggestionMultipleSlotIndexSuggestionScoringAndSlotIndexBias() {
- String[] zoneIds = { "Europe/London", "Europe/Paris" };
+ String[] zoneIds = {"Europe/London", "Europe/Paris"};
TelephonyTimeZoneSuggestion emptySlotIndex1Suggestion = createEmptySlotIndex1Suggestion();
TelephonyTimeZoneSuggestion emptySlotIndex2Suggestion = createEmptySlotIndex2Suggestion();
QualifiedTelephonyTimeZoneSuggestion expectedEmptySlotIndex1ScoredSuggestion =
@@ -672,7 +595,7 @@ public class TimeZoneDetectorStrategyImplTest {
// Assert internal service state.
script.verifyLatestQualifiedTelephonySuggestionReceived(
- SLOT_INDEX1, expectedZoneSlotIndex1ScoredSuggestion)
+ SLOT_INDEX1, expectedZoneSlotIndex1ScoredSuggestion)
.verifyLatestQualifiedTelephonySuggestionReceived(
SLOT_INDEX2, expectedEmptySlotIndex2ScoredSuggestion);
assertEquals(expectedZoneSlotIndex1ScoredSuggestion,
@@ -805,14 +728,14 @@ public class TimeZoneDetectorStrategyImplTest {
boolean bypassUserPolicyChecks = false;
boolean expectedResult = true;
script.simulateManualTimeZoneSuggestion(
- USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
+ USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
.verifyTimeZoneChangedAndReset(manualSuggestion);
assertEquals(manualSuggestion, mTimeZoneDetectorStrategy.getLatestManualSuggestion());
}
@Test
- @Parameters({ "true,true", "true,false", "false,true", "false,false" })
+ @Parameters({"true,true", "true,false", "false,true", "false,false"})
public void testManualSuggestion_autoTimeEnabled_userRestrictions(
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
ConfigurationInternal config =
@@ -834,7 +757,7 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Test
- @Parameters({ "true,true", "true,false", "false,true", "false,false" })
+ @Parameters({"true,true", "true,false", "false,true", "false,false"})
public void testManualSuggestion_autoTimeDisabled_userRestrictions(
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
ConfigurationInternal config =
@@ -849,7 +772,7 @@ public class TimeZoneDetectorStrategyImplTest {
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
boolean expectedResult = userConfigAllowed || bypassUserPolicyChecks;
script.simulateManualTimeZoneSuggestion(
- USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult);
+ USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult);
if (expectedResult) {
script.verifyTimeZoneChangedAndReset(manualSuggestion);
assertEquals(manualSuggestion, mTimeZoneDetectorStrategy.getLatestManualSuggestion());
@@ -1258,7 +1181,6 @@ public class TimeZoneDetectorStrategyImplTest {
script.simulateLocationAlgorithmEvent(locationAlgorithmEvent)
.verifyTimeZoneChangedAndReset(locationAlgorithmEvent)
.verifyTelephonyFallbackIsEnabled(false);
-
}
// Demonstrate what happens when geolocation is uncertain when telephony fallback is
@@ -1569,7 +1491,7 @@ public class TimeZoneDetectorStrategyImplTest {
boolean bypassUserPolicyChecks = false;
boolean expectedResult = true;
script.simulateManualTimeZoneSuggestion(
- USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
+ USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
.verifyTimeZoneChangedAndReset(manualSuggestion);
expectedDeviceTimeZoneId = manualSuggestion.getZoneId();
assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
@@ -1880,6 +1802,7 @@ public class TimeZoneDetectorStrategyImplTest {
boolean actualResult = mTimeZoneDetectorStrategy.suggestManualTimeZone(
userId, manualTimeZoneSuggestion, bypassUserPolicyChecks);
assertEquals(expectedResult, actualResult);
+
return this;
}
@@ -2001,4 +1924,34 @@ public class TimeZoneDetectorStrategyImplTest {
return new TelephonyTestCase(matchType, quality, expectedScore);
}
+ static class FakeTimeZoneChangeEventListener implements TimeZoneChangeListener {
+ private final List<TimeZoneChangeEvent> mEvents = new ArrayList<>();
+
+ FakeTimeZoneChangeEventListener() {
+ }
+
+ @Override
+ public void process(TimeZoneChangeEvent event) {
+ mEvents.add(event);
+ }
+
+ public List<TimeZoneChangeEvent> getTimeZoneChangeEvents() {
+ return mEvents;
+ }
+
+ @Override
+ public void dump(IndentingPrintWriter ipw) {
+ // No-op for tests
+ }
+ }
+
+ private static void assertEmpty(Collection<?> collection) {
+ assertTrue(
+ "Expected empty, but contains (" + collection.size() + ") elements: " + collection,
+ collection.isEmpty());
+ }
+
+ private static void assertNotEmpty(Collection<?> collection) {
+ assertFalse("Expected not empty: " + collection, collection.isEmpty());
+ }
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/BasicToPwleSegmentAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/BasicToPwleSegmentAdapterTest.java
new file mode 100644
index 000000000000..09f573cd1ee0
--- /dev/null
+++ b/services/tests/vibrator/src/com/android/server/vibrator/BasicToPwleSegmentAdapterTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2024 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.vibrator;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.vibrator.IVibrator;
+import android.os.VibratorInfo;
+import android.os.vibrator.BasicPwleSegment;
+import android.os.vibrator.Flags;
+import android.os.vibrator.PwleSegment;
+import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationEffectSegment;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+public class BasicToPwleSegmentAdapterTest {
+
+ private static final float TEST_RESONANT_FREQUENCY = 150;
+ private static final float[] TEST_FREQUENCIES =
+ new float[]{90f, 120f, 150f, 60f, 30f, 210f, 270f, 300f, 240f, 180f};
+ private static final float[] TEST_OUTPUT_ACCELERATIONS =
+ new float[]{1.2f, 1.8f, 2.4f, 0.6f, 0.1f, 2.2f, 1.0f, 0.5f, 1.9f, 3.0f};
+
+ private static final VibratorInfo.FrequencyProfile TEST_FREQUENCY_PROFILE =
+ new VibratorInfo.FrequencyProfile(TEST_RESONANT_FREQUENCY, TEST_FREQUENCIES,
+ TEST_OUTPUT_ACCELERATIONS);
+
+ private static final VibratorInfo.FrequencyProfile EMPTY_FREQUENCY_PROFILE =
+ new VibratorInfo.FrequencyProfile(TEST_RESONANT_FREQUENCY, null, null);
+
+ private BasicToPwleSegmentAdapter mAdapter;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Before
+ public void setUp() throws Exception {
+ mAdapter = new BasicToPwleSegmentAdapter();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void testBasicPwleSegments_withFeatureFlagDisabled_returnsOriginalSegments() {
+ List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
+ // startIntensity, endIntensity, startSharpness, endSharpness, duration
+ new BasicPwleSegment(0.2f, 0.8f, 0.2f, 0.4f, 20),
+ new BasicPwleSegment(0.8f, 0.2f, 0.4f, 0.5f, 100),
+ new BasicPwleSegment(0.2f, 0.65f, 0.5f, 0.5f, 50)));
+ List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
+
+ VibratorInfo vibratorInfo = createVibratorInfo(
+ TEST_FREQUENCY_PROFILE, IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
+
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ -1))
+ .isEqualTo(-1);
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ 1))
+ .isEqualTo(1);
+
+ assertThat(segments).isEqualTo(originalSegments);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void testBasicPwleSegments_noPwleCapability_returnsOriginalSegments() {
+ List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
+ // startIntensity, endIntensity, startSharpness, endSharpness, duration
+ new BasicPwleSegment(0.2f, 0.8f, 0.2f, 0.4f, 20),
+ new BasicPwleSegment(0.8f, 0.2f, 0.4f, 0.5f, 100),
+ new BasicPwleSegment(0.2f, 0.65f, 0.5f, 0.5f, 50)));
+ List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
+
+ VibratorInfo vibratorInfo = createVibratorInfo(TEST_FREQUENCY_PROFILE);
+
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ -1))
+ .isEqualTo(-1);
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ 1))
+ .isEqualTo(1);
+
+ assertThat(segments).isEqualTo(originalSegments);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void testBasicPwleSegments_invalidFrequencyProfile_returnsOriginalSegments() {
+ List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
+ // startIntensity, endIntensity, startSharpness, endSharpness, duration
+ new BasicPwleSegment(0.2f, 0.8f, 0.2f, 0.4f, 20),
+ new BasicPwleSegment(0.8f, 0.2f, 0.4f, 0.5f, 100),
+ new BasicPwleSegment(0.2f, 0.65f, 0.5f, 0.5f, 50)));
+ List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
+ VibratorInfo vibratorInfo = createVibratorInfo(
+ EMPTY_FREQUENCY_PROFILE, IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
+
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ -1))
+ .isEqualTo(-1);
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ 1))
+ .isEqualTo(1);
+
+ assertThat(segments).isEqualTo(originalSegments);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void testBasicPwleSegments_withPwleCapability_adaptSegmentsCorrectly() {
+ List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 40f, /* duration= */ 100),
+ // startIntensity, endIntensity, startSharpness, endSharpness, duration
+ new BasicPwleSegment(0.0f, 1.0f, 0.0f, 1.0f, 100),
+ new BasicPwleSegment(0.0f, 1.0f, 0.0f, 1.0f, 100),
+ new BasicPwleSegment(0.0f, 1.0f, 0.0f, 1.0f, 100)));
+ List<VibrationEffectSegment> expectedSegments = Arrays.asList(
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 40f, /* duration= */ 100),
+ // startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration
+ new PwleSegment(0.0f, 1.0f, 30.0f, 300.0f, 100),
+ new PwleSegment(0.0f, 1.0f, 30.0f, 300.0f, 100),
+ new PwleSegment(0.0f, 1.0f, 30.0f, 300.0f, 100));
+ VibratorInfo vibratorInfo = createVibratorInfo(
+ TEST_FREQUENCY_PROFILE, IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
+
+ assertThat(mAdapter.adaptToVibrator(vibratorInfo, segments, /*repeatIndex= */ 1))
+ .isEqualTo(1);
+
+ assertThat(segments).isEqualTo(expectedSegments);
+ }
+
+ private static VibratorInfo createVibratorInfo(VibratorInfo.FrequencyProfile frequencyProfile,
+ int... capabilities) {
+ return new VibratorInfo.Builder(0)
+ .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0))
+ .setFrequencyProfile(frequencyProfile)
+ .build();
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
index 463254caa845..50419d46f48f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
@@ -159,8 +159,8 @@ public class AppCompatReachabilityOverridesTest extends WindowTestsBase {
@Override
void onPostActivityCreation(@NonNull ActivityRecord activity) {
super.onPostActivityCreation(activity);
- spyOn(activity.mAppCompatController.getAppCompatReachabilityOverrides());
- activity.mAppCompatController.getAppCompatReachabilityPolicy()
+ spyOn(activity.mAppCompatController.getReachabilityOverrides());
+ activity.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(mLetterboxInnerBoundsSupplier);
}
@@ -196,7 +196,7 @@ public class AppCompatReachabilityOverridesTest extends WindowTestsBase {
@NonNull
private AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
- return activity().top().mAppCompatController.getAppCompatReachabilityOverrides();
+ return activity().top().mAppCompatController.getReachabilityOverrides();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java
index ddc4de9cfd8a..09b8bce2c930 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityPolicyTest.java
@@ -246,8 +246,8 @@ public class AppCompatReachabilityPolicyTest extends WindowTestsBase {
@Override
void onPostActivityCreation(@NonNull ActivityRecord activity) {
super.onPostActivityCreation(activity);
- spyOn(activity.mAppCompatController.getAppCompatReachabilityOverrides());
- activity.mAppCompatController.getAppCompatReachabilityPolicy()
+ spyOn(activity.mAppCompatController.getReachabilityOverrides());
+ activity.mAppCompatController.getReachabilityPolicy()
.setLetterboxInnerBoundsSupplier(mLetterboxInnerBoundsSupplier);
}
@@ -281,12 +281,12 @@ public class AppCompatReachabilityPolicyTest extends WindowTestsBase {
@NonNull
private AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
- return activity().top().mAppCompatController.getAppCompatReachabilityOverrides();
+ return activity().top().mAppCompatController.getReachabilityOverrides();
}
@NonNull
private AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() {
- return activity().top().mAppCompatController.getAppCompatReachabilityPolicy();
+ return activity().top().mAppCompatController.getReachabilityPolicy();
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 9d9f24cb50f2..d6080e08774e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -330,7 +330,7 @@ public class SizeCompatTests extends WindowTestsBase {
if (horizontalReachability) {
final Consumer<Integer> doubleClick =
(Integer x) -> {
- mActivity.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivity.mAppCompatController.getReachabilityPolicy()
.handleDoubleTap(x, displayHeight / 2);
mActivity.mRootWindowContainer.performSurfacePlacement();
};
@@ -360,7 +360,7 @@ public class SizeCompatTests extends WindowTestsBase {
} else {
final Consumer<Integer> doubleClick =
(Integer y) -> {
- mActivity.mAppCompatController.getAppCompatReachabilityPolicy()
+ mActivity.mAppCompatController.getReachabilityPolicy()
.handleDoubleTap(displayWidth / 2, y);
mActivity.mRootWindowContainer.performSurfacePlacement();
};
@@ -421,7 +421,7 @@ public class SizeCompatTests extends WindowTestsBase {
final Consumer<Integer> doubleClick =
(Integer y) -> {
- activity.mAppCompatController.getAppCompatReachabilityPolicy()
+ activity.mAppCompatController.getReachabilityPolicy()
.handleDoubleTap(dw / 2, y);
activity.mRootWindowContainer.performSurfacePlacement();
};
@@ -3427,7 +3427,7 @@ public class SizeCompatTests extends WindowTestsBase {
setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ false);
final AppCompatReachabilityOverrides reachabilityOverrides =
- mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ mActivity.mAppCompatController.getReachabilityOverrides();
assertFalse(reachabilityOverrides.isVerticalReachabilityEnabled());
assertFalse(reachabilityOverrides.isHorizontalReachabilityEnabled());
}
@@ -3451,7 +3451,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Horizontal reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertFalse(mActivity.mAppCompatController.getReachabilityOverrides()
.isHorizontalReachabilityEnabled());
}
@@ -3475,7 +3475,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Vertical reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertFalse(mActivity.mAppCompatController.getReachabilityOverrides()
.isVerticalReachabilityEnabled());
}
@@ -3498,7 +3498,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Vertical reachability is disabled because the app does not match parent width
assertNotEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertFalse(mActivity.mAppCompatController.getReachabilityOverrides()
.isVerticalReachabilityEnabled());
}
@@ -3516,7 +3516,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Vertical reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isVerticalReachabilityEnabled());
}
@@ -3533,7 +3533,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Horizontal reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isHorizontalReachabilityEnabled());
}
@@ -3548,7 +3548,7 @@ public class SizeCompatTests extends WindowTestsBase {
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isHorizontalReachabilityEnabled());
}
@@ -3563,7 +3563,7 @@ public class SizeCompatTests extends WindowTestsBase {
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_LANDSCAPE);
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isVerticalReachabilityEnabled());
}
@@ -3585,7 +3585,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Horizontal reachability is disabled because the app does not match parent height
assertNotEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertFalse(mActivity.mAppCompatController.getReachabilityOverrides()
.isHorizontalReachabilityEnabled());
}
@@ -3608,7 +3608,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Horizontal reachability is enabled because the app matches parent height
assertEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isHorizontalReachabilityEnabled());
}
@@ -3631,7 +3631,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Vertical reachability is enabled because the app matches parent width
assertEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ assertTrue(mActivity.mAppCompatController.getReachabilityOverrides()
.isVerticalReachabilityEnabled());
}
@@ -4315,7 +4315,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Make sure app doesn't jump to top (default tabletop position) when unfolding.
assertEquals(1.0f, mActivity.mAppCompatController
- .getAppCompatReachabilityOverrides().getVerticalPositionMultiplier(mActivity
+ .getReachabilityOverrides().getVerticalPositionMultiplier(mActivity
.getParent().getConfiguration()), 0);
// Simulate display fully open after unfolding.
@@ -4323,7 +4323,7 @@ public class SizeCompatTests extends WindowTestsBase {
doReturn(false).when(mActivity.mDisplayContent).inTransition();
assertEquals(1.0f, mActivity.mAppCompatController
- .getAppCompatReachabilityOverrides().getVerticalPositionMultiplier(mActivity
+ .getReachabilityOverrides().getVerticalPositionMultiplier(mActivity
.getParent().getConfiguration()), 0);
}
@@ -5028,7 +5028,7 @@ public class SizeCompatTests extends WindowTestsBase {
private void setUpAllowThinLetterboxed(boolean thinLetterboxAllowed) {
final AppCompatReachabilityOverrides reachabilityOverrides =
- mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ mActivity.mAppCompatController.getReachabilityOverrides();
spyOn(reachabilityOverrides);
doReturn(thinLetterboxAllowed).when(reachabilityOverrides)
.allowVerticalReachabilityForThinLetterbox();
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 63a12816f783..b7b209b78300 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -3690,8 +3690,8 @@ public final class SatelliteManager {
* @param list The list of provisioned satellite subscriber infos.
* @param executor The executor on which the callback will be called.
* @param callback The callback object to which the result will be delivered.
- * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
- * will return {@code true}.
+ * If the request is successful, {@link OutcomeReceiver#onResult}
+ * will be called.
* If the request is not successful,
* {@link OutcomeReceiver#onError(Throwable)} will return an error with
* a SatelliteException.
@@ -3704,7 +3704,7 @@ public final class SatelliteManager {
@FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
public void provisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
@NonNull @CallbackExecutor Executor executor,
- @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+ @NonNull OutcomeReceiver<Void, SatelliteException> callback) {
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
@@ -3718,8 +3718,8 @@ public final class SatelliteManager {
if (resultData.containsKey(KEY_PROVISION_SATELLITE_TOKENS)) {
boolean isUpdated =
resultData.getBoolean(KEY_PROVISION_SATELLITE_TOKENS);
- executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onResult(isUpdated)));
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> callback.onResult(null)));
} else {
loge("KEY_REQUEST_PROVISION_TOKENS does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
@@ -3751,8 +3751,8 @@ public final class SatelliteManager {
* @param list The list of deprovisioned satellite subscriber infos.
* @param executor The executor on which the callback will be called.
* @param callback The callback object to which the result will be delivered.
- * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
- * will return {@code true}.
+ * If the request is successful, {@link OutcomeReceiver#onResult}
+ * will be called.
* If the request is not successful,
* {@link OutcomeReceiver#onError(Throwable)} will return an error with
* a SatelliteException.
@@ -3765,7 +3765,7 @@ public final class SatelliteManager {
@FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
@NonNull @CallbackExecutor Executor executor,
- @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+ @NonNull OutcomeReceiver<Void, SatelliteException> callback) {
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
@@ -3780,7 +3780,7 @@ public final class SatelliteManager {
boolean isUpdated =
resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS);
executor.execute(() -> Binder.withCleanCallingIdentity(() ->
- callback.onResult(isUpdated)));
+ callback.onResult(null)));
} else {
loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist.");
executor.execute(() -> Binder.withCleanCallingIdentity(() ->