Merge "Migrate VCN to separate non-updatable libraries" into aosp-main-future
diff --git a/core/api/current.txt b/core/api/current.txt
index 3335375..832a68f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -39990,8 +39990,10 @@
method @NonNull public java.util.List<java.security.cert.X509Certificate> getGrantedCertificateChainFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
method @NonNull public java.security.Key getGrantedKeyFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
method @NonNull public java.security.KeyPair getGrantedKeyPairFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException;
+ method @FlaggedApi("android.security.keystore2.attest_modules") @NonNull public byte[] getSupplementaryAttestationInfo(int) throws android.security.KeyStoreException;
method public long grantKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException;
method public void revokeKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException;
+ field public static final int MODULE_HASH = -1879047468; // 0x900002d4
}
public class SecureKeyImportUnavailableException extends java.security.ProviderException {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 340d9cb..6446f07 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -483,6 +483,10 @@
field public static final long TRACE_TAG_NETWORK = 2097152L; // 0x200000L
}
+ public class UpdateEngine {
+ method @FlaggedApi("android.os.update_engine_api") public void triggerPostinstall(@NonNull String);
+ }
+
}
package android.os.storage {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 8f84ee8..79dd22f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -78,8 +78,6 @@
import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
-import android.content.integrity.AppIntegrityManager;
-import android.content.integrity.IAppIntegrityManager;
import android.content.om.IOverlayManager;
import android.content.om.OverlayManager;
import android.content.pm.ApplicationInfo;
@@ -1536,16 +1534,6 @@
return new AttestationVerificationManager(ctx.getOuterContext(),
IAttestationVerificationManagerService.Stub.asInterface(b));
}});
-
- //CHECKSTYLE:ON IndentationCheck
- registerService(Context.APP_INTEGRITY_SERVICE, AppIntegrityManager.class,
- new CachedServiceFetcher<AppIntegrityManager>() {
- @Override
- public AppIntegrityManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
- return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
- }});
registerService(Context.APP_HIBERNATION_SERVICE, AppHibernationManager.class,
new CachedServiceFetcher<AppHibernationManager>() {
@Override
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 97f6899..b0ea92d 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -18,6 +18,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.HdrCapabilities.HdrType;
+import static android.view.Display.INVALID_DISPLAY;
import android.Manifest;
import android.annotation.FlaggedApi;
@@ -47,6 +48,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserManager;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -96,6 +98,8 @@
@GuardedBy("mLock")
private final WeakDisplayCache mDisplayCache = new WeakDisplayCache();
+ private int mDisplayIdToMirror = INVALID_DISPLAY;
+
/**
* Broadcast receiver that indicates when the Wifi display status changes.
* <p>
@@ -1086,6 +1090,7 @@
if (surface != null) {
builder.setSurface(surface);
}
+ builder.setDisplayIdToMirror(getDisplayIdToMirror());
return createVirtualDisplay(builder.build(), handler, callback);
}
@@ -1163,6 +1168,7 @@
if (surface != null) {
builder.setSurface(surface);
}
+ builder.setDisplayIdToMirror(getDisplayIdToMirror());
return createVirtualDisplay(projection, builder.build(), callback, handler);
}
@@ -1708,6 +1714,16 @@
return mGlobal.getDefaultDozeBrightness(displayId);
}
+ private int getDisplayIdToMirror() {
+ if (mDisplayIdToMirror == INVALID_DISPLAY) {
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ mDisplayIdToMirror = userManager.isVisibleBackgroundUsersSupported()
+ ? userManager.getMainDisplayIdAssignedToUser()
+ : DEFAULT_DISPLAY;
+ }
+ return mDisplayIdToMirror;
+ }
+
/**
* Listens for changes in available display devices.
*/
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index bf351ce..f53d1c4 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -62,7 +62,11 @@
return isSuccess;
}
if (eventCount == eventTypes.length) {
- resize((int) (1.4 * eventCount));
+ int resizeLength = (int) (1.4 * eventCount);
+ if (eventCount == resizeLength) {
+ resizeLength++;
+ }
+ resize(resizeLength);
}
eventTypes[eventCount] = eventType;
returnCodes[eventCount] = returnCode;
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index bfcc5cc..8d35338 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -118,9 +118,10 @@
# Memory
per-file OomKillRecord.java = file:/MEMORY_OWNERS
-# MessageQueue
+# MessageQueue and related classes
per-file MessageQueue.java = mfasheh@google.com, shayba@google.com
per-file Message.java = mfasheh@google.com, shayba@google.com
+per-file TestLooperManager.java = mfasheh@google.com, shayba@google.com
# Stats
per-file IStatsBootstrapAtomService.aidl = file:/services/core/java/com/android/server/stats/OWNERS
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index f64a811..11c54ef 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -193,4 +193,31 @@
return false;
}
}
+
+ /**
+ * Gets the genfs labels version of the vendor. The genfs labels version is
+ * specified in {@code /vendor/etc/selinux/genfs_labels_version.txt}. The
+ * version follows the VINTF version format "YYYYMM" and affects how {@code
+ * genfs_contexts} entries are applied.
+ *
+ * <p>The genfs labels version indicates changes in the SELinux labeling
+ * scheme over time. For example:
+ * <ul>
+ * <li>For version 202504 and later, {@code /sys/class/udc} is labeled as
+ * {@code sysfs_udc}.
+ * <li>For version 202404 and earlier, {@code /sys/class/udc} is labeled
+ * as {@code sysfs}.
+ * </ul>
+ * Check {@code /system/etc/selinux/plat_sepolicy_genfs_{version}.cil} to
+ * see which labels are new in {version}.
+ *
+ * <p>Older vendors may override {@code genfs_contexts} with vendor-specific
+ * extensions. The framework must not break such labellings to maintain
+ * compatibility with such vendors, by checking the genfs labels version and
+ * implementing a fallback mechanism.
+ *
+ * @return an integer representing the genfs labels version of /vendor, in
+ * the format YYYYMM.
+ */
+ public static final native int getGenfsLabelsVersion();
}
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 8aec7eb..9085fe0 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -277,7 +277,8 @@
if (service != null) {
return service;
} else {
- return Binder.allowBlocking(getIServiceManager().checkService(name).getBinder());
+ return Binder.allowBlocking(
+ getIServiceManager().checkService(name).getServiceWithMetadata().service);
}
} catch (RemoteException e) {
Log.e(TAG, "error in checkService", e);
@@ -425,7 +426,8 @@
private static IBinder rawGetService(String name) throws RemoteException {
final long start = sStatLogger.getTime();
- final IBinder binder = getIServiceManager().getService2(name).getBinder();
+ final IBinder binder =
+ getIServiceManager().getService2(name).getServiceWithMetadata().service;
final int time = (int) sStatLogger.logDurationStat(Stats.GET_SERVICE, start);
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 5a9c878..49b696d 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -61,7 +61,7 @@
@UnsupportedAppUsage
public IBinder getService(String name) throws RemoteException {
// Same as checkService (old versions of servicemanager had both methods).
- return checkService(name).getBinder();
+ return checkService(name).getServiceWithMetadata().service;
}
public Service getService2(String name) throws RemoteException {
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 0a8f62f..81e4549 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -667,4 +668,23 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Run postinstall script for specified partition |partition|
+ *
+ * @param partition The partition to trigger postinstall runs
+ *
+ * @throws ServiceSpecificException error code of this exception would be one of
+ * https://cs.android.com/android/platform/superproject/main/+/main:system/update_engine/common/error_code.h
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_UPDATE_ENGINE_API)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public void triggerPostinstall(@NonNull String partition) {
+ try {
+ mUpdateEngine.triggerPostinstall(partition);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b8a8be1..ef8b3d7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -19338,14 +19338,14 @@
* If hotword detection should be enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String HOTWORD_DETECTION_ENABLED = "hotword_detection_enabled";
/**
* Whether Smart Replies are enabled within Wear.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SMART_REPLIES_ENABLED = "smart_replies_enabled";
/**
@@ -19359,7 +19359,7 @@
* If FLP should obtain location data from the paired device.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String OBTAIN_PAIRED_DEVICE_LOCATION =
"obtain_paired_device_location";
@@ -19367,7 +19367,7 @@
* The play store availability on companion phone.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PHONE_PLAY_STORE_AVAILABILITY =
"phone_play_store_availability";
@@ -19383,7 +19383,7 @@
* Whether the bug report is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BUG_REPORT = "bug_report";
// Possible bug report states
@@ -19396,14 +19396,14 @@
* The enabled/disabled state of the SmartIlluminate.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SMART_ILLUMINATE_ENABLED = "smart_illuminate_enabled";
/**
* Whether automatic time is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_AUTO_TIME = "clockwork_auto_time";
// Possible clockwork auto time states
@@ -19421,7 +19421,7 @@
* Whether automatic time zone is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_AUTO_TIME_ZONE = "clockwork_auto_time_zone";
// Possible clockwork auto time zone states
@@ -19438,14 +19438,14 @@
* Whether 24 hour time format is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_24HR_TIME = "clockwork_24hr_time";
/**
* Whether the auto wifi toggle setting is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AUTO_WIFI = "auto_wifi";
// Possible force wifi on states
@@ -19465,7 +19465,7 @@
* wifi requirement until this time). The time is in millis since epoch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ALT_BYPASS_WIFI_REQUIREMENT_TIME_MILLIS =
"alt_bypass_wifi_requirement_time_millis";
@@ -19473,7 +19473,7 @@
* Whether the setup was skipped.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SETUP_SKIPPED = "setup_skipped";
// Possible setup_skipped states
@@ -19488,7 +19488,7 @@
* The last requested call forwarding action.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String LAST_CALL_FORWARD_ACTION = "last_call_forward_action";
// Possible call forwarding actions
@@ -19501,31 +19501,31 @@
// Stem button settings.
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_TYPE = "STEM_1_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_DATA = "STEM_1_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_DEFAULT_DATA = "STEM_1_DEFAULT_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_TYPE = "STEM_2_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_DATA = "STEM_2_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_DEFAULT_DATA = "STEM_2_DEFAULT_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_TYPE = "STEM_3_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_DATA = "STEM_3_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_DEFAULT_DATA = "STEM_3_DEFAULT_DATA";
// Stem types
@@ -19540,14 +19540,14 @@
* If the device should be muted when off body.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String MUTE_WHEN_OFF_BODY_ENABLED = "obtain_mute_when_off_body";
/**
* Wear OS version string.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_OS_VERSION_STRING = "wear_os_version_string";
/**
@@ -19560,28 +19560,28 @@
* The android wear system version.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ANDROID_WEAR_VERSION = "android_wear_version";
/**
* The wear system capabiltiies.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SYSTEM_CAPABILITIES = "system_capabilities";
/**
* The android wear system edition.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SYSTEM_EDITION = "android_wear_system_edition";
/**
* The Wear platform MR number.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_PLATFORM_MR_NUMBER = "wear_platform_mr_number";
/**
@@ -19595,42 +19595,42 @@
* Whether ambient is currently enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_ENABLED = "ambient_enabled";
/**
* Whether ambient tilt to wake is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TILT_TO_WAKE = "ambient_tilt_to_wake";
/**
* Whether ambient low bit mode is enabled by developer options.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_LOW_BIT_ENABLED_DEV = "ambient_low_bit_enabled_dev";
/**
* Whether ambient touch to wake is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TOUCH_TO_WAKE = "ambient_touch_to_wake";
/**
* Whether ambient tilt to bright is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TILT_TO_BRIGHT = "ambient_tilt_to_bright";
/**
* Whether touch and hold to edit WF is enabled
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String GESTURE_TOUCH_AND_HOLD_WATCH_FACE_ENABLED =
"gesture_touch_and_hold_watchface_enabled";
@@ -19644,7 +19644,7 @@
* Whether bedtime mode is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BEDTIME_MODE = "bedtime_mode";
/**
@@ -19656,35 +19656,35 @@
* Whether the current watchface is decomposable.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String DECOMPOSABLE_WATCHFACE = "current_watchface_decomposable";
/**
* Whether to force ambient when docked.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_FORCE_WHEN_DOCKED = "ambient_force_when_docked";
/**
* Whether the ambient low bit mode is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_LOW_BIT_ENABLED = "ambient_low_bit_enabled";
/**
* The timeout duration in minutes of ambient mode when plugged in.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_PLUGGED_TIMEOUT_MIN = "ambient_plugged_timeout_min";
/**
* What OS does paired device has.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PAIRED_DEVICE_OS_TYPE = "paired_device_os_type";
// Possible values of PAIRED_DEVICE_OS_TYPE
@@ -19719,7 +19719,7 @@
* The user's last setting for hfp client.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String USER_HFP_CLIENT_SETTING = "user_hfp_client_setting";
// Possible hfp client user setting values
@@ -19744,7 +19744,7 @@
* The companion App name.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String COMPANION_APP_NAME = "wear_companion_app_name";
/**
@@ -19752,21 +19752,21 @@
* wear. 1 for supporting, 0 for not supporting.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ENABLE_ALL_LANGUAGES = "enable_all_languages";
/**
* The Locale (as language tag) the user chose at startup.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SETUP_LOCALE = "setup_locale";
/**
* The version of oem setup present.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String OEM_SETUP_VERSION = "oem_setup_version";
/**
@@ -19812,7 +19812,7 @@
* -{@link BATTERY_SAVER_MODE_CUSTOM}
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BATTERY_SAVER_MODE = "battery_saver_mode";
/**
@@ -19869,7 +19869,7 @@
* If burn in protection is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BURN_IN_PROTECTION_ENABLED = "burn_in_protection";
/**
@@ -19888,7 +19888,7 @@
* RIGHT_WRIST_ROTATION_0 = "2", RIGHT_WRIST_ROTATION_180 = "3"
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WRIST_ORIENTATION_MODE = "wear_wrist_orientation_mode";
/**
@@ -19927,7 +19927,7 @@
*
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_SYSUI_PACKAGE = "clockwork_sysui_package";
/**
@@ -19957,7 +19957,7 @@
* Whether the device has Wet Mode/ Touch Lock Mode enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WET_MODE_ON = "wet_mode_on";
/**
@@ -19976,7 +19976,7 @@
* Whether charging sounds are enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CHARGING_SOUNDS_ENABLED = "wear_charging_sounds_enabled";
/**
@@ -19985,7 +19985,7 @@
*
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String DYNAMIC_COLOR_THEME_ENABLED = "dynamic_color_theme_enabled";
/**
@@ -20077,7 +20077,7 @@
* The key to indicate the data migration status on device upgrade in Wear Services.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String UPGRADE_DATA_MIGRATION_STATUS =
"upgrade_data_migration_status";
@@ -20134,20 +20134,20 @@
* The custom foreground color.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CUSTOM_COLOR_FOREGROUND = "custom_foreground_color";
/**
* The custom background color.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CUSTOM_COLOR_BACKGROUND = "custom_background_color";
/** The status of the phone switching process.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PHONE_SWITCHING_STATUS = "phone_switching_status";
/**
@@ -20318,7 +20318,7 @@
* Controls the launcher ui mode on wearable devices.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_LAUNCHER_UI_MODE = "wear_launcher_ui_mode";
/** Whether Wear Power Anomaly Service is enabled.
diff --git a/core/java/android/security/net/config/CertificatesEntryRef.java b/core/java/android/security/net/config/CertificatesEntryRef.java
index 45cd0f0..a46049f 100644
--- a/core/java/android/security/net/config/CertificatesEntryRef.java
+++ b/core/java/android/security/net/config/CertificatesEntryRef.java
@@ -17,6 +17,7 @@
package android.security.net.config;
import android.util.ArraySet;
+
import java.security.cert.X509Certificate;
import java.util.Set;
@@ -24,16 +25,23 @@
public final class CertificatesEntryRef {
private final CertificateSource mSource;
private final boolean mOverridesPins;
+ private final boolean mDisableCT;
- public CertificatesEntryRef(CertificateSource source, boolean overridesPins) {
+ public CertificatesEntryRef(CertificateSource source, boolean overridesPins,
+ boolean disableCT) {
mSource = source;
mOverridesPins = overridesPins;
+ mDisableCT = disableCT;
}
boolean overridesPins() {
return mOverridesPins;
}
+ boolean disableCT() {
+ return mDisableCT;
+ }
+
public Set<TrustAnchor> getTrustAnchors() {
// TODO: cache this [but handle mutable sources]
Set<TrustAnchor> anchors = new ArraySet<TrustAnchor>();
diff --git a/core/java/android/security/net/config/KeyStoreConfigSource.java b/core/java/android/security/net/config/KeyStoreConfigSource.java
index 8d4f098..a54d8d0 100644
--- a/core/java/android/security/net/config/KeyStoreConfigSource.java
+++ b/core/java/android/security/net/config/KeyStoreConfigSource.java
@@ -17,8 +17,8 @@
package android.security.net.config;
import android.util.Pair;
+
import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.util.Set;
/**
@@ -32,7 +32,7 @@
mConfig = new NetworkSecurityConfig.Builder()
.addCertificatesEntryRef(
// Use the KeyStore and do not override pins (of which there are none).
- new CertificatesEntryRef(new KeyStoreCertificateSource(ks), false))
+ new CertificatesEntryRef(new KeyStoreCertificateSource(ks), false, false))
.build();
}
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 129ae63..410c68b 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -112,7 +112,6 @@
return mHstsEnforced;
}
- // TODO(b/28746284): add exceptions for user-added certificates and enterprise overrides.
public boolean isCertificateTransparencyVerificationRequired() {
return mCertificateTransparencyVerificationRequired;
}
@@ -192,20 +191,21 @@
* @hide
*/
public static Builder getDefaultBuilder(ApplicationInfo info) {
+ // System certificate store, does not bypass static pins, does not disable CT.
+ CertificatesEntryRef systemRef = new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), false, false);
Builder builder = new Builder()
.setHstsEnforced(DEFAULT_HSTS_ENFORCED)
- // System certificate store, does not bypass static pins.
- .addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false));
+ .addCertificatesEntryRef(systemRef);
final boolean cleartextTrafficPermitted = info.targetSdkVersion < Build.VERSION_CODES.P
&& !info.isInstantApp();
builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);
// Applications targeting N and above must opt in into trusting the user added certificate
// store.
if (info.targetSdkVersion <= Build.VERSION_CODES.M && !info.isPrivilegedApp()) {
- // User certificate store, does not bypass static pins.
+ // User certificate store, does not bypass static pins. CT is disabled.
builder.addCertificatesEntryRef(
- new CertificatesEntryRef(UserCertificateSource.getInstance(), false));
+ new CertificatesEntryRef(UserCertificateSource.getInstance(), false, true));
}
return builder;
}
@@ -339,6 +339,16 @@
if (mCertificateTransparencyVerificationRequiredSet) {
return mCertificateTransparencyVerificationRequired;
}
+ // CT verification has not been set explicitly. Before deferring to
+ // the parent, check if any of the CertificatesEntryRef requires it
+ // to be disabled (i.e., user store or inline certificate).
+ if (hasCertificatesEntryRefs()) {
+ for (CertificatesEntryRef ref : getCertificatesEntryRefs()) {
+ if (ref.disableCT()) {
+ return false;
+ }
+ }
+ }
if (mParentBuilder != null) {
return mParentBuilder.getCertificateTransparencyVerificationRequired();
}
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index b1c1479..95e579f 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -182,6 +182,7 @@
boolean overridePins =
parser.getAttributeBooleanValue(null, "overridePins", defaultOverridePins);
int sourceId = parser.getAttributeResourceValue(null, "src", -1);
+ boolean disableCT = false;
String sourceString = parser.getAttributeValue(null, "src");
CertificateSource source = null;
if (sourceString == null) {
@@ -190,10 +191,12 @@
if (sourceId != -1) {
// TODO: Cache ResourceCertificateSources by sourceId
source = new ResourceCertificateSource(sourceId, mContext);
+ disableCT = true;
} else if ("system".equals(sourceString)) {
source = SystemCertificateSource.getInstance();
} else if ("user".equals(sourceString)) {
source = UserCertificateSource.getInstance();
+ disableCT = true;
} else if ("wfa".equals(sourceString)) {
source = WfaCertificateSource.getInstance();
} else {
@@ -201,7 +204,7 @@
+ "Should be one of system|user|@resourceVal");
}
XmlUtils.skipCurrentTag(parser);
- return new CertificatesEntryRef(source, overridePins);
+ return new CertificatesEntryRef(source, overridePins, disableCT);
}
private Collection<CertificatesEntryRef> parseTrustAnchors(XmlResourceParser parser,
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index 4400ed1..1923c5f 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -20,7 +20,7 @@
"file_patterns": [
"BinderDeathDispatcher\\.java"
],
- "name": "FrameworksCoreTests_internal_os_binder"
+ "name": "FrameworksCoreTests_all_binder"
},
{
"file_patterns": [
diff --git a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
index 39aadfb..f0c8f0a 100644
--- a/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
+++ b/core/java/com/android/internal/pm/pkg/component/AconfigFlags.java
@@ -239,16 +239,12 @@
negated = true;
featureFlag = featureFlag.substring(1).strip();
}
- final Boolean flagValue = getFlagValue(featureFlag);
+ Boolean flagValue = getFlagValue(featureFlag);
if (flagValue == null) {
- Slog.w(LOG_TAG, "Skipping element " + parser.getName()
- + " due to unknown feature flag " + featureFlag);
- return true;
+ flagValue = false;
}
// Skip if flag==false && attr=="flag" OR flag==true && attr=="!flag" (negated)
if (flagValue == negated) {
- Slog.v(LOG_TAG, "Skipping element " + parser.getName()
- + " behind feature flag " + featureFlag + " = " + flagValue);
return true;
}
return false;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 9a4ff8f..37c84ce 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -290,6 +290,7 @@
"libasync_safe",
"libbinderthreadstateutils",
"libdmabufinfo",
+ "libgenfslabelsversion.ffi",
"libgui_window_info_static",
"libkernelconfigs",
"libnativehelper_lazy",
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 7a4670f4..805d5ad 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -18,18 +18,19 @@
#include <errno.h>
#include <fcntl.h>
-
-#include <utils/Log.h>
-
+#include <genfslabelsversion.h>
#include <nativehelper/JNIPlatformHelp.h>
-#include "jni.h"
-#include "core_jni_helpers.h"
-#include "selinux/selinux.h"
-#include "selinux/android.h"
-#include <memory>
-#include <atomic>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
+
+#include <atomic>
+#include <memory>
+
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "selinux/android.h"
+#include "selinux/selinux.h"
namespace android {
namespace {
@@ -404,8 +405,19 @@
}
/*
+ * Function: getGenfsLabelsVersion
+ * Purpose: get which genfs labels version /vendor uses
+ * Returns: int: genfs labels version of /vendor
+ * Exceptions: none
+ */
+static jint getGenfsLabelsVersion(JNIEnv *, jclass) {
+ return get_genfs_labels_version();
+}
+
+/*
* JNI registration.
*/
+// clang-format off
static const JNINativeMethod method_table[] = {
/* name, signature, funcPtr */
{ "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
@@ -420,7 +432,9 @@
{ "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
{ "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },
{ "fileSelabelLookup" , "(Ljava/lang/String;)Ljava/lang/String;" , (void*)fileSelabelLookup},
+ { "getGenfsLabelsVersion" , "()I" , (void *)getGenfsLabelsVersion},
};
+// clang-format on
static int log_callback(int type, const char *fmt, ...) {
va_list ap;
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 6a191c6..0a33a80 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -523,14 +523,25 @@
}
test_module_config {
- name: "FrameworksCoreTests_internal_os_binder",
+ name: "FrameworksCoreTests_all_binder",
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
"device-tests",
"device-platinum-tests",
],
- include_filters: ["com.android.internal.os.BinderDeathDispatcherTest"],
+ include_filters: [
+ "android.os.BinderProxyTest",
+ "android.os.BinderDeathRecipientTest",
+ "android.os.BinderFrozenStateChangeNotificationTest",
+ "android.os.BinderProxyCountingTest",
+ "android.os.BinderUncaughtExceptionHandlerTest",
+ "android.os.BinderThreadPriorityTest",
+ "android.os.BinderWorkSourceTest",
+ "android.os.ParcelNullabilityTest",
+ "android.os.ParcelTest",
+ "com.android.internal.os.BinderDeathDispatcherTest",
+ ],
exclude_annotations: ["com.android.internal.os.SkipPresubmit"],
}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index c0a9bc2..f9d449c 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -18,10 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresFlagsEnabled
-import android.platform.test.flag.junit.CheckFlagsRule
import android.platform.test.flag.junit.DeviceFlagsValueProvider
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider
-import android.platform.test.ravenwood.RavenwoodRule
import android.util.SparseArray
import androidx.core.util.forEach
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -47,15 +44,7 @@
class FontScaleConverterFactoryTest {
@get:Rule
- val ravenwoodRule: RavenwoodRule = RavenwoodRule.Builder().build()
-
- @get:Rule
- val checkFlagsRule: CheckFlagsRule =
- if (RavenwoodRule.isOnRavenwood()) {
- RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
- } else {
- DeviceFlagsValueProvider.createCheckFlagsRule()
- }
+ val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
private var defaultLookupTables: SparseArray<FontScaleConverter>? = null
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index 3eefe04..9dc4ca1 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -33,8 +33,6 @@
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.RavenwoodFlagsValueProvider;
-import android.platform.test.ravenwood.RavenwoodRule;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
@@ -65,13 +63,7 @@
private static final String TEST_LIB = "com.android.frameworks.coretests.bdr_helper_app1";
@Rule
- public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build();
-
- @Rule
- public final CheckFlagsRule mCheckFlagsRule =
- RavenwoodRule.isOnRavenwood()
- ? RavenwoodFlagsValueProvider.createAllOnCheckFlagsRule()
- : DeviceFlagsValueProvider.createCheckFlagsRule();
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private ResourcesManager mResourcesManager;
private Map<Integer, DisplayMetrics> mDisplayMetricsMap;
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
index 4172bff..9a679d8 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
@@ -31,6 +31,8 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.internal.os.SkipPresubmit;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -131,6 +133,7 @@
}
@Test
+ @SkipPresubmit("b/381950874: bitrot and failed")
public void testPassPriorityToService() throws Exception {
for (int prio = 19; prio >= -20; prio--) {
Process.setThreadPriority(prio);
@@ -146,6 +149,7 @@
}
@Test
+ @SkipPresubmit("b/381950874: bitrot and failed")
public void testCallBackFromServiceWithPriority() throws Exception {
for (int prio = -20; prio <= 19; prio++) {
final int expected = prio;
diff --git a/keystore/java/Android.bp b/keystore/java/Android.bp
index 21edff1..264ac5ff 100644
--- a/keystore/java/Android.bp
+++ b/keystore/java/Android.bp
@@ -13,5 +13,13 @@
"**/*.java",
"**/*.aidl",
],
+ exclude_srcs: select(release_flag("RELEASE_ATTEST_MODULES"), {
+ true: [
+ "android/security/KeyStore2HalCurrent.java",
+ ],
+ default: [
+ "android/security/KeyStore2HalLatest.java",
+ ],
+ }),
visibility: ["//frameworks/base"],
}
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index dd703f5..f5cf571 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -101,7 +101,7 @@
R execute(IKeystoreService service) throws RemoteException;
}
- private <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request)
+ <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request)
throws KeyStoreException {
IKeystoreService service = getService(false /* retryLookup */);
boolean firstTry = true;
@@ -369,6 +369,18 @@
}
}
+ /**
+ * Returns tag-specific info required to interpret a tag's attested value.
+ * @see IKeystoreService#getSupplementaryAttestationInfo(Tag) for more details.
+ * @param tag
+ * @return
+ * @throws KeyStoreException
+ * @hide
+ */
+ public byte[] getSupplementaryAttestationInfo(int tag) throws KeyStoreException {
+ return KeyStore2HalVersion.getSupplementaryAttestationInfoHelper(tag, this);
+ }
+
static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
if (errorCode > 0) {
// KeyStore layer error
diff --git a/keystore/java/android/security/KeyStore2HalCurrent.java b/keystore/java/android/security/KeyStore2HalCurrent.java
new file mode 100644
index 0000000..f4d8fe6
--- /dev/null
+++ b/keystore/java/android/security/KeyStore2HalCurrent.java
@@ -0,0 +1,30 @@
+/*
+ * 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 android.security;
+
+/**
+ * @hide This class is necessary to allow the version of the AIDL interface for Keystore and
+* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When
+* `RELEASE_ATTEST_MODULES` is not set, this file is included, and the current HALs for Keystore
+* (V4) and KeyMint (V3) are used.
+*/
+class KeyStore2HalVersion {
+ public static byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks)
+ throws KeyStoreException {
+ return new byte[0];
+ }
+}
diff --git a/keystore/java/android/security/KeyStore2HalLatest.java b/keystore/java/android/security/KeyStore2HalLatest.java
new file mode 100644
index 0000000..123f1c0
--- /dev/null
+++ b/keystore/java/android/security/KeyStore2HalLatest.java
@@ -0,0 +1,31 @@
+/*
+ * 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 android.security;
+
+/**
+ * @hide This class is necessary to allow the version of the AIDL interface for Keystore and
+* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When
+* `RELEASE_ATTEST_MODULES` is set, this file is included, and the latest HALs for Keystore (V5)
+* and KeyMint (V4) are used.
+*/
+class KeyStore2HalVersion {
+ public static byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks)
+ throws KeyStoreException {
+ return ks.handleRemoteExceptionWithRetry(
+ (service) -> service.getSupplementaryAttestationInfo(tag));
+ }
+}
diff --git a/keystore/java/android/security/keystore/KeyStoreManager.java b/keystore/java/android/security/keystore/KeyStoreManager.java
index e6091c1..740ccb5 100644
--- a/keystore/java/android/security/keystore/KeyStoreManager.java
+++ b/keystore/java/android/security/keystore/KeyStoreManager.java
@@ -17,9 +17,11 @@
package android.security.keystore;
import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.Context;
+import android.hardware.security.keymint.TagType;
import android.security.KeyStore2;
import android.security.KeyStoreException;
import android.security.keystore2.AndroidKeyStoreProvider;
@@ -32,6 +34,8 @@
import com.android.internal.annotations.GuardedBy;
import java.io.ByteArrayInputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.security.Key;
import java.security.KeyPair;
import java.security.PublicKey;
@@ -299,6 +303,37 @@
return Collections.emptyList();
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {MODULE_HASH})
+ public @interface SupplementaryAttestationInfoTagEnum {}
+
+ /**
+ * When passed into getSupplementaryAttestationInfo, getSupplementaryAttestationInfo returns the
+ * DER-encoded structure corresponding to the `Modules` schema described in the KeyMint HAL's
+ * KeyCreationResult.aidl. The SHA-256 hash of this encoded structure is what's included with
+ * the tag in attestations.
+ */
+ // TODO(b/369375199): Replace with Tag.MODULE_HASH when flagging is removed.
+ public static final int MODULE_HASH = TagType.BYTES | 724;
+
+ /**
+ * Returns tag-specific data required to interpret a tag's attested value.
+ *
+ * When performing key attestation, the obtained attestation certificate contains a list of tags
+ * and their corresponding attested values. For some tags, additional information about the
+ * attested value can be queried via this API. See individual tags for specifics.
+ *
+ * @param tag tag for which info is being requested
+ * @return tag-specific info
+ * @throws KeyStoreException if the requested info is not available
+ */
+ @FlaggedApi(android.security.keystore2.Flags.FLAG_ATTEST_MODULES)
+ public @NonNull byte[] getSupplementaryAttestationInfo(
+ @SupplementaryAttestationInfoTagEnum int tag) throws KeyStoreException {
+ return mKeyStore2.getSupplementaryAttestationInfo(tag);
+ }
+
/**
* Returns a new {@link KeyDescriptor} instance in the app domain / namespace with the {@code
* alias} set to the provided value.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 3e5adf3..5836085 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -1501,10 +1501,6 @@
int rootIdx = -1;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change c = info.getChanges().get(i);
- if (c.hasFlags(FLAG_IS_WALLPAPER)) {
- st.setAlpha(c.getLeash(), 1.0f);
- continue;
- }
if (TransitionUtil.isOpeningMode(c.getMode())) {
final Point offset = c.getEndRelOffset();
st.setPosition(c.getLeash(), offset.x, offset.y);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
index 30d7245..e61929f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
@@ -141,10 +141,13 @@
pipHandler.setEnterAnimationType(ANIM_TYPE_ALPHA);
pipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction,
finishCB);
+ // make a new finishTransaction because pip's startEnterAnimation "consumes" it so
+ // we need a separate one to send over to launcher.
+ SurfaceControl.Transaction otherFinishT = new SurfaceControl.Transaction();
// Dispatch the rest of the transition normally. This will most-likely be taken by
// recents or default handler.
mixed.mLeftoversHandler = player.dispatchTransition(mixed.mTransition, everythingElse,
- otherStartT, finishTransaction, finishCB, mixedHandler);
+ otherStartT, otherFinishT, finishCB, mixedHandler);
} else {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Not leaving split, so just "
+ "forward animation to Pip-Handler.");
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
index d03d779..d1bf6ac 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/FromSplitScreenEnterPipOnUserLeaveHintTest.kt
@@ -183,12 +183,6 @@
}
/** {@inheritDoc} */
- @FlakyTest(bugId = 312446524)
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
@Test
@FlakyTest(bugId = 336510055)
override fun entireScreenCovered() {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 749ad0a..6f8947c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2479,10 +2479,10 @@
final long identity = Binder.clearCallingIdentity();
try {
int currentUser = ActivityManager.getCurrentUser();
- if (callingUser == currentUser) {
- // enforce the deny list only if the caller is not current user. Currently only auto
- // uses background visible user, and auto doesn't support profiles so profiles of
- // current users is not checked here.
+ if (callingUser == currentUser || callingUser == UserHandle.USER_SYSTEM) {
+ // enforce the deny list only if the caller is not current user or not a system
+ // user. Currently only auto uses background visible user, and auto doesn't
+ // support profiles so profiles of current users is not checked here.
return;
}
} finally {
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index f8383d9..554ad8b 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1431,4 +1431,14 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+flag {
+ name: "ignore_touches_next_to_notification_shelf"
+ namespace: "systemui"
+ description: "The shelf can vertically overlap the unlock icon. Ignore touches if so."
+ bug: "358424256"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
index d9dcfdc..9c6fd4b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayCallbackControllerTest.kt
@@ -56,6 +56,7 @@
// Adding twice should not invoke twice
reset(callback)
+ underTest.onStartDream()
underTest.addCallback(callback)
underTest.onWakeUp()
verify(callback, times(1)).onWakeUp()
@@ -68,6 +69,19 @@
}
@Test
+ fun onWakeUp_multipleCalls() {
+ underTest.onStartDream()
+ assertThat(underTest.isDreaming).isEqualTo(true)
+
+ underTest.addCallback(callback)
+ underTest.onWakeUp()
+ underTest.onWakeUp()
+ underTest.onWakeUp()
+ verify(callback, times(1)).onWakeUp()
+ assertThat(underTest.isDreaming).isEqualTo(false)
+ }
+
+ @Test
fun onStartDreamInvokesCallback() {
underTest.addCallback(callback)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index 7dd7174..30b0aef 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -712,6 +712,9 @@
// Verify DreamOverlayContainerViewController is destroyed.
verify(mDreamOverlayContainerViewController).destroy()
+
+ // DreamOverlay callback receives onWakeUp.
+ verify(mDreamOverlayCallbackController).onWakeUp()
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt
new file mode 100644
index 0000000..22677b2
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelTest.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceEntryBackgroundViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val underTest: DeviceEntryBackgroundViewModel by lazy {
+ kosmos.deviceEntryBackgroundViewModel
+ }
+
+ @Test
+ fun lockscreenToDozingTransitionChangesBackgroundViewAlphaToZero() =
+ testScope.runTest {
+ kosmos.fingerprintPropertyRepository.supportsUdfps()
+ val alpha by collectLastValue(underTest.alpha)
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(dozingToLockscreen(0f, STARTED), dozingToLockscreen(0.1f)),
+ testScope,
+ )
+ runCurrent()
+ assertThat(alpha).isEqualTo(1.0f)
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ listOf(lockscreenToDozing(0f, STARTED)),
+ testScope,
+ )
+ runCurrent()
+
+ assertThat(alpha).isEqualTo(0.0f)
+ }
+
+ private fun lockscreenToDozing(value: Float, state: TransitionState = RUNNING): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
+ value = value,
+ transitionState = state,
+ ownerName = "DeviceEntryBackgroundViewModelTest",
+ )
+ }
+
+ private fun dozingToLockscreen(value: Float, state: TransitionState = RUNNING): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.DOZING,
+ to = KeyguardState.LOCKSCREEN,
+ value = value,
+ transitionState = state,
+ ownerName = "DeviceEntryBackgroundViewModelTest",
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 5d606c6..4b1ed3b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -189,17 +189,6 @@
}
@Test
- fun iconContainer_isVisible_bypassEnabled() =
- testScope.runTest {
- val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
- runCurrent()
- deviceEntryRepository.setBypassEnabled(true)
- runCurrent()
-
- assertThat(isVisible?.value).isTrue()
- }
-
- @Test
fun iconContainer_isNotVisible_pulseExpanding_notBypassing() =
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
@@ -288,22 +277,23 @@
}
@Test
- fun iconContainer_isNotVisible_bypassDisabled_onLockscreen() =
+ fun iconContainer_isNotVisible_notifsFullyHiddenThenVisible_bypassEnabled() =
testScope.runTest {
val isVisible by collectLastValue(underTest.isNotifIconContainerVisible)
runCurrent()
- keyguardTransitionRepository.sendTransitionSteps(
- from = KeyguardState.AOD,
- to = KeyguardState.LOCKSCREEN,
- testScope,
- )
notificationsKeyguardInteractor.setPulseExpanding(false)
- deviceEntryRepository.setBypassEnabled(false)
+ deviceEntryRepository.setBypassEnabled(true)
whenever(dozeParameters.alwaysOn).thenReturn(true)
whenever(dozeParameters.displayNeedsBlanking).thenReturn(false)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
runCurrent()
+ assertThat(isVisible?.value).isTrue()
+ assertThat(isVisible?.isAnimating).isTrue()
+
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
+ runCurrent()
+
assertThat(isVisible?.value).isFalse()
assertThat(isVisible?.isAnimating).isTrue()
}
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index 22d34eb..fbb07be 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -58,6 +58,14 @@
android:layout_height="match_parent"
android:visibility="invisible" />
+ <!-- Root for all keyguard content. It was previously located within the shade. -->
+ <com.android.systemui.keyguard.ui.view.KeyguardRootView
+ android:id="@id/keyguard_root_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ />
+
<!-- Shared container for the notification stack. Can be positioned by either
the keyguard_root_view or notification_panel -->
<com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
@@ -68,14 +76,6 @@
android:clipToPadding="false"
/>
- <!-- Root for all keyguard content. It was previously located within the shade. -->
- <com.android.systemui.keyguard.ui.view.KeyguardRootView
- android:id="@id/keyguard_root_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipChildren="false"
- />
-
<include layout="@layout/brightness_mirror_container" />
<com.android.systemui.scrim.ScrimView
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
index 373671d0..0949ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt
@@ -16,6 +16,7 @@
package com.android.systemui.bouncer.domain.interactor
+import android.util.Log
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
@@ -46,6 +47,7 @@
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
/** Encapsulates business logic for interacting with the lock-screen alternate bouncer. */
@@ -137,6 +139,8 @@
flowOf(false)
}
}
+ .distinctUntilChanged()
+ .onEach { Log.d(TAG, "canShowAlternateBouncer changed to $it") }
.stateIn(
scope = scope,
started = WhileSubscribed(),
@@ -234,5 +238,7 @@
companion object {
private const val MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS = 200L
+
+ private const val TAG = "AlternateBouncerInteractor"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayCallbackController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayCallbackController.kt
index d5ff8f2..2b61752 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayCallbackController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayCallbackController.kt
@@ -39,8 +39,10 @@
}
fun onWakeUp() {
- isDreaming = false
- callbacks.forEach { it.onWakeUp() }
+ if (isDreaming) {
+ isDreaming = false
+ callbacks.forEach { it.onWakeUp() }
+ }
}
fun onStartDream() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 113e001..0b465e9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -296,6 +296,8 @@
mStateController.setLowLightActive(false);
mStateController.setEntryAnimationsFinished(false);
+ mDreamOverlayCallbackController.onWakeUp();
+
if (mDreamOverlayContainerViewController != null) {
mDreamOverlayContainerViewController.destroy();
mDreamOverlayContainerViewController = null;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index afe3481..4d37276 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -189,6 +189,7 @@
internalTransitionInteractor.currentTransitionInfoInternal,
keyguardInteractor.statusBarState,
keyguardInteractor.isKeyguardDismissible,
+ keyguardInteractor.isKeyguardOccluded,
)
.collect {
(
@@ -196,7 +197,8 @@
startedStep,
currentTransitionInfo,
statusBarState,
- isKeyguardUnlocked) ->
+ isKeyguardUnlocked,
+ isKeyguardOccluded) ->
val id = transitionId
if (id != null) {
if (startedStep.to == KeyguardState.PRIMARY_BOUNCER) {
@@ -236,9 +238,13 @@
if (nextState == TransitionState.CANCELED) {
transitionRepository.startTransition(
TransitionInfo(
- ownerName = name,
+ ownerName =
+ "$name " +
+ "(on behalf of FromPrimaryBouncerInteractor)",
from = KeyguardState.PRIMARY_BOUNCER,
- to = KeyguardState.LOCKSCREEN,
+ to =
+ if (isKeyguardOccluded) KeyguardState.OCCLUDED
+ else KeyguardState.LOCKSCREEN,
modeOnCanceled = TransitionModeOnCanceled.REVERSE,
animator =
getDefaultAnimatorForTransitionsToState(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
index 86dae0c..69fc012 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
@@ -121,7 +121,10 @@
private fun applyClockDefaultConstraints(context: Context, constraints: ConstraintSet) {
constraints.apply {
constrainWidth(R.id.lockscreen_clock_view_large, ConstraintSet.WRAP_CONTENT)
- constrainHeight(R.id.lockscreen_clock_view_large, ConstraintSet.MATCH_CONSTRAINT)
+ // The following two lines make lockscreen_clock_view_large is constrained to available
+ // height when it goes beyond constraints; otherwise, it use WRAP_CONTENT
+ constrainHeight(R.id.lockscreen_clock_view_large, WRAP_CONTENT)
+ constrainMaxHeight(R.id.lockscreen_clock_view_large, 0)
val largeClockTopMargin =
SystemBarUtils.getStatusBarHeight(context) +
context.resources.getDimensionPixelSize(
@@ -138,7 +141,7 @@
R.id.lockscreen_clock_view_large,
ConstraintSet.END,
PARENT_ID,
- ConstraintSet.END
+ ConstraintSet.END,
)
// In preview, we'll show UDFPS icon for UDFPS devices
@@ -160,14 +163,14 @@
BOTTOM,
PARENT_ID,
BOTTOM,
- clockBottomMargin
+ clockBottomMargin,
)
}
constrainWidth(R.id.lockscreen_clock_view, WRAP_CONTENT)
constrainHeight(
R.id.lockscreen_clock_view,
- context.resources.getDimensionPixelSize(customizationR.dimen.small_clock_height)
+ context.resources.getDimensionPixelSize(customizationR.dimen.small_clock_height),
)
connect(
R.id.lockscreen_clock_view,
@@ -175,7 +178,7 @@
PARENT_ID,
START,
context.resources.getDimensionPixelSize(customizationR.dimen.clock_padding_start) +
- context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal)
+ context.resources.getDimensionPixelSize(R.dimen.status_view_margin_horizontal),
)
val smallClockTopMargin =
context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
@@ -188,7 +191,7 @@
context: Context,
rootView: ConstraintLayout,
previewClock: ClockController,
- viewModel: KeyguardPreviewClockViewModel
+ viewModel: KeyguardPreviewClockViewModel,
) {
val cs = ConstraintSet().apply { clone(rootView) }
applyClockDefaultConstraints(context, cs)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index a021de4..546b320 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -59,6 +59,7 @@
primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel,
primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel,
primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel,
+ lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel,
) {
val color: Flow<Int> =
deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground ->
@@ -103,6 +104,7 @@
primaryBouncerToLockscreenTransitionViewModel
.deviceEntryBackgroundViewAlpha,
occludedToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
+ lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
)
.merge()
.onStart {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 0b023d9..630fb99 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -341,12 +341,8 @@
when {
// If there are no notification icons to show, then it can be hidden
!hasAodIcons -> false
- // If we're bypassing, then we're visible
- isBypassEnabled -> true
// If we are pulsing (and not bypassing), then we are hidden
isPulseExpanding -> false
- // Besides bypass above, they should not be visible on lockscreen
- isOnLockscreen -> false
// If notifs are fully gone, then we're visible
areNotifsFullyHidden -> true
// Otherwise, we're hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
index d3eefca..7abf35d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
@@ -55,16 +55,16 @@
onCancel = { 1f },
)
+ val deviceEntryBackgroundViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(0f)
+
override val deviceEntryParentViewAlpha: Flow<Float> =
deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest {
isUdfpsEnrolledAndEnabled ->
if (isUdfpsEnrolledAndEnabled) {
transitionAnimation.immediatelyTransitionTo(1f)
} else {
- transitionAnimation.sharedFlow(
- duration = 250.milliseconds,
- onStep = { 1f - it },
- )
+ transitionAnimation.sharedFlow(duration = 250.milliseconds, onStep = { 1f - it })
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
index 55d7b1d..2bdee67 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
@@ -42,7 +42,7 @@
context: Context,
newController: MediaController,
new: MediaData,
- old: MediaData?
+ old: MediaData?,
): Boolean {
if (old == null || !mediaControlsPostsOptimization()) return false
@@ -71,7 +71,7 @@
/** Returns whether actions lists are equal. */
fun areCustomActionListsEqual(
first: List<PlaybackState.CustomAction>?,
- second: List<PlaybackState.CustomAction>?
+ second: List<PlaybackState.CustomAction>?,
): Boolean {
// Same object, or both null
if (first === second) {
@@ -94,7 +94,7 @@
private fun areCustomActionsEqual(
firstAction: PlaybackState.CustomAction,
- secondAction: PlaybackState.CustomAction
+ secondAction: PlaybackState.CustomAction,
): Boolean {
if (
firstAction.action != secondAction.action ||
@@ -139,7 +139,7 @@
context: Context,
newController: MediaController,
new: MediaData,
- old: MediaData
+ old: MediaData,
): Boolean {
val oldState = MediaController(context, old.token!!).playbackState
return if (
@@ -150,8 +150,7 @@
var same = true
new.actions.asSequence().zip(old.actions.asSequence()).forEach {
if (
- it.first.actionIntent?.intent?.filterEquals(it.second.actionIntent?.intent) !=
- true ||
+ it.first.actionIntent?.intent != it.second.actionIntent?.intent ||
it.first.icon != it.second.icon ||
it.first.contentDescription != it.second.contentDescription
) {
@@ -164,7 +163,7 @@
oldState?.actions == newController.playbackState?.actions &&
areCustomActionListsEqual(
oldState?.customActions,
- newController.playbackState?.customActions
+ newController.playbackState?.customActions,
)
} else {
false
@@ -172,8 +171,5 @@
}
private fun areClickIntentsEqual(newIntent: PendingIntent?, oldIntent: PendingIntent?): Boolean {
- if ((newIntent == null && oldIntent == null) || newIntent === oldIntent) return true
- if (newIntent == null || oldIntent == null) return false
-
- return newIntent.intent?.filterEquals(oldIntent.intent) == true
+ return newIntent == oldIntent
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 0c05dbd..e197f03 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -2710,6 +2710,11 @@
}
private int calculatePanelHeightShade() {
+ // Bypass should always occupy the full height
+ if (mBarState == KEYGUARD && mKeyguardBypassController.getBypassEnabled()) {
+ return mNotificationStackScrollLayoutController.getHeight();
+ }
+
int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin();
int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 7b6a2cb..560028c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -444,9 +444,11 @@
if (onFinishedRunnable != null) {
onFinishedRunnable.run();
}
+ if (mRunWithoutInterruptions) {
+ enableAppearDrawing(false);
+ }
// We need to reset the View state, even if the animation was cancelled
- enableAppearDrawing(false);
onAppearAnimationFinished(isAppearing);
if (mRunWithoutInterruptions) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 8c80fd4..36e3e92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -203,13 +203,16 @@
messagingStyle = mConversationProcessor
.processNotification(entry, builder, mLogger);
}
- result.mInflatedSingleLineViewModel = SingleLineViewInflater
+ SingleLineViewModel viewModel = SingleLineViewInflater
.inflateSingleLineViewModel(
entry.getSbn().getNotification(),
messagingStyle,
builder,
row.getContext()
);
+ // If the messagingStyle is null, we want to inflate the normal view
+ isConversation = viewModel.isConversation();
+ result.mInflatedSingleLineViewModel = viewModel;
result.mInflatedSingleLineView =
SingleLineViewInflater.inflatePrivateSingleLineView(
isConversation,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index d67947d..4e26ae8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -90,7 +90,7 @@
notification = notification,
isGroupConversation = isGroupConversation,
builder = builder,
- systemUiContext = systemUiContext
+ systemUiContext = systemUiContext,
)
val conversationData =
@@ -98,7 +98,7 @@
// We don't show the sender's name for one-to-one conversation
conversationSenderName =
if (isGroupConversation) conversationTextData?.senderName else null,
- avatar = conversationAvatar
+ avatar = conversationAvatar,
)
return SingleLineViewModel(
@@ -111,7 +111,7 @@
@JvmStatic
fun inflateRedactedSingleLineViewModel(
context: Context,
- isConversation: Boolean = false
+ isConversation: Boolean = false,
): SingleLineViewModel {
val conversationData =
if (isConversation) {
@@ -122,7 +122,7 @@
com.android.systemui.res.R.drawable
.ic_redacted_notification_single_line_icon
)
- )
+ ),
)
} else {
null
@@ -134,7 +134,7 @@
context.getString(
com.android.systemui.res.R.string.redacted_notification_single_line_text
),
- conversationData
+ conversationData,
)
}
@@ -159,11 +159,13 @@
}
// load the sender's name to display
- val name = lastMessage.senderPerson?.name
+ // null senderPerson means the current user.
+ val name = lastMessage.senderPerson?.name ?: user.name
+
val senderName =
systemUiContext.resources.getString(
R.string.conversation_single_line_name_display,
- if (Flags.cleanUpSpansAndNewLines()) name?.toString() else name
+ if (Flags.cleanUpSpansAndNewLines()) name?.toString() else name,
)
// We need to find back-up values for those texts if they are needed and empty
@@ -333,7 +335,7 @@
sender.icon
?: builder.getDefaultAvatar(
name = sender.name,
- uniqueNames = uniqueNames
+ uniqueNames = uniqueNames,
)
lastKey = senderKey
} else {
@@ -341,7 +343,7 @@
sender.icon
?: builder.getDefaultAvatar(
name = sender.name,
- uniqueNames = uniqueNames
+ uniqueNames = uniqueNames,
)
break
}
@@ -424,7 +426,7 @@
private fun Notification.Builder.getDefaultAvatar(
name: CharSequence?,
- uniqueNames: PeopleHelper.NameToPrefixMap? = null
+ uniqueNames: PeopleHelper.NameToPrefixMap? = null,
): Icon {
val layoutColor = getSmallIconColor(/* isHeader= */ false)
if (!name.isNullOrEmpty()) {
@@ -432,7 +434,7 @@
return peopleHelper.createAvatarSymbol(
/* name = */ name,
/* symbol = */ symbol,
- /* layoutColor = */ layoutColor
+ /* layoutColor = */ layoutColor,
)
}
// If name is null, create default avatar with background color
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
index 3b0f1ee..a17197c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/SingleLineViewBinder.kt
@@ -24,14 +24,14 @@
object SingleLineViewBinder {
@JvmStatic
fun bind(viewModel: SingleLineViewModel?, view: HybridNotificationView?) {
- if (viewModel?.isConversation() == true && view is HybridConversationNotificationView) {
+ if (view is HybridConversationNotificationView) {
if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) return
- viewModel.conversationData?.avatar?.let { view.setAvatar(it) }
+ viewModel?.conversationData?.avatar?.let { view.setAvatar(it) }
view.setText(
- viewModel.titleText,
- viewModel.contentText,
- viewModel.conversationData?.conversationSenderName
+ viewModel?.titleText,
+ viewModel?.contentText,
+ viewModel?.conversationData?.conversationSenderName,
)
} else {
// bind the title and content text views
@@ -39,7 +39,7 @@
bind(
/* title = */ viewModel?.titleText,
/* text = */ viewModel?.contentText,
- /* contentView = */ null
+ /* contentView = */ null,
)
}
}
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 dad6894..ae71ca4 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
@@ -24,6 +24,7 @@
import static com.android.server.notification.Flags.screenshareNotificationHiding;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Flags.confineNotificationTouchToViewWidth;
+import static com.android.systemui.Flags.ignoreTouchesNextToNotificationShelf;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener;
@@ -604,6 +605,16 @@
true /* requireMinHeight */,
false /* ignoreDecors */,
!confineNotificationTouchToViewWidth() /* ignoreWidth */);
+
+ // Verify the MotionEvent x,y are actually inside the touch area of the shelf,
+ // since the shelf may be animated down to a collapsed size on keyguard.
+ if (ignoreTouchesNextToNotificationShelf()) {
+ if (child instanceof NotificationShelf shelf) {
+ if (!NotificationSwipeHelper.isTouchInView(ev, shelf)) {
+ return null;
+ }
+ }
+ }
if (child instanceof ExpandableNotificationRow row) {
ExpandableNotificationRow parent = row.getNotificationParent();
if (parent != null && parent.areChildrenExpanded()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 7e327e6..0e94ca35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -18,6 +18,7 @@
package com.android.systemui.statusbar.notification.stack;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE;
+import static com.android.systemui.Flags.ignoreTouchesNextToNotificationShelf;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -39,6 +40,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -503,13 +505,21 @@
final int height = (view instanceof ExpandableView)
? ((ExpandableView) view).getActualHeight()
: view.getHeight();
+ final int width;
+ if (ignoreTouchesNextToNotificationShelf()) {
+ width = (view instanceof NotificationShelf)
+ ? ((NotificationShelf) view).getActualWidth()
+ : view.getWidth();
+ } else {
+ width = view.getWidth();
+ }
final int rx = (int) ev.getRawX();
final int ry = (int) ev.getRawY();
int[] temp = new int[2];
view.getLocationOnScreen(temp);
final int x = temp[0];
final int y = temp[1];
- Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
+ Rect rect = new Rect(x, y, x + width, y + height);
boolean ret = rect.contains(rx, ry);
return ret;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 1ea26e5..6fde603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -528,6 +528,7 @@
this::consumeKeyguardAuthenticatedBiometricsHandled
);
} else {
+ // Collector that keeps the AlternateBouncerInteractor#canShowAlternateBouncer flow hot.
mListenForCanShowAlternateBouncer = mJavaAdapter.alwaysCollectFlow(
mAlternateBouncerInteractor.getCanShowAlternateBouncer(),
this::consumeCanShowAlternateBouncer
@@ -576,8 +577,17 @@
}
private void consumeCanShowAlternateBouncer(boolean canShow) {
- // do nothing, we only are registering for the flow to ensure that there's at least
- // one subscriber that will update AlternateBouncerInteractor.canShowAlternateBouncer.value
+ // Hack: this is required to fix issues where
+ // KeyguardBouncerRepository#alternateBouncerVisible state is incorrectly set and then never
+ // reset. This is caused by usages of show()/forceShow() that only read this flow to set the
+ // alternate bouncer visible state, if there is a race condition between when that flow
+ // changes to false and when the read happens, the flow will be set to an incorrect value
+ // and not reset on time.
+ if (!canShow) {
+ Log.d(TAG, "canShowAlternateBouncer turned false, maybe try hiding the alternate "
+ + "bouncer if it is already visible");
+ mAlternateBouncerInteractor.maybeHide();
+ }
}
/** Register a callback, to be invoked by the Predictive Back system. */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index 6b3fb5b..503fa78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -29,12 +29,13 @@
import com.android.systemui.statusbar.notification.row.SingleLineViewInflater.inflatePublicSingleLineView
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder
-import com.android.systemui.util.mockito.mock
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
+import kotlin.test.assertNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -69,7 +70,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
val publicView =
@@ -78,7 +79,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
assertNotNull(publicView)
@@ -114,7 +115,7 @@
.addMessage(
"How about lunch?",
System.currentTimeMillis(),
- Person.Builder().setName("user2").build()
+ Person.Builder().setName("user2").build(),
)
.setGroupConversation(true)
notificationBuilder.setStyle(style).setShortcutId(SHORTCUT_ID)
@@ -127,7 +128,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
as HybridConversationNotificationView
@@ -137,7 +138,7 @@
reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
entry = row.entry,
context = context,
- logger = mock()
+ logger = mock(),
)
as HybridConversationNotificationView
assertNotNull(publicView)
@@ -150,10 +151,7 @@
systemUiContext = context,
)
// WHEN: binds the view
- SingleLineViewBinder.bind(
- viewModel,
- view,
- )
+ SingleLineViewBinder.bind(viewModel, view)
// THEN: the single-line conversation view should be bound with view model's corresponding
// fields
@@ -161,10 +159,55 @@
assertEquals(viewModel.contentText, view.textView.text)
assertEquals(
viewModel.conversationData?.conversationSenderName,
- view.conversationSenderNameView.text
+ view.conversationSenderNameView.text,
)
}
+ @Test
+ @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
+ fun bindConversationSingleLineView_nonConversationViewModel() {
+ // GIVEN: a ConversationSingleLineView, and a nonConversationViewModel
+ val style = Notification.BigTextStyle().bigText(CONTENT_TEXT)
+ notificationBuilder.setStyle(style)
+ val notification = notificationBuilder.build()
+ val row: ExpandableNotificationRow = helper.createRow(notification)
+
+ val view =
+ inflatePrivateSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+
+ val publicView =
+ inflatePublicSingleLineView(
+ isConversation = true,
+ reinflateFlags = FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+ entry = row.entry,
+ context = context,
+ logger = mock(),
+ )
+ assertNotNull(publicView)
+
+ val viewModel =
+ SingleLineViewInflater.inflateSingleLineViewModel(
+ notification = notification,
+ messagingStyle = null,
+ builder = notificationBuilder,
+ systemUiContext = context,
+ )
+ // WHEN: binds the view with the view model
+ SingleLineViewBinder.bind(viewModel, view)
+
+ // THEN: the single-line view should be bound with view model's corresponding
+ // fields as a normal non-conversation single-line view
+ assertEquals(viewModel.titleText, view?.titleView?.text)
+ assertEquals(viewModel.contentText, view?.textView?.text)
+ assertNull(viewModel.conversationData)
+ }
+
private companion object {
const val CHANNEL_ID = "CHANNEL_ID"
const val CONTENT_TITLE = "A Cool New Feature"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 95db95c..789701f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -13,6 +13,8 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.Flags.FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -36,6 +38,7 @@
import android.animation.Animator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.os.Handler;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.service.notification.StatusBarNotification;
import android.testing.TestableLooper;
@@ -52,6 +55,7 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
@@ -85,6 +89,7 @@
private NotificationMenuRowPlugin mMenuRow;
private Handler mHandler;
private ExpandableNotificationRow mNotificationRow;
+ private NotificationShelf mShelf;
private Runnable mFalsingCheck;
private final FeatureFlags mFeatureFlags = new FakeFeatureFlags();
@@ -111,6 +116,7 @@
mEvent = mock(MotionEvent.class);
mMenuRow = mock(NotificationMenuRowPlugin.class);
mNotificationRow = mock(ExpandableNotificationRow.class);
+ mShelf = mock(NotificationShelf.class);
mHandler = mock(Handler.class);
mFalsingCheck = mock(Runnable.class);
}
@@ -665,6 +671,54 @@
}
@Test
+ @EnableFlags(FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF)
+ public void testIsTouchInView_notificationShelf_flagEnabled() {
+ doReturn(500).when(mShelf).getWidth();
+ doReturn(FAKE_ROW_WIDTH).when(mShelf).getActualWidth();
+ doReturn(FAKE_ROW_HEIGHT).when(mShelf).getHeight();
+ doReturn(FAKE_ROW_HEIGHT).when(mShelf).getActualHeight();
+
+ Answer answer = (Answer) invocation -> {
+ int[] arr = invocation.getArgument(0);
+ arr[0] = 0;
+ arr[1] = 0;
+ return null;
+ };
+
+ doReturn(5f).when(mEvent).getRawX();
+ doReturn(10f).when(mEvent).getRawY();
+ doAnswer(answer).when(mShelf).getLocationOnScreen(any());
+ assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf));
+
+ doReturn(50f).when(mEvent).getRawX();
+ assertFalse("Touch is not within the view", mSwipeHelper.isTouchInView(mEvent, mShelf));
+ }
+
+ @Test
+ @DisableFlags(FLAG_IGNORE_TOUCHES_NEXT_TO_NOTIFICATION_SHELF)
+ public void testIsTouchInView_notificationShelf_flagDisabled() {
+ doReturn(500).when(mShelf).getWidth();
+ doReturn(FAKE_ROW_WIDTH).when(mShelf).getActualWidth();
+ doReturn(FAKE_ROW_HEIGHT).when(mShelf).getHeight();
+ doReturn(FAKE_ROW_HEIGHT).when(mShelf).getActualHeight();
+
+ Answer answer = (Answer) invocation -> {
+ int[] arr = invocation.getArgument(0);
+ arr[0] = 0;
+ arr[1] = 0;
+ return null;
+ };
+
+ doReturn(5f).when(mEvent).getRawX();
+ doReturn(10f).when(mEvent).getRawY();
+ doAnswer(answer).when(mShelf).getLocationOnScreen(any());
+ assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf));
+
+ doReturn(50f).when(mEvent).getRawX();
+ assertTrue("Touch is within the view", mSwipeHelper.isTouchInView(mEvent, mShelf));
+ }
+
+ @Test
public void testContentAlphaRemainsUnchangedWhenNotificationIsNotDismissible() {
doReturn(FAKE_ROW_WIDTH).when(mNotificationRow).getMeasuredWidth();
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt
new file mode 100644
index 0000000..09836ed
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModelKosmos.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@ExperimentalCoroutinesApi
+val Kosmos.deviceEntryBackgroundViewModel by Fixture {
+ DeviceEntryBackgroundViewModel(
+ context = applicationContext,
+ deviceEntryIconViewModel = deviceEntryIconViewModel,
+ configurationInteractor = configurationInteractor,
+ keyguardTransitionInteractor = keyguardTransitionInteractor,
+ alternateBouncerToAodTransitionViewModel = alternateBouncerToAodTransitionViewModel,
+ alternateBouncerToDozingTransitionViewModel = alternateBouncerToDozingTransitionViewModel,
+ aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
+ dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel,
+ dreamingToAodTransitionViewModel = dreamingToAodTransitionViewModel,
+ dreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel,
+ goneToAodTransitionViewModel = goneToAodTransitionViewModel,
+ goneToDozingTransitionViewModel = goneToDozingTransitionViewModel,
+ goneToLockscreenTransitionViewModel = goneToLockscreenTransitionViewModel,
+ lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel,
+ occludedToAodTransitionViewModel = occludedToAodTransitionViewModel,
+ occludedToDozingTransitionViewModel = occludedToDozingTransitionViewModel,
+ occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
+ primaryBouncerToAodTransitionViewModel = primaryBouncerToAodTransitionViewModel,
+ primaryBouncerToDozingTransitionViewModel = primaryBouncerToDozingTransitionViewModel,
+ primaryBouncerToLockscreenTransitionViewModel =
+ primaryBouncerToLockscreenTransitionViewModel,
+ lockscreenToDozingTransitionViewModel = lockscreenToDozingTransitionViewModel,
+ )
+}
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 66c8d0f..59043a83 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -182,21 +182,6 @@
visibility: [":__subpackages__"],
}
-// Separated out from ravenwood-junit-impl since it needs to compile
-// against `module_current`
-java_library {
- name: "ravenwood-junit-impl-flag",
- srcs: [
- "junit-flag-src/**/*.java",
- ],
- sdk_version: "module_current",
- libs: [
- "junit",
- "flag-junit",
- ],
- visibility: ["//visibility:public"],
-}
-
// Carefully compiles against only module_current to support tests that
// want to verify they're unbundled. The "impl" library above is what
// ships inside the Ravenwood environment to actually drive any API
@@ -651,7 +636,6 @@
"flag-junit",
"ravenwood-framework",
"ravenwood-junit-impl",
- "ravenwood-junit-impl-flag",
"mockito-ravenwood-prebuilt",
"inline-mockito-ravenwood-prebuilt",
diff --git a/ravenwood/junit-flag-src/android/platform/test/flag/junit/RavenwoodFlagsValueProvider.java b/ravenwood/junit-flag-src/android/platform/test/flag/junit/RavenwoodFlagsValueProvider.java
deleted file mode 100644
index 9d62774..0000000
--- a/ravenwood/junit-flag-src/android/platform/test/flag/junit/RavenwoodFlagsValueProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 android.platform.test.flag.junit;
-
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.IFlagsValueProvider;
-
-/**
- * Offer to create {@link CheckFlagsRule} instances that are useful on the Ravenwood deviceless
- * testing environment.
- *
- * At the moment, default flag values are not available on Ravenwood, so the only options offered
- * here are "all-on" and "all-off" options. Tests that want to exercise specific flag states should
- * use {@link android.platform.test.flag.junit.SetFlagsRule}.
- */
-public class RavenwoodFlagsValueProvider {
- /**
- * Create a {@link CheckFlagsRule} instance where flags are in an "all-on" state.
- */
- public static CheckFlagsRule createAllOnCheckFlagsRule() {
- return new CheckFlagsRule(new IFlagsValueProvider() {
- @Override
- public boolean getBoolean(String flag) {
- return true;
- }
- });
- }
-
- /**
- * Create a {@link CheckFlagsRule} instance where flags are in an "all-off" state.
- */
- public static CheckFlagsRule createAllOffCheckFlagsRule() {
- return new CheckFlagsRule(new IFlagsValueProvider() {
- @Override
- public boolean getBoolean(String flag) {
- return false;
- }
- });
- }
-}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 9644a52..3ebef02 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -129,7 +129,7 @@
mTestClass = new TestClass(testClass);
- Log.v(TAG, "RavenwoodAwareTestRunner starting for " + testClass.getCanonicalName());
+ Log.v(TAG, "RavenwoodAwareTestRunner initializing for " + testClass.getCanonicalName());
// Hook point to allow more customization.
runAnnotatedMethodsOnRavenwood(RavenwoodTestRunnerInitializing.class, null);
@@ -146,7 +146,9 @@
private void runAnnotatedMethodsOnRavenwood(Class<? extends Annotation> annotationClass,
Object instance) {
- Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
+ }
for (var method : mTestClass.getAnnotatedMethods(annotationClass)) {
ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
@@ -169,12 +171,14 @@
RavenwoodTestStats.getInstance().attachToRunNotifier(notifier);
if (mRealRunner instanceof ClassSkippingTestRunner) {
- Log.i(TAG, "onClassSkipped: description=" + description);
+ Log.v(TAG, "onClassSkipped: description=" + description);
mRealRunner.run(notifier);
return;
}
- Log.v(TAG, "Starting " + mTestJavaClass.getCanonicalName());
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "Running " + mTestJavaClass.getCanonicalName());
+ }
if (RAVENWOOD_VERBOSE_LOGGING) {
dumpDescription(description);
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
index a5d0bfd..70bc52b 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRunnerState.java
@@ -15,6 +15,8 @@
*/
package android.platform.test.ravenwood;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -59,16 +61,22 @@
private Description mMethodDescription;
public void enterTestRunner() {
- Log.i(TAG, "enterTestRunner: " + mRunner);
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "enterTestRunner: " + mRunner);
+ }
RavenwoodRuntimeEnvironmentController.initForRunner();
}
public void enterTestClass() {
- Log.i(TAG, "enterTestClass: " + mRunner.mTestJavaClass.getName());
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "enterTestClass: " + mRunner.mTestJavaClass.getName());
+ }
}
public void exitTestClass() {
- Log.i(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName());
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "exitTestClass: " + mRunner.mTestJavaClass.getName());
+ }
assertTrue(RAVENWOOD_RULE_ERROR, sActiveProperties.isEmpty());
RavenwoodRuntimeEnvironmentController.exitTestClass();
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index 930914f..3cb6c5a 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -552,7 +552,7 @@
}
private static void dumpCommandLineArgs() {
- Log.i(TAG, "JVM arguments:");
+ Log.v(TAG, "JVM arguments:");
// Note, we use the wrapper in JUnit4, not the actual class (
// java.lang.management.ManagementFactory), because we can't see the later at the build
@@ -561,7 +561,7 @@
var args = ManagementFactory.getRuntimeMXBean().getInputArguments();
for (var arg : args) {
- Log.i(TAG, " " + arg);
+ Log.v(TAG, " " + arg);
}
}
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
index fac0791..70c161c1 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
@@ -84,7 +84,7 @@
var ravenwoodProps = readProperties(path + RAVENWOOD_BUILD_PROP);
var deviceProps = readProperties(path + DEVICE_BUILD_PROP);
- Log.i(TAG, "Default system properties:");
+ Log.v(TAG, "Default system properties:");
ravenwoodProps.forEach((key, origValue) -> {
final String value;
@@ -100,7 +100,7 @@
} else {
value = origValue;
}
- Log.i(TAG, key + "=" + value);
+ Log.v(TAG, key + "=" + value);
sDefaultValues.put(key, value);
});
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
index f3688d6..3592105 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerBase.java
@@ -15,6 +15,8 @@
*/
package android.platform.test.ravenwood;
+import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
+
import android.platform.test.annotations.internal.InnerRunner;
import android.util.Log;
@@ -53,7 +55,9 @@
}
try {
- Log.i(TAG, "Initializing the inner runner: " + runnerClass);
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ Log.v(TAG, "Initializing the inner runner: " + runnerClass);
+ }
try {
return runnerClass.getConstructor(Class.class)
.newInstance(testClass.getJavaClass());
diff --git a/ravenwood/runtime-jni/ravenwood_initializer.cpp b/ravenwood/runtime-jni/ravenwood_initializer.cpp
index dbbc345..391c5d5 100644
--- a/ravenwood/runtime-jni/ravenwood_initializer.cpp
+++ b/ravenwood/runtime-jni/ravenwood_initializer.cpp
@@ -140,7 +140,7 @@
if (gVM != nullptr && gRunnerState != nullptr) {
JNIEnv* env;
if (gVM->GetEnv((void**)&env, JNI_VERSION_1_4) >= 0) {
- ALOGI("%s access to system property '%s'", write ? "Write" : "Read", key);
+ ALOGV("%s access to system property '%s'", write ? "Write" : "Read", key);
env->CallStaticVoidMethod(gRunnerState, gCheckSystemPropertyAccess,
env->NewStringUTF(key), write ? JNI_TRUE : JNI_FALSE);
return;
@@ -208,7 +208,7 @@
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
- ALOGI("%s: JNI_OnLoad", __FILE__);
+ ALOGV("%s: JNI_OnLoad", __FILE__);
maybeRedirectLog();
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index bab4c7e..8d8ed71 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -204,7 +204,7 @@
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
- ALOGI("%s: JNI_OnLoad", __FILE__);
+ ALOGV("%s: JNI_OnLoad", __FILE__);
JNIEnv* env = GetJNIEnvOrDie(vm);
g_StructStat = FindGlobalClassOrDie(env, "android/system/StructStat");
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7580b69..49f15e4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3653,6 +3653,12 @@
return;
}
+ // Magnification connection should not be requested for visible background users.
+ // (b/332222893)
+ if (mUmi.isVisibleBackgroundFullUser(userState.mUserId)) {
+ return;
+ }
+
final boolean shortcutEnabled = (userState.isShortcutMagnificationEnabledLocked()
|| userState.isMagnificationSingleFingerTripleTapEnabledLocked()
|| (Flags.enableMagnificationMultipleFingerMultipleTapGesture()
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
index 19e3e69..fe06406 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationConnectionManager.java
@@ -19,6 +19,7 @@
import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION_CALLBACK;
import static android.os.Build.HW_TIMEOUT_MULTIPLIER;
+import static android.os.UserHandle.getCallingUserId;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID;
@@ -54,6 +55,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -209,6 +211,7 @@
private final Callback mCallback;
private final AccessibilityTraceManager mTrace;
private final MagnificationScaleProvider mScaleProvider;
+ private final UserManagerInternal mUserManagerInternal;
public MagnificationConnectionManager(Context context, Object lock, @NonNull Callback callback,
AccessibilityTraceManager trace, MagnificationScaleProvider scaleProvider) {
@@ -217,6 +220,7 @@
mCallback = callback;
mTrace = trace;
mScaleProvider = scaleProvider;
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
}
/**
@@ -280,12 +284,18 @@
* Requests {@link IMagnificationConnection} through
* {@link StatusBarManagerInternal#requestMagnificationConnection(boolean)} and
* destroys all window magnifications if necessary.
+ * NOTE: Currently, this is not allowed to call from visible background users.(b/332222893)
*
* @param connect {@code true} if needs connection, otherwise set the connection to null and
* destroy all window magnifications.
* @return {@code true} if {@link IMagnificationConnection} state is going to change.
*/
public boolean requestConnection(boolean connect) {
+ final int callingUserId = getCallingUserId();
+ if (mUserManagerInternal.isVisibleBackgroundFullUser(callingUserId)) {
+ throw new SecurityException("Visible background user(u" + callingUserId
+ + " is not permitted to request magnification connection.");
+ }
if (DBG) {
Slog.d(TAG, "requestConnection :" + connect);
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index c9f8929..b52c6505 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -92,6 +92,7 @@
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.PrintWriter;
@@ -192,6 +193,8 @@
private final ContentCaptureManagerInternal mContentCaptureManagerInternal;
+ private final UserManagerInternal mUserManagerInternal;
+
private final DisabledInfoCache mDisabledInfoCache;
AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
@@ -208,6 +211,7 @@
mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
mContentCaptureManagerInternal = LocalServices.getService(
ContentCaptureManagerInternal.class);
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mDisabledInfoCache = disableCache;
updateLocked(disabled);
}
@@ -379,6 +383,13 @@
return 0;
}
+ // TODO(b/376482880): remove this check once autofill service supports visible
+ // background users.
+ if (mUserManagerInternal.isVisibleBackgroundFullUser(mUserId)) {
+ Slog.d(TAG, "Currently, autofill service does not support visible background users.");
+ return 0;
+ }
+
if (!forAugmentedAutofillOnly && isAutofillDisabledLocked(clientActivity)) {
// Standard autofill is enabled, but service disabled autofill for this activity; that
// means no session, unless the activity is allowlisted for augmented autofill
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f32031de..f2069d0 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -427,6 +427,11 @@
mDreamsDisabledByAmbientModeSuppression = disabledByAmbientModeSuppression;
}
+ @VisibleForTesting
+ void setCurrentUser(int currentUserId) {
+ mCurrentUser = currentUserId;
+ }
+
@Override
public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
mCurrentUser = to.getUserIdentifier();
@@ -848,9 +853,9 @@
throw new IllegalArgumentException("Unknown mode: " + mode);
}
- final int user = UserHandle.getCallingUserId();
- enforceCurrentUserIfVisibleBackgroundEnabled(user);
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
+ final int user = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -913,7 +918,7 @@
@AttentionModeThemeOverlayType int attentionModeThemeOverlayType) {
setAttentionModeThemeOverlay_enforcePermission();
- enforceCurrentUserIfVisibleBackgroundEnabled(UserHandle.getCallingUserId());
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
synchronized (mLock) {
if (mAttentionModeThemeOverlay != attentionModeThemeOverlayType) {
@@ -1004,16 +1009,16 @@
return false;
}
final int user = Binder.getCallingUserHandle().getIdentifier();
- enforceCurrentUserIfVisibleBackgroundEnabled(user);
-
if (user != mCurrentUser && getContext().checkCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS)
!= PackageManager.PERMISSION_GRANTED) {
Slog.e(TAG, "Target user is not current user,"
+ " INTERACT_ACROSS_USERS permission is required");
return false;
-
}
+
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
+
// Store the last requested bedtime night mode state so that we don't need to notify
// anyone if the user decides to switch to the night mode to bedtime.
if (modeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
@@ -1062,9 +1067,10 @@
Slog.e(TAG, "Set custom time start, requires MODIFY_DAY_NIGHT_MODE permission");
return;
}
- final int user = UserHandle.getCallingUserId();
- enforceCurrentUserIfVisibleBackgroundEnabled(user);
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
+
+ final int user = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
LocalTime newTime = LocalTime.ofNanoOfDay(time * 1000);
@@ -1092,9 +1098,10 @@
Slog.e(TAG, "Set custom time end, requires MODIFY_DAY_NIGHT_MODE permission");
return;
}
- final int user = UserHandle.getCallingUserId();
- enforceCurrentUserIfVisibleBackgroundEnabled(user);
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
+
+ final int user = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
try {
LocalTime newTime = LocalTime.ofNanoOfDay(time * 1000);
@@ -1115,7 +1122,7 @@
assertLegit(callingPackage);
assertSingleProjectionType(projectionType);
enforceProjectionTypePermissions(projectionType);
- enforceCurrentUserIfVisibleBackgroundEnabled(getCallingUserId());
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
synchronized (mLock) {
if (mProjectionHolders == null) {
@@ -1161,7 +1168,7 @@
assertLegit(callingPackage);
assertSingleProjectionType(projectionType);
enforceProjectionTypePermissions(projectionType);
- enforceCurrentUserIfVisibleBackgroundEnabled(getCallingUserId());
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
return releaseProjectionUnchecked(projectionType, callingPackage);
}
@@ -1203,7 +1210,7 @@
return;
}
- enforceCurrentUserIfVisibleBackgroundEnabled(getCallingUserId());
+ enforceCurrentUserIfVisibleBackgroundEnabled(mCurrentUser);
synchronized (mLock) {
if (mProjectionListeners == null) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 88edb12..3499a3a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1773,8 +1773,7 @@
// Create a Session for the target user and pass in the bundle
completeCloningAccount(response, result, account, toAccounts, userFrom);
} else {
- // Bundle format is not defined.
- super.onResultSkipSanitization(result);
+ super.onResult(result);
}
}
}.bind();
@@ -1861,8 +1860,7 @@
// account to avoid retries?
// TODO: what we do with the visibility?
- // Bundle format is not defined.
- super.onResultSkipSanitization(result);
+ super.onResult(result);
}
@Override
@@ -2108,7 +2106,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
IAccountManagerResponse response = getResponseAndClose();
if (response != null) {
try {
@@ -2462,7 +2459,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
&& !result.containsKey(AccountManager.KEY_INTENT)) {
final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
@@ -2977,7 +2973,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
if (result != null) {
String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
Bundle bundle = new Bundle();
@@ -3155,7 +3150,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(
@@ -3627,12 +3621,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- Bundle sessionBundle = null;
- if (result != null) {
- // Session bundle will be removed from result.
- sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- }
- result = sanitizeBundle(result);
mNumResults++;
Intent intent = null;
if (result != null) {
@@ -3694,6 +3682,7 @@
// bundle contains data necessary for finishing the session
// later. The session bundle will be encrypted here and
// decrypted later when trying to finish the session.
+ Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
if (sessionBundle != null) {
String accountType = sessionBundle.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(accountType)
@@ -4081,7 +4070,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
IAccountManagerResponse response = getResponseAndClose();
if (response == null) {
return;
@@ -4395,7 +4383,6 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
mNumResults++;
if (result == null) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
@@ -4952,68 +4939,6 @@
callback, resultReceiver);
}
-
- // All keys for Strings passed from AbstractAccountAuthenticator using Bundle.
- private static final String[] sStringBundleKeys = new String[] {
- AccountManager.KEY_ACCOUNT_NAME,
- AccountManager.KEY_ACCOUNT_TYPE,
- AccountManager.KEY_AUTHTOKEN,
- AccountManager.KEY_AUTH_TOKEN_LABEL,
- AccountManager.KEY_ERROR_MESSAGE,
- AccountManager.KEY_PASSWORD,
- AccountManager.KEY_ACCOUNT_STATUS_TOKEN};
-
- /**
- * Keep only documented fields in a Bundle received from AbstractAccountAuthenticator.
- */
- protected static Bundle sanitizeBundle(Bundle bundle) {
- if (bundle == null) {
- return null;
- }
- Bundle sanitizedBundle = new Bundle();
- Bundle.setDefusable(sanitizedBundle, true);
- int updatedKeysCount = 0;
- for (String stringKey : sStringBundleKeys) {
- if (bundle.containsKey(stringKey)) {
- String value = bundle.getString(stringKey);
- sanitizedBundle.putString(stringKey, value);
- updatedKeysCount++;
- }
- }
- String key = AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY;
- if (bundle.containsKey(key)) {
- long expiryMillis = bundle.getLong(key, 0L);
- sanitizedBundle.putLong(key, expiryMillis);
- updatedKeysCount++;
- }
- key = AccountManager.KEY_BOOLEAN_RESULT;
- if (bundle.containsKey(key)) {
- boolean booleanResult = bundle.getBoolean(key, false);
- sanitizedBundle.putBoolean(key, booleanResult);
- updatedKeysCount++;
- }
- key = AccountManager.KEY_ERROR_CODE;
- if (bundle.containsKey(key)) {
- int errorCode = bundle.getInt(key, 0);
- sanitizedBundle.putInt(key, errorCode);
- updatedKeysCount++;
- }
- key = AccountManager.KEY_INTENT;
- if (bundle.containsKey(key)) {
- Intent intent = bundle.getParcelable(key, Intent.class);
- sanitizedBundle.putParcelable(key, intent);
- updatedKeysCount++;
- }
- if (bundle.containsKey(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE)) {
- // The field is not copied in sanitized bundle.
- updatedKeysCount++;
- }
- if (updatedKeysCount != bundle.size()) {
- Log.w(TAG, "Size mismatch after sanitizeBundle call.");
- }
- return sanitizedBundle;
- }
-
private abstract class Session extends IAccountAuthenticatorResponse.Stub
implements IBinder.DeathRecipient, ServiceConnection {
private final Object mSessionLock = new Object();
@@ -5304,15 +5229,10 @@
}
}
}
+
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
- result = sanitizeBundle(result);
- onResultSkipSanitization(result);
- }
-
- public void onResultSkipSanitization(Bundle result) {
- Bundle.setDefusable(result, true);
mNumResults++;
Intent intent = null;
if (result != null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3666524..f9197e3c 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -5077,7 +5077,10 @@
+ " requires " + r.permission);
return new ServiceLookupResult(r.permission);
} else if ((Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals(r.permission)
- || Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE.equals(r.permission))
+ || Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE.equals(r.permission)
+ || Manifest.permission.BIND_WEARABLE_SENSING_SERVICE.equals(r.permission)
+ || Manifest.permission.BIND_ON_DEVICE_SANDBOXED_INFERENCE_SERVICE.equals(
+ r.permission))
&& callingUid != Process.SYSTEM_UID) {
// Hotword detection and visual query detection must run in its own sandbox, and we
// don't even trust its enclosing application to bind to it - only the system.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f64a163..e1909d9 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1583,8 +1583,11 @@
synchronized (mCachedAbsVolDrivingStreamsLock) {
mCachedAbsVolDrivingStreams.forEach((dev, stream) -> {
- mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", /*enabled=*/true,
- stream);
+ boolean enabled = true;
+ if (dev == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+ enabled = mAvrcpAbsVolSupported;
+ }
+ mAudioSystem.setDeviceAbsoluteVolumeEnabled(dev, /*address=*/"", enabled, stream);
});
}
}
@@ -4848,7 +4851,7 @@
if (absDev == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
enabled = mAvrcpAbsVolSupported;
}
- if (stream != streamType) {
+ if (stream != streamType || !enabled) {
mAudioSystem.setDeviceAbsoluteVolumeEnabled(absDev, /*address=*/"",
enabled, streamType);
}
@@ -10354,10 +10357,10 @@
}
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean support) {
- mAvrcpAbsVolSupported = support;
- if (absVolumeIndexFix()) {
- int a2dpDev = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
- synchronized (mCachedAbsVolDrivingStreamsLock) {
+ synchronized (mCachedAbsVolDrivingStreamsLock) {
+ mAvrcpAbsVolSupported = support;
+ if (absVolumeIndexFix()) {
+ int a2dpDev = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
mCachedAbsVolDrivingStreams.compute(a2dpDev, (dev, stream) -> {
if (!mAvrcpAbsVolSupported) {
mAudioSystem.setDeviceAbsoluteVolumeEnabled(a2dpDev, /*address=*/
@@ -12420,6 +12423,12 @@
pw.println("\nLoudness alignment:");
mLoudnessCodecHelper.dump(pw);
+ pw.println("\nAbsolute voume devices:");
+ synchronized (mCachedAbsVolDrivingStreamsLock) {
+ mCachedAbsVolDrivingStreams.forEach((dev, stream) -> pw.println(
+ "Device type: 0x" + Integer.toHexString(dev) + ", driving stream " + stream));
+ }
+
mAudioSystem.dump(pw);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8a7dabd..cc41b73 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3389,18 +3389,31 @@
return true;
}
// Does it contain a device admin for any user?
- int[] users;
+ int[] allUsers = mUserManager.getUserIds();
+ int[] targetUsers;
if (userId == UserHandle.USER_ALL) {
- users = mUserManager.getUserIds();
+ targetUsers = allUsers;
} else {
- users = new int[]{userId};
+ targetUsers = new int[]{userId};
}
- for (int i = 0; i < users.length; ++i) {
- if (dpm.packageHasActiveAdmins(packageName, users[i])) {
+
+ for (int i = 0; i < targetUsers.length; ++i) {
+ if (dpm.packageHasActiveAdmins(packageName, targetUsers[i])) {
return true;
}
- if (isDeviceManagementRoleHolder(packageName, users[i])
- && dpmi.isUserOrganizationManaged(users[i])) {
+ }
+
+ // If a package is DMRH on a managed user, it should also be treated as an admin on
+ // that user. If that package is also a system package, it should also be protected
+ // on other users otherwise "uninstall updates" on an unmanaged user may break
+ // management on other users because apk version is shared between all users.
+ var packageState = snapshotComputer().getPackageStateInternal(packageName);
+ if (packageState == null) {
+ return false;
+ }
+ for (int user : packageState.isSystem() ? allUsers : targetUsers) {
+ if (isDeviceManagementRoleHolder(packageName, user)
+ && dpmi.isUserOrganizationManaged(user)) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index df9f7fb..5fc3e33 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1015,8 +1015,7 @@
permission, attributionSource, message, forDataDelivery, startDataDelivery,
fromDatasource, attributedOp);
// Finish any started op if some step in the attribution chain failed.
- if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED
- && result != PermissionChecker.PERMISSION_SOFT_DENIED) {
+ if (startDataDelivery && result != PermissionChecker.PERMISSION_GRANTED) {
if (attributedOp == AppOpsManager.OP_NONE) {
finishDataDelivery(AppOpsManager.permissionToOpCode(permission),
attributionSource.asState(), fromDatasource);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 63491e8..e0c4ebe 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -37,6 +37,7 @@
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.O;
import static android.os.IInputConstants.INVALID_INPUT_DEVICE_ID;
+import static android.os.UserManager.isVisibleBackgroundUsersEnabled;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -184,6 +185,7 @@
import android.service.vr.IPersistentVrStateCallbacks;
import android.speech.RecognizerIntent;
import android.telecom.TelecomManager;
+import android.util.ArraySet;
import android.util.Log;
import android.util.MathUtils;
import android.util.MutableBoolean;
@@ -256,6 +258,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -718,6 +721,25 @@
// Timeout for showing the keyguard after the screen is on, in case no "ready" is received.
private int mKeyguardDrawnTimeout = 1000;
+ private final boolean mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled();
+
+ // Key codes that should be ignored for visible background users in MUMD environment.
+ private static final Set<Integer> KEY_CODES_IGNORED_FOR_VISIBLE_BACKGROUND_USERS =
+ new ArraySet<>(Arrays.asList(
+ KeyEvent.KEYCODE_POWER,
+ KeyEvent.KEYCODE_SLEEP,
+ KeyEvent.KEYCODE_WAKEUP,
+ KeyEvent.KEYCODE_CALL,
+ KeyEvent.KEYCODE_ENDCALL,
+ KeyEvent.KEYCODE_ASSIST,
+ KeyEvent.KEYCODE_VOICE_ASSIST,
+ KeyEvent.KEYCODE_MUTE,
+ KeyEvent.KEYCODE_VOLUME_MUTE,
+ KeyEvent.KEYCODE_RECENT_APPS,
+ KeyEvent.KEYCODE_APP_SWITCH,
+ KeyEvent.KEYCODE_NOTIFICATION
+ ));
+
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -811,7 +833,11 @@
event.recycle();
break;
case MSG_HANDLE_ALL_APPS:
- launchAllAppsAction();
+ KeyEvent keyEvent = (KeyEvent) msg.obj;
+ if (isKeyEventForCurrentUser(keyEvent.getDisplayId(), keyEvent.getKeyCode(),
+ "launchAllAppsViaA11y")) {
+ launchAllAppsAction();
+ }
break;
case MSG_RINGER_TOGGLE_CHORD:
handleRingerChordGesture();
@@ -2054,12 +2080,21 @@
}
switch (mDoubleTapOnHomeBehavior) {
case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
+ if (!isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(), "toggleRecentApps")) {
+ break;
+ }
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH);
mHomeConsumed = true;
toggleRecentApps();
break;
case DOUBLE_TAP_HOME_PIP_MENU:
+ if (!isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(),
+ "showPictureInPictureMenu")) {
+ break;
+ }
mHomeConsumed = true;
showPictureInPictureMenuInternal();
break;
@@ -2082,15 +2117,26 @@
switch (mLongPressOnHomeBehavior) {
case LONG_PRESS_HOME_ALL_APPS:
notifyKeyGestureCompleted(event, KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
- launchAllAppsAction();
+ if (isKeyEventForCurrentUser(event.getDisplayId(), event.getKeyCode(),
+ "launchAllAppsViaA11y")) {
+ launchAllAppsAction();
+ }
break;
case LONG_PRESS_HOME_ASSIST:
+ if (!isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(), "launchAssistAction")) {
+ break;
+ }
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
launchAssistAction(null, event.getDeviceId(), event.getEventTime(),
AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
break;
case LONG_PRESS_HOME_NOTIFICATION_PANEL:
+ if (!isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(), "toggleNotificationPanel")) {
+ break;
+ }
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
toggleNotificationPanel();
@@ -3451,7 +3497,11 @@
if (isUserSetupComplete() && !keyguardOn) {
if (mModifierShortcutManager.interceptKey(event)) {
- dismissKeyboardShortcutsMenu();
+ if (isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(),
+ "dismissKeyboardShortcutsMenu")) {
+ dismissKeyboardShortcutsMenu();
+ }
mPendingMetaAction = false;
mPendingCapsLockToggle = false;
return true;
@@ -3763,7 +3813,10 @@
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
} else if (mPendingMetaAction) {
if (!canceled) {
- launchAllAppsAction();
+ if (isKeyEventForCurrentUser(event.getDisplayId(), event.getKeyCode(),
+ "launchAllAppsViaA11y")) {
+ launchAllAppsAction();
+ }
notifyKeyGestureCompleted(event,
KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
}
@@ -4030,7 +4083,8 @@
return true;
case KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS:
case KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS:
- if (complete) {
+ if (complete && isKeyEventForCurrentUser(event.getDisplayId(),
+ event.getKeycodes()[0], "launchAllAppsViaA11y")) {
launchAllAppsAction();
}
return true;
@@ -4703,7 +4757,10 @@
}
// no keyguard stuff to worry about, just launch home!
- if (mRecentsVisible) {
+ // If Recents is visible and the action is not from visible background users,
+ // hide Recents and notify it to launch Home.
+ if (mRecentsVisible
+ && (!mVisibleBackgroundUsersEnabled || displayId == DEFAULT_DISPLAY)) {
try {
ActivityManager.getService().stopAppSwitches();
} catch (RemoteException e) {}
@@ -4859,6 +4916,14 @@
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
+ // There are key events that perform the operation as the current user,
+ // and these should be ignored for visible background users.
+ if (mVisibleBackgroundUsersEnabled
+ && KEY_CODES_IGNORED_FOR_VISIBLE_BACKGROUND_USERS.contains(keyCode)
+ && !isKeyEventForCurrentUser(event.getDisplayId(), keyCode, null)) {
+ return 0;
+ }
+
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
// Exception: Wake and power key events are forwarded to PowerManager to allow it to
@@ -5439,6 +5504,9 @@
* Notify the StatusBar that a system key was pressed.
*/
private void sendSystemKeyToStatusBar(KeyEvent key) {
+ if (!isKeyEventForCurrentUser(key.getDisplayId(), key.getKeyCode(), "handleSystemKey")) {
+ return;
+ }
IStatusBarService statusBar = getStatusBarService();
if (statusBar != null) {
try {
@@ -5866,6 +5934,10 @@
}
private void wakeUpFromWakeKey(KeyEvent event) {
+ if (!isKeyEventForCurrentUser(
+ event.getDisplayId(), event.getKeyCode(), "wakeUpFromWakeKey")) {
+ return;
+ }
wakeUpFromWakeKey(
event.getEventTime(),
event.getKeyCode(),
@@ -6445,6 +6517,12 @@
// TODO (b/113840485): Move this logic to DisplayPolicy when lockscreen supports multi-display.
@Override
public void setAllowLockscreenWhenOn(int displayId, boolean allow) {
+ // We should ignore this operation for visible background users
+ // until lockscreen supports multi-display.
+ if (mVisibleBackgroundUsersEnabled
+ && mUserManagerInternal.getUserAssignedToDisplay(displayId) != mCurrentUserId) {
+ return;
+ }
if (allow) {
mAllowLockscreenWhenOnDisplays.add(displayId);
} else {
@@ -7253,4 +7331,29 @@
}
return DEFAULT_DISPLAY;
}
+
+ /**
+ * This method is intended to prevent key events for visible background users
+ * from interfering with the current user's experience in MUMD environment.
+ *
+ * @param displayId the displayId of the key event.
+ * @param keyCode the key code of the event.
+ *
+ * @return false if the key event is for a visible background user.
+ */
+ private boolean isKeyEventForCurrentUser(int displayId, int keyCode, @Nullable String purpose) {
+ if (!mVisibleBackgroundUsersEnabled) {
+ return true;
+ }
+ int assignedUser = mUserManagerInternal.getUserAssignedToDisplay(displayId);
+ if (assignedUser == mCurrentUserId) {
+ return true;
+ }
+ if (DEBUG_INPUT) {
+ Slog.w(TAG, "Cannot handle " + KeyEvent.keyCodeToString(keyCode)
+ + (purpose != null ? " to " + purpose : "")
+ + " for visible background user(u" + assignedUser + ")");
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 9b39fa1..a49a9fd 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -46,6 +46,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.FileDescriptor;
@@ -89,6 +90,8 @@
@GuardedBy("mSearchables")
private final SparseArray<Searchables> mSearchables = new SparseArray<>();
+ private final UserManagerInternal mUserManagerInternal;
+
/**
* Initializes the Search Manager service in the provided system context.
* Only one instance of this object should be created!
@@ -101,6 +104,7 @@
mMyPackageMonitor.register(context, null, UserHandle.ALL, true);
new GlobalSearchProviderObserver(context.getContentResolver());
mHandler = BackgroundThread.getHandler();
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
}
private Searchables getSearchables(int userId) {
@@ -336,6 +340,14 @@
@Override
public void launchAssist(int userHandle, Bundle args) {
+ // Currently, visible background users are not allowed to launch assist.(b/332222893)
+ // TODO(b/368715893): Consider indirect calls from system service when checking the
+ // calling user.
+ final int callingUserId = UserHandle.getCallingUserId();
+ if (mUserManagerInternal.isVisibleBackgroundFullUser(callingUserId)) {
+ throw new SecurityException("Visible background user(u" + callingUserId
+ + ") is not permitted to launch assist.");
+ }
StatusBarManagerInternal statusBarManager =
LocalServices.getService(StatusBarManagerInternal.class);
if (statusBarManager != null) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index b884079..102306f 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -31,6 +31,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.app.SynchronousUserSwitchObserver;
import android.app.UidObserver;
import android.content.BroadcastReceiver;
@@ -74,6 +75,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/** Controls all the system settings related to vibration. */
@@ -147,9 +149,6 @@
PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT));
- private static final IntentFilter INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER =
- new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
-
/** Listener for changes on vibration settings. */
interface OnVibratorSettingsChanged {
/** Callback triggered when any of the vibrator settings change. */
@@ -158,15 +157,18 @@
private final Object mLock = new Object();
private final Context mContext;
- private final String mSystemUiPackage;
@VisibleForTesting
final SettingsContentObserver mSettingObserver;
@VisibleForTesting
- final SettingsBroadcastReceiver mSettingChangeReceiver;
+ final RingerModeBroadcastReceiver mRingerModeBroadcastReceiver;
+ @VisibleForTesting
+ final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
@VisibleForTesting
final VibrationUidObserver mUidObserver;
@VisibleForTesting
final VibrationUserSwitchObserver mUserSwitchObserver;
+ @VisibleForTesting
+ final VibrationLowPowerModeListener mLowPowerModeListener;
@GuardedBy("mLock")
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -180,10 +182,13 @@
@GuardedBy("mLock")
@Nullable
private PowerManagerInternal mPowerManagerInternal;
+ @GuardedBy("mLock")
@Nullable
private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
@GuardedBy("mLock")
+ private String mSystemUiPackage;
+ @GuardedBy("mLock")
private boolean mVibrateInputDevices;
@GuardedBy("mLock")
private SparseIntArray mCurrentVibrationIntensities = new SparseIntArray();
@@ -205,11 +210,11 @@
mContext = context;
mVibrationConfig = config;
mSettingObserver = new SettingsContentObserver(handler);
- mSettingChangeReceiver = new SettingsBroadcastReceiver();
+ mRingerModeBroadcastReceiver = new RingerModeBroadcastReceiver();
+ mBatteryBroadcastReceiver = new BatteryBroadcastReceiver();
mUidObserver = new VibrationUidObserver();
mUserSwitchObserver = new VibrationUserSwitchObserver();
- mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class)
- .getSystemUiServiceComponent().getPackageName();
+ mLowPowerModeListener = new VibrationLowPowerModeListener();
VibrationEffect clickEffect = createEffectFromResource(
com.android.internal.R.array.config_virtualKeyVibePattern);
@@ -233,18 +238,34 @@
}
public void onSystemReady() {
- PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class);
- AudioManager am = mContext.getSystemService(AudioManager.class);
- int ringerMode = (am == null) ? mRingerMode : am.getRingerModeInternal();
+ onSystemReady(LocalServices.getService(PackageManagerInternal.class),
+ LocalServices.getService(PowerManagerInternal.class),
+ ActivityManager.getService(),
+ LocalServices.getService(VirtualDeviceManagerInternal.class),
+ mContext.getSystemService(AudioManager.class));
+ }
+
+ @VisibleForTesting
+ void onSystemReady(PackageManagerInternal packageManagerInternal,
+ PowerManagerInternal powerManagerInternal,
+ IActivityManager activityManagerInternal,
+ @Nullable VirtualDeviceManagerInternal virtualDeviceManagerInternal,
+ @Nullable AudioManager audioManager) {
+ int ringerMode = (audioManager == null)
+ ? AudioManager.RINGER_MODE_NORMAL
+ : audioManager.getRingerModeInternal();
+ String sysUiPackage = packageManagerInternal.getSystemUiServiceComponent().getPackageName();
synchronized (mLock) {
- mPowerManagerInternal = pm;
- mAudioManager = am;
+ mPowerManagerInternal = powerManagerInternal;
+ mVirtualDeviceManagerInternal = virtualDeviceManagerInternal;
+ mAudioManager = audioManager;
mRingerMode = ringerMode;
+ mSystemUiPackage = sysUiPackage;
}
try {
- ActivityManager.getService().registerUidObserver(mUidObserver,
+ activityManagerInternal.registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
ActivityManager.PROCESS_STATE_UNKNOWN, /* callingPackage= */ null);
} catch (RemoteException e) {
@@ -252,32 +273,16 @@
}
try {
- ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
+ activityManagerInternal.registerUserSwitchObserver(mUserSwitchObserver, TAG);
} catch (RemoteException e) {
// ignored; both services live in system_server
}
- pm.registerLowPowerModeObserver(
- new PowerManagerInternal.LowPowerModeListener() {
- @Override
- public int getServiceType() {
- return PowerManager.ServiceType.VIBRATION;
- }
+ powerManagerInternal.registerLowPowerModeObserver(mLowPowerModeListener);
- @Override
- public void onLowPowerModeChanged(PowerSaveState result) {
- boolean shouldNotifyListeners;
- synchronized (mLock) {
- shouldNotifyListeners = result.batterySaverEnabled != mBatterySaverMode;
- mBatterySaverMode = result.batterySaverEnabled;
- }
- if (shouldNotifyListeners) {
- notifyListeners();
- }
- }
- });
-
- registerSettingsChangeReceiver(INTERNAL_RINGER_MODE_CHANGED_INTENT_FILTER);
+ mContext.registerReceiver(mRingerModeBroadcastReceiver,
+ new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION),
+ Context.RECEIVER_EXPORTED_UNAUDITED);
// Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
@@ -301,12 +306,7 @@
if (mVibrationConfig.ignoreVibrationsOnWirelessCharger()) {
Intent batteryStatus = mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updateBatteryInfo(intent);
- }
- },
+ mBatteryBroadcastReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED),
Context.RECEIVER_NOT_EXPORTED);
// After registering the receiver for battery status, process the sticky broadcast that
@@ -476,8 +476,10 @@
public boolean shouldCancelVibrationOnScreenOff(@NonNull CallerInfo callerInfo,
long vibrationStartUptimeMillis) {
PowerManagerInternal pm;
+ String sysUiPackageName;
synchronized (mLock) {
pm = mPowerManagerInternal;
+ sysUiPackageName = mSystemUiPackage;
}
if (pm != null) {
// The SleepData from PowerManager may refer to a more recent sleep than the broadcast
@@ -501,7 +503,7 @@
}
// Only allow vibrations from System packages to continue vibrating when the screen goes off
return callerInfo.uid != Process.SYSTEM_UID && callerInfo.uid != 0
- && !mSystemUiPackage.equals(callerInfo.opPkg);
+ && !Objects.equals(sysUiPackageName, callerInfo.opPkg);
}
/**
@@ -782,11 +784,6 @@
UserHandle.USER_ALL);
}
- private void registerSettingsChangeReceiver(IntentFilter intentFilter) {
- mContext.registerReceiver(mSettingChangeReceiver, intentFilter,
- Context.RECEIVER_EXPORTED_UNAUDITED);
- }
-
@Nullable
private VibrationEffect createEffectFromResource(int resId) {
return createEffectFromResource(mContext.getResources(), resId);
@@ -833,12 +830,11 @@
}
private boolean isAppRunningOnAnyVirtualDevice(int uid) {
- if (mVirtualDeviceManagerInternal == null) {
- mVirtualDeviceManagerInternal =
- LocalServices.getService(VirtualDeviceManagerInternal.class);
+ VirtualDeviceManagerInternal vdm;
+ synchronized (mLock) {
+ vdm = mVirtualDeviceManagerInternal;
}
- return mVirtualDeviceManagerInternal != null
- && mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(uid);
+ return vdm != null && vdm.isAppRunningOnAnyVirtualDevice(uid);
}
/** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
@@ -857,7 +853,7 @@
/** Implementation of {@link BroadcastReceiver} to update on ringer mode change. */
@VisibleForTesting
- final class SettingsBroadcastReceiver extends BroadcastReceiver {
+ final class RingerModeBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -868,6 +864,18 @@
}
}
+ /** Implementation of {@link BroadcastReceiver} to update on battery mode change. */
+ @VisibleForTesting
+ final class BatteryBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+ updateBatteryInfo(intent);
+ }
+ }
+ }
+
/** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
@VisibleForTesting
final class VibrationUidObserver extends UidObserver {
@@ -913,4 +921,25 @@
update();
}
}
+
+ /** Implementation of {@link PowerManagerInternal.LowPowerModeListener} for low battery. */
+ @VisibleForTesting
+ final class VibrationLowPowerModeListener implements PowerManagerInternal.LowPowerModeListener {
+ @Override
+ public int getServiceType() {
+ return PowerManager.ServiceType.VIBRATION;
+ }
+
+ @Override
+ public void onLowPowerModeChanged(PowerSaveState result) {
+ boolean shouldNotifyListeners;
+ synchronized (mLock) {
+ shouldNotifyListeners = result.batterySaverEnabled != mBatterySaverMode;
+ mBatterySaverMode = result.batterySaverEnabled;
+ }
+ if (shouldNotifyListeners) {
+ notifyListeners();
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index de0ec30..96b9243 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5863,6 +5863,7 @@
return;
}
+ final State prevState = mState;
mState = state;
if (getTaskFragment() != null) {
@@ -5903,6 +5904,14 @@
mAtmService.updateBatteryStats(this, false);
mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
break;
+ case STOPPING:
+ // It is possible that an Activity is scheduled to be STOPPED directly from RESUMED
+ // state. Updating the PAUSED usage state in that case, since the Activity will be
+ // STOPPED while cycled through the PAUSED state.
+ if (prevState == RESUMED) {
+ mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
+ }
+ break;
case STOPPED:
mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
if (mDisplayContent != null) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 670a61d..05dcbb7 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
@@ -268,7 +269,16 @@
}
final DisplayPolicy.DecorInsets.Info decor =
displayContent.getDisplayPolicy().getDecorInsetsInfo(rotation, dw, dh);
- outAppBounds.intersectUnchecked(decor.mOverrideNonDecorFrame);
+ if (!outAppBounds.intersect(decor.mOverrideNonDecorFrame)) {
+ // TODO (b/364883053): When a split screen is requested from an app intent for a new
+ // task, the bounds is not the final bounds, and this is also not a bounds change
+ // event handled correctly with the offset. Revert back to legacy method for this
+ // case.
+ if (inOutConfig.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_MULTI_WINDOW) {
+ outAppBounds.inset(decor.mOverrideNonDecorInsets);
+ }
+ }
if (task != null && (task.mOffsetYForInsets != 0 || task.mOffsetXForInsets != 0)) {
outAppBounds.offset(-task.mOffsetXForInsets, -task.mOffsetYForInsets);
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 57b8792..d3cae4c 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -400,7 +400,7 @@
}
final Point position = getWindowFrameSurfacePosition();
if (!mPosition.equals(position)) {
- mPosition.set(position.x, position.y);
+ mPosition.set(position);
if (windowState != null && windowState.getWindowFrames().didFrameSizeChange()
&& windowState.mWinAnimator.getShown() && mWindowContainer.okToDisplay()) {
windowState.applyWithNextDraw(mSetControlPositionConsumer);
@@ -543,6 +543,7 @@
}
boolean initiallyVisible = mClientVisible;
final Point surfacePosition = getWindowFrameSurfacePosition();
+ mPosition.set(surfacePosition);
mAdapter = new ControlAdapter(surfacePosition);
if (mSource.getType() == WindowInsets.Type.ime()) {
if (android.view.inputmethod.Flags.refactorInsetsController()) {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index d042b38..dd5f613 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1385,7 +1385,16 @@
// Commit wallpaper visibility after activity, because usually the wallpaper target token is
// an activity, and wallpaper's visibility depends on activity's visibility.
for (int i = mParticipants.size() - 1; i >= 0; --i) {
- final WallpaperWindowToken wt = mParticipants.valueAt(i).asWallpaperToken();
+ final WindowContainer<?> wc = mParticipants.valueAt(i);
+ WallpaperWindowToken wt = wc.asWallpaperToken();
+ if (!Flags.ensureWallpaperInTransitions()) {
+ if (wt == null) {
+ final WindowState windowState = wc.asWindowState();
+ if (windowState != null) {
+ wt = windowState.mToken.asWallpaperToken();
+ }
+ }
+ }
if (wt == null) continue;
final WindowState target = wt.mDisplayContent.mWallpaperController.getWallpaperTarget();
final boolean isTargetInvisible = target == null || !target.mToken.isVisible();
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
index 87fe6cf..6d27ddd 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationConnectionManagerTest.java
@@ -62,6 +62,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import org.junit.Before;
@@ -92,12 +93,16 @@
private MagnificationConnectionManager.Callback mMockCallback;
private MockContentResolver mResolver;
private MagnificationConnectionManager mMagnificationConnectionManager;
+ @Mock
+ private UserManagerInternal mMockUserManagerInternal;
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
+ LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
mResolver = new MockContentResolver();
mMockConnection = new MockMagnificationConnection();
mMagnificationConnectionManager = new MagnificationConnectionManager(mContext, new Object(),
@@ -110,6 +115,8 @@
Settings.Secure.putFloatForUser(mResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.5f,
CURRENT_USER_ID);
+
+ when(mMockUserManagerInternal.isVisibleBackgroundFullUser(anyInt())).thenReturn(false);
}
private void stubSetConnection(boolean needDelay) {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index b9ce8ad..0c92abc 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1163,6 +1163,16 @@
verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
Bundle result = mBundleCaptor.getValue();
+ Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
+ assertNotNull(sessionBundle);
+ // Assert that session bundle is decrypted and hence data is visible.
+ assertEquals(AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1,
+ sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1));
+ // Assert finishSessionAsUser added calling uid and pid into the sessionBundle
+ assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID));
+ assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID));
+ assertEquals(sessionBundle.getString(
+ AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package");
// Verify response data
assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null));
@@ -2111,6 +2121,12 @@
result.getString(AccountManager.KEY_ACCOUNT_NAME));
assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+
+ Bundle optionBundle = result.getParcelable(
+ AccountManagerServiceTestFixtures.KEY_OPTIONS_BUNDLE);
+ // Assert addAccountAsUser added calling uid and pid into the option bundle
+ assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_UID));
+ assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_PID));
}
@SmallTest
@@ -3441,52 +3457,6 @@
+ (readTotalTime.doubleValue() / readerCount / loopSize));
}
- @SmallTest
- public void testSanitizeBundle_expectedFields() throws Exception {
- Bundle bundle = new Bundle();
- bundle.putString(AccountManager.KEY_ACCOUNT_NAME, "name");
- bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, "type");
- bundle.putString(AccountManager.KEY_AUTHTOKEN, "token");
- bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, "label");
- bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "error message");
- bundle.putString(AccountManager.KEY_PASSWORD, "password");
- bundle.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, "status");
-
- bundle.putLong(AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 123L);
- bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
- bundle.putInt(AccountManager.KEY_ERROR_CODE, 456);
-
- Bundle sanitizedBundle = AccountManagerService.sanitizeBundle(bundle);
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_NAME), "name");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_TYPE), "type");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_AUTHTOKEN), "token");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL), "label");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_ERROR_MESSAGE), "error message");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_PASSWORD), "password");
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN), "status");
-
- assertEquals(sanitizedBundle.getLong(
- AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0), 123L);
- assertEquals(sanitizedBundle.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false), true);
- assertEquals(sanitizedBundle.getInt(AccountManager.KEY_ERROR_CODE, 0), 456);
- }
-
- @SmallTest
- public void testSanitizeBundle_filtersUnexpectedFields() throws Exception {
- Bundle bundle = new Bundle();
- bundle.putString(AccountManager.KEY_ACCOUNT_NAME, "name");
- bundle.putString("unknown_key", "value");
- Bundle sessionBundle = new Bundle();
- bundle.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
-
- Bundle sanitizedBundle = AccountManagerService.sanitizeBundle(bundle);
-
- assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_NAME), "name");
- assertFalse(sanitizedBundle.containsKey("unknown_key"));
- // It is a valid response from Authenticator which will be accessed using original Bundle
- assertFalse(sanitizedBundle.containsKey(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
- }
-
private void waitForCyclicBarrier(CyclicBarrier cyclicBarrier) {
try {
cyclicBarrier.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
diff --git a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
index c247c08..3b0cb4a 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiModeManagerServiceTest.java
@@ -68,6 +68,7 @@
import android.Manifest;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Flags;
import android.app.IOnProjectionStateChangedListener;
@@ -247,6 +248,8 @@
mInjector = spy(new TestInjector());
mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true,
mTwilightManager, mInjector);
+ // Initialize the current user.
+ mUiManagerService.setCurrentUser(ActivityManager.getCurrentUser());
try {
mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
} catch (SecurityException e) {/* ignore for permission denial */}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
index 492f108..e4a6efd 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -44,7 +44,8 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -52,12 +53,14 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManagerInternal;
import android.media.AudioManager;
import android.os.Handler;
@@ -79,12 +82,10 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
-import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.vibrator.VibrationSession.CallerInfo;
import com.android.server.vibrator.VibrationSession.Status;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -101,8 +102,7 @@
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
- private static final int OLD_USER_ID = 123;
- private static final int NEW_USER_ID = 456;
+ private static final int USER_ID = 123;
private static final int UID = 1;
private static final int VIRTUAL_DEVICE_ID = 1;
private static final String SYSUI_PACKAGE_NAME = "sysui";
@@ -132,13 +132,12 @@
@Mock private VirtualDeviceManagerInternal mVirtualDeviceManagerInternalMock;
@Mock private PackageManagerInternal mPackageManagerInternalMock;
@Mock private AudioManager mAudioManagerMock;
+ @Mock private IActivityManager mActivityManagerMock;
@Mock private VibrationConfig mVibrationConfigMock;
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
private VibrationSettings mVibrationSettings;
- private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
- private BroadcastReceiver mRegisteredBatteryBroadcastReceiver;
@Before
public void setUp() throws Exception {
@@ -146,24 +145,20 @@
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
- when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
- when(mContextSpy.getSystemService(eq(Context.AUDIO_SERVICE))).thenReturn(mAudioManagerMock);
- doAnswer(invocation -> {
- mRegisteredPowerModeListener = invocation.getArgument(0);
- return null;
- }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
+ doReturn(contentResolver).when(mContextSpy).getContentResolver();
+
+ // Make sure broadcast receivers are not registered for this test, to avoid flakes.
+ doReturn(null).when(mContextSpy)
+ .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class), anyInt());
when(mPackageManagerInternalMock.getSystemUiServiceComponent())
.thenReturn(new ComponentName(SYSUI_PACKAGE_NAME, ""));
- removeServicesForTest();
- addServicesForTest();
-
setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
setIgnoreVibrationsOnWirelessCharger(false);
- createSystemReadyVibrationSettings();
mockGoToSleep(/* goToSleepTime= */ 0, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ createSystemReadyVibrationSettings();
}
private void createSystemReadyVibrationSettings() {
@@ -177,38 +172,18 @@
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- mVibrationSettings.onSystemReady();
- }
-
- private void removeServicesForTest() {
- LocalServices.removeServiceForTest(PowerManagerInternal.class);
- LocalServices.removeServiceForTest(PackageManagerInternal.class);
- LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
- }
-
- private void addServicesForTest() {
- LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
- LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
- LocalServices.addService(VirtualDeviceManagerInternal.class,
- mVirtualDeviceManagerInternalMock);
- }
-
- @After
- public void tearDown() throws Exception {
- removeServicesForTest();
+ mVibrationSettings.onSystemReady(mPackageManagerInternalMock, mPowerManagerInternalMock,
+ mActivityManagerMock, mVirtualDeviceManagerInternalMock, mAudioManagerMock);
}
@Test
public void create_withOnlyRequiredSystemServices() {
- // The only core services that we depend on are PowerManager and PackageManager
- removeServicesForTest();
- LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
- LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock);
- when(mContextSpy.getSystemService(eq(Context.AUDIO_SERVICE))).thenReturn(null);
-
VibrationSettings minimalVibrationSettings = new VibrationSettings(mContextSpy,
new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
- minimalVibrationSettings.onSystemReady();
+
+ // The only core services that we depend on are Power, Package and Activity managers
+ minimalVibrationSettings.onSystemReady(mPackageManagerInternalMock,
+ mPowerManagerInternalMock, mActivityManagerMock, null, null);
}
@Test
@@ -216,8 +191,8 @@
mVibrationSettings.addListener(mListenerMock);
// Testing the broadcast flow manually.
- mVibrationSettings.mUserSwitchObserver.onUserSwitching(NEW_USER_ID);
- mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);
+ mVibrationSettings.mUserSwitchObserver.onUserSwitching(USER_ID);
+ mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(USER_ID);
verify(mListenerMock, times(2)).onChange();
}
@@ -227,9 +202,9 @@
mVibrationSettings.addListener(mListenerMock);
// Testing the broadcast flow manually.
- mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+ mVibrationSettings.mRingerModeBroadcastReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
- mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+ mVibrationSettings.mRingerModeBroadcastReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
verify(mListenerMock, times(2)).onChange();
@@ -251,9 +226,9 @@
mVibrationSettings.addListener(mListenerMock);
// Testing the broadcast flow manually.
- mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
- mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change.
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // Noop.
verify(mListenerMock, times(2)).onChange();
}
@@ -268,10 +243,9 @@
mVibrationSettings.removeListener(mListenerMock);
// Trigger multiple observers manually.
- mVibrationSettings.mSettingObserver.onChange(false);
- mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);
- mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+ mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(USER_ID);
+ mVibrationSettings.mRingerModeBroadcastReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
verifyNoMoreInteractions(mListenerMock);
@@ -312,11 +286,12 @@
@Test
public void wirelessChargingVibrationsEnabled_doesNotRegisterBatteryReceiver_allowsAnyUsage() {
- setBatteryReceiverRegistrationResult(getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS));
setIgnoreVibrationsOnWirelessCharger(false);
createSystemReadyVibrationSettings();
- assertNull(mRegisteredBatteryBroadcastReceiver);
+ verify(mContextSpy, never()).registerReceiver(any(BroadcastReceiver.class),
+ argThat(filter -> filter.matchAction(Intent.ACTION_BATTERY_CHANGED)), anyInt());
+
for (int usage : ALL_USAGES) {
assertVibrationNotIgnoredForUsage(usage);
}
@@ -324,7 +299,6 @@
@Test
public void shouldIgnoreVibration_noBatteryIntentWhenSystemReady_allowsAnyUsage() {
- setBatteryReceiverRegistrationResult(null);
setIgnoreVibrationsOnWirelessCharger(true);
createSystemReadyVibrationSettings();
@@ -336,7 +310,9 @@
@Test
public void shouldIgnoreVibration_onNonWirelessChargerWhenSystemReady_allowsAnyUsage() {
Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
- setBatteryReceiverRegistrationResult(nonWirelessChargingIntent);
+ doReturn(nonWirelessChargingIntent).when(mContextSpy).registerReceiver(
+ any(BroadcastReceiver.class),
+ argThat(filter -> filter.matchAction(Intent.ACTION_BATTERY_CHANGED)), anyInt());
setIgnoreVibrationsOnWirelessCharger(true);
createSystemReadyVibrationSettings();
@@ -348,7 +324,9 @@
@Test
public void shouldIgnoreVibration_onWirelessChargerWhenSystemReady_doesNotAllowFromAnyUsage() {
Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
- setBatteryReceiverRegistrationResult(wirelessChargingIntent);
+ doReturn(wirelessChargingIntent).when(mContextSpy).registerReceiver(
+ any(BroadcastReceiver.class),
+ argThat(filter -> filter.matchAction(Intent.ACTION_BATTERY_CHANGED)), anyInt());
setIgnoreVibrationsOnWirelessCharger(true);
createSystemReadyVibrationSettings();
@@ -359,13 +337,12 @@
@Test
public void shouldIgnoreVibration_receivesWirelessChargingIntent_doesNotAllowFromAnyUsage() {
- Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
- setBatteryReceiverRegistrationResult(nonWirelessChargingIntent);
setIgnoreVibrationsOnWirelessCharger(true);
createSystemReadyVibrationSettings();
Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
- mRegisteredBatteryBroadcastReceiver.onReceive(mContextSpy, wirelessChargingIntent);
+ mVibrationSettings.mBatteryBroadcastReceiver.onReceive(
+ mContextSpy, wirelessChargingIntent);
for (int usage : ALL_USAGES) {
assertVibrationIgnoredForUsage(usage, Status.IGNORED_ON_WIRELESS_CHARGER);
@@ -374,17 +351,21 @@
@Test
public void shouldIgnoreVibration_receivesNonWirelessChargingIntent_allowsAnyUsage() {
- Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
- setBatteryReceiverRegistrationResult(wirelessChargingIntent);
setIgnoreVibrationsOnWirelessCharger(true);
createSystemReadyVibrationSettings();
+
+ Intent wirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_WIRELESS);
+ mVibrationSettings.mBatteryBroadcastReceiver.onReceive(
+ mContextSpy, wirelessChargingIntent);
+
// Check that initially, all usages are ignored due to the wireless charging.
for (int usage : ALL_USAGES) {
assertVibrationIgnoredForUsage(usage, Status.IGNORED_ON_WIRELESS_CHARGER);
}
Intent nonWirelessChargingIntent = getBatteryChangedIntent(BATTERY_PLUGGED_USB);
- mRegisteredBatteryBroadcastReceiver.onReceive(mContextSpy, nonWirelessChargingIntent);
+ mVibrationSettings.mBatteryBroadcastReceiver.onReceive(
+ mContextSpy, nonWirelessChargingIntent);
for (int usage : ALL_USAGES) {
assertVibrationNotIgnoredForUsage(usage);
@@ -401,7 +382,7 @@
USAGE_HARDWARE_FEEDBACK
));
- mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
for (int usage : ALL_USAGES) {
if (expectedAllowedVibrations.contains(usage)) {
@@ -414,7 +395,7 @@
@Test
public void shouldIgnoreVibration_notInBatterySaverMode_allowsAnyUsage() {
- mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
+ mVibrationSettings.mLowPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
for (int usage : ALL_USAGES) {
assertVibrationNotIgnoredForUsage(usage);
@@ -606,7 +587,7 @@
// Testing the broadcast flow manually.
when(mAudioManagerMock.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
- mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+ mVibrationSettings.mRingerModeBroadcastReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
assertVibrationIgnoredForUsage(USAGE_RINGTONE, Status.IGNORED_FOR_RINGER_MODE);
@@ -862,16 +843,15 @@
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
// Test early update of settings based on new user id.
- putUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
- NEW_USER_ID);
- mVibrationSettings.mUserSwitchObserver.onUserSwitching(NEW_USER_ID);
+ putUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW, USER_ID);
+ mVibrationSettings.mUserSwitchObserver.onUserSwitching(USER_ID);
assertEquals(VIBRATION_INTENSITY_LOW,
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
// Test later update of settings for UserHandle.USER_CURRENT.
putUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
UserHandle.USER_CURRENT);
- mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(NEW_USER_ID);
+ mVibrationSettings.mUserSwitchObserver.onUserSwitchComplete(USER_ID);
assertEquals(VIBRATION_INTENSITY_LOW,
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
}
@@ -1019,7 +999,7 @@
private void setRingerMode(int ringerMode) {
when(mAudioManagerMock.getRingerModeInternal()).thenReturn(ringerMode);
// Mock AudioManager broadcast of internal ringer mode change.
- mVibrationSettings.mSettingChangeReceiver.onReceive(mContextSpy,
+ mVibrationSettings.mRingerModeBroadcastReceiver.onReceive(mContextSpy,
new Intent(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
}
@@ -1034,14 +1014,6 @@
return new CallerInfo(attrs, uid, VIRTUAL_DEVICE_ID, opPkg, null);
}
- private void setBatteryReceiverRegistrationResult(Intent result) {
- doAnswer(invocation -> {
- mRegisteredBatteryBroadcastReceiver = invocation.getArgument(0);
- return result;
- }).when(mContextSpy).registerReceiver(any(BroadcastReceiver.class),
- argThat(filter -> filter.matchAction(Intent.ACTION_BATTERY_CHANGED)), anyInt());
- }
-
private Intent getBatteryChangedIntent(int extraPluggedValue) {
Intent batteryIntent = new Intent(Intent.ACTION_BATTERY_CHANGED);
batteryIntent.putExtra(EXTRA_PLUGGED, extraPluggedValue);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index e8d089c..f48ba65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -30,6 +30,7 @@
import static org.junit.Assert.assertTrue;
import android.graphics.Insets;
+import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSource;
@@ -260,6 +261,27 @@
}
@Test
+ public void testUpdateInsetsControlPosition() {
+ final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
+
+ final WindowState ime1 = createWindow(null, TYPE_INPUT_METHOD, "ime1");
+ ime1.getFrame().set(new Rect(0, 0, 0, 0));
+ mImeProvider.setWindowContainer(ime1, null, null);
+ mImeProvider.updateControlForTarget(target, false /* force */, null /* statsToken */);
+ ime1.getFrame().set(new Rect(0, 400, 500, 500));
+ mImeProvider.updateInsetsControlPosition(ime1);
+ assertEquals(new Point(0, 400), mImeProvider.getControl(target).getSurfacePosition());
+
+ final WindowState ime2 = createWindow(null, TYPE_INPUT_METHOD, "ime2");
+ ime2.getFrame().set(new Rect(0, 0, 0, 0));
+ mImeProvider.setWindowContainer(ime2, null, null);
+ mImeProvider.updateControlForTarget(target, false /* force */, null /* statsToken */);
+ ime2.getFrame().set(new Rect(0, 400, 500, 500));
+ mImeProvider.updateInsetsControlPosition(ime2);
+ assertEquals(new Point(0, 400), mImeProvider.getControl(target).getSurfacePosition());
+ }
+
+ @Test
public void testSetRequestedVisibleTypes() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
diff --git a/tests/NetworkSecurityConfigTest/res/xml/ct_domains.xml b/tests/NetworkSecurityConfigTest/res/xml/ct_domains.xml
new file mode 100644
index 0000000..67d4397a
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/ct_domains.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <base-config>
+ <certificateTransparency enabled="true" />
+ </base-config>
+ <domain-config>
+ <domain>android.com</domain>
+ <trust-anchors>
+ <certificates src="system" />
+ </trust-anchors>
+ </domain-config>
+ <domain-config>
+ <domain>subdomain_user.android.com</domain>
+ <trust-anchors>
+ <certificates src="user" />
+ </trust-anchors>
+ </domain-config>
+ <domain-config>
+ <certificateTransparency enabled="true" />
+ <domain>subdomain_user_ct.android.com</domain>
+ <trust-anchors>
+ <certificates src="user" />
+ </trust-anchors>
+ </domain-config>
+ <domain-config>
+ <domain>subdomain_inline.android.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/ca_certs_pem" />
+ </trust-anchors>
+ </domain-config>
+ <domain-config>
+ <certificateTransparency enabled="true" />
+ <domain>subdomain_inline_ct.android.com</domain>
+ <trust-anchors>
+ <certificates src="@raw/ca_certs_pem" />
+ </trust-anchors>
+ </domain-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/ct_users.xml b/tests/NetworkSecurityConfigTest/res/xml/ct_users.xml
new file mode 100644
index 0000000..c35fd71
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/ct_users.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <base-config>
+ <trust-anchors>
+ <certificates src="user" />
+ </trust-anchors>
+ </base-config>
+ <domain-config>
+ <domain>android.com</domain>
+ </domain-config>
+ <domain-config>
+ <certificateTransparency enabled="true" />
+ <domain>subdomain.android.com</domain>
+ </domain-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index 0494f17..c6fe068 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -111,7 +111,8 @@
private NetworkSecurityConfig getSystemStoreConfig() {
return new NetworkSecurityConfig.Builder()
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), false, false))
.build();
}
@@ -141,7 +142,8 @@
NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
.setPinSet(new PinSet(pins, Long.MAX_VALUE))
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), false, false))
.build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
@@ -159,7 +161,8 @@
NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
.setPinSet(new PinSet(pins, Long.MAX_VALUE))
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), false, false))
.build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
@@ -178,7 +181,8 @@
NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
.setPinSet(new PinSet(pins, Long.MAX_VALUE))
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), true))
+ new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), true, false))
.build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
@@ -245,7 +249,8 @@
NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
.setPinSet(new PinSet(pins, Long.MAX_VALUE))
.addCertificatesEntryRef(
- new CertificatesEntryRef(SystemCertificateSource.getInstance(), false))
+ new CertificatesEntryRef(
+ SystemCertificateSource.getInstance(), false, false))
.build();
ArraySet<Pair<Domain, NetworkSecurityConfig>> domainMap
= new ArraySet<Pair<Domain, NetworkSecurityConfig>>();
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 81e05c1..542465d 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -502,4 +502,47 @@
TestUtils.assertConnectionSucceeds(context, "android.com", 443);
TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
}
+
+ public void testCertificateTransparencyDomainConfig() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.ct_domains,
+ TestUtils.makeApplicationInfo());
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ assertTrue(appConfig.hasPerDomainConfigs());
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+ assertNotNull(config);
+ // Check defaults.
+ assertTrue(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("android.com");
+ assertTrue(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("subdomain_user.android.com");
+ assertFalse(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("subdomain_user_ct.android.com");
+ assertTrue(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("subdomain_inline.android.com");
+ assertFalse(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("subdomain_inline_ct.android.com");
+ assertTrue(config.isCertificateTransparencyVerificationRequired());
+ }
+
+ public void testCertificateTransparencyUserConfig() throws Exception {
+ XmlConfigSource source = new XmlConfigSource(getContext(), R.xml.ct_users,
+ TestUtils.makeApplicationInfo());
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ assertTrue(appConfig.hasPerDomainConfigs());
+ NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+ assertNotNull(config);
+ // Check defaults.
+ assertFalse(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("android.com");
+ assertFalse(config.isCertificateTransparencyVerificationRequired());
+
+ config = appConfig.getConfigForHostname("subdomain.android.com");
+ assertTrue(config.isCertificateTransparencyVerificationRequired());
+ }
}