summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java4
-rw-r--r--apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl2
-rw-r--r--apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java11
-rw-r--r--apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java359
-rw-r--r--core/api/current.txt9
-rw-r--r--core/api/system-current.txt58
-rw-r--r--core/api/test-current.txt7
-rw-r--r--core/java/android/app/AppOpsManager.java36
-rw-r--r--core/java/android/content/Context.java20
-rw-r--r--core/java/android/content/Intent.java23
-rw-r--r--core/java/android/content/pm/IDataLoaderStatusListener.aidl18
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java7
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java44
-rw-r--r--core/java/android/net/vcn/VcnManager.java65
-rw-r--r--core/java/android/os/BatteryStats.java18
-rw-r--r--core/java/android/os/Vibrator.java22
-rw-r--r--core/java/android/os/VibratorInfo.java39
-rw-r--r--core/java/android/permission/PermissionUsageHelper.java9
-rw-r--r--core/java/android/provider/Telephony.java7
-rw-r--r--core/java/android/telephony/PhoneStateListener.java3
-rw-r--r--core/java/android/telephony/TelephonyCallback.java40
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java16
-rw-r--r--core/java/android/util/Slog.java100
-rw-r--r--core/java/android/view/KeyCharacterMap.java29
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java51
-rw-r--r--core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java10
-rw-r--r--core/java/com/android/internal/os/CpuPowerCalculator.java98
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl2
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl2
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl3
-rw-r--r--core/jni/AndroidRuntime.cpp22
-rw-r--r--core/jni/android_util_Binder.cpp4
-rw-r--r--core/jni/android_view_KeyCharacterMap.cpp55
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/values/attrs.xml10
-rw-r--r--core/res/res/values/strings.xml5
-rw-r--r--core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java83
-rw-r--r--core/tests/coretests/src/android/os/VibratorInfoTest.java181
-rw-r--r--core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java86
-rw-r--r--data/etc/platform.xml1
-rw-r--r--keystore/java/android/security/AndroidKeyStoreMaintenance.java18
-rw-r--r--keystore/java/android/security/KeyStore.java14
-rw-r--r--libs/WindowManager/Shell/Android.bp10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java64
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl33
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java67
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl63
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl (renamed from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl)11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java153
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl77
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl (renamed from packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl)12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java226
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl (renamed from packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl)4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java151
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java (renamed from libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java)10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java85
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java22
-rw-r--r--libs/androidfw/AssetManager2.cpp3
-rw-r--r--media/jni/soundpool/Sound.cpp12
-rw-r--r--media/jni/soundpool/Stream.cpp4
-rw-r--r--media/jni/soundpool/StreamManager.cpp2
-rw-r--r--media/jni/soundpool/android_media_SoundPool.cpp3
-rw-r--r--packages/SystemUI/shared/Android.bp1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl121
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java354
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java123
-rw-r--r--services/core/java/com/android/server/BatteryService.java2
-rw-r--r--services/core/java/com/android/server/OWNERS1
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java45
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java4
-rw-r--r--services/core/java/com/android/server/app/GameManagerSettings.java5
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java36
-rw-r--r--services/core/java/com/android/server/appop/DiscreteRegistry.java347
-rw-r--r--services/core/java/com/android/server/appop/HistoricalRegistry.java4
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java8
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java23
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java47
-rw-r--r--services/core/java/com/android/server/pm/DataLoaderManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java10
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorController.java121
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java1
-rw-r--r--services/core/jni/com_android_server_vibrator_VibratorController.cpp69
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java47
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java24
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java31
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyConstants.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java34
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java11
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java12
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java7
-rw-r--r--services/incremental/IncrementalService.cpp90
-rw-r--r--services/incremental/IncrementalService.h7
-rw-r--r--services/incremental/ServiceWrappers.cpp12
-rw-r--r--services/incremental/ServiceWrappers.h8
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp162
-rw-r--r--services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java117
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java11
-rw-r--r--telecomm/java/android/telecom/CallDiagnosticService.java112
-rw-r--r--telecomm/java/android/telecom/DiagnosticCall.java162
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java67
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java61
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java12
-rw-r--r--telephony/java/android/telephony/data/DataService.java34
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java26
-rw-r--r--telephony/java/android/telephony/ims/RcsContactPresenceTuple.java25
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java90
-rw-r--r--telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl1
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java25
-rw-r--r--telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java35
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt19
-rw-r--r--tests/Input/Android.bp15
-rw-r--r--tests/Input/src/com/android/test/input/InputDeviceTest.java98
-rw-r--r--tests/vcn/java/com/android/server/VcnManagementServiceTest.java10
150 files changed, 3519 insertions, 2418 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
index 752c36e53bf9..6cdf5853339a 100644
--- a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
+++ b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
@@ -65,7 +65,7 @@ public class DeviceIdleManager {
* @return package names the system has white-listed to opt out of power save restrictions,
* except for device idle mode.
*
- * @hide Should be migrated to PowerWhitelistManager
+ * @hide Should be migrated to PowerExemptionManager
*/
@TestApi
public @NonNull String[] getSystemPowerWhitelistExceptIdle() {
@@ -80,7 +80,7 @@ public class DeviceIdleManager {
* @return package names the system has white-listed to opt out of power save restrictions for
* all modes.
*
- * @hide Should be migrated to PowerWhitelistManager
+ * @hide Should be migrated to PowerExemptionManager
*/
@TestApi
public @NonNull String[] getSystemPowerWhitelist() {
diff --git a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
index 43d4873a3540..9d18dfe98a34 100644
--- a/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
+++ b/apex/jobscheduler/framework/java/android/os/IDeviceIdleController.aidl
@@ -42,7 +42,7 @@ interface IDeviceIdleController {
boolean isPowerSaveWhitelistExceptIdleApp(String name);
boolean isPowerSaveWhitelistApp(String name);
@UnsupportedAppUsage(maxTargetSdk = 30,
- publicAlternatives = "Use SystemApi {@code PowerWhitelistManager#whitelistAppTemporarily(String, int, String)}.")
+ publicAlternatives = "Use SystemApi {@code PowerExemptionManager#addToTemporaryAllowList(String, int, int, String)}.")
void addPowerSaveTempWhitelistApp(String name, long duration, int userId, int reasonCode, String reason);
long addPowerSaveTempWhitelistAppForMms(String name, int userId, int reasonCode, String reason);
long addPowerSaveTempWhitelistAppForSms(String name, int userId, int reasonCode, String reason);
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index 8445335b568e..d9a49aa52365 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -170,7 +170,7 @@ public class PowerExemptionManager {
/** @hide */
public static final int REASON_EXEMPTED_PACKAGE = 64;
/** @hide */
- public static final int REASON_ALLOWLISTED_PACKAGE = 65;
+ public static final int REASON_ALLOWLISTED_PACKAGE = 65;
/** @hide */
public static final int REASON_APPOP = 66;
@@ -193,6 +193,10 @@ public class PowerExemptionManager {
* Set temp-allow-list for activity recognition.
*/
public static final int REASON_ACTIVITY_RECOGNITION = 103;
+ /**
+ * Set temp-allow-list for transferring accounts between users.
+ */
+ public static final int REASON_ACCOUNT_TRANSFER = 104;
/* Reason code range 200-299 are reserved for broadcast actions */
/**
@@ -216,7 +220,7 @@ public class PowerExemptionManager {
* Device idle system allow list, including EXCEPT-IDLE
* @hide
*/
- public static final int REASON_SYSTEM_ALLOW_LISTED = 300;
+ public static final int REASON_SYSTEM_ALLOW_LISTED = 300;
/** @hide */
public static final int REASON_ALARM_MANAGER_ALARM_CLOCK = 301;
/**
@@ -329,6 +333,7 @@ public class PowerExemptionManager {
REASON_PUSH_MESSAGING,
REASON_PUSH_MESSAGING_OVER_QUOTA,
REASON_ACTIVITY_RECOGNITION,
+ REASON_ACCOUNT_TRANSFER,
REASON_BOOT_COMPLETED,
REASON_PRE_BOOT_COMPLETED,
REASON_LOCKED_BOOT_COMPLETED,
@@ -579,6 +584,8 @@ public class PowerExemptionManager {
return "PUSH_MESSAGING_OVER_QUOTA";
case REASON_ACTIVITY_RECOGNITION:
return "ACTIVITY_RECOGNITION";
+ case REASON_ACCOUNT_TRANSFER:
+ return "REASON_ACCOUNT_TRANSFER";
case REASON_BOOT_COMPLETED:
return "BOOT_COMPLETED";
case REASON_PRE_BOOT_COMPLETED:
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
index b1b733a599c6..eba39c7573be 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java
@@ -16,13 +16,6 @@
package android.os;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
-import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
-import static android.app.ActivityManager.PROCESS_STATE_TOP;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,7 +26,6 @@ import android.content.Context;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Collections;
import java.util.List;
/**
@@ -43,9 +35,11 @@ import java.util.List;
* placed on the temporary whitelist are removed from that whitelist after a predetermined amount of
* time.
*
+ * @deprecated Use {@link PowerExemptionManager} instead
* @hide
*/
@SystemApi
+@Deprecated
@SystemService(Context.POWER_WHITELIST_MANAGER)
public class PowerWhitelistManager {
private final Context mContext;
@@ -53,21 +47,23 @@ public class PowerWhitelistManager {
// TODO: migrate to PowerWhitelistController
private final IDeviceIdleController mService;
+ private final PowerExemptionManager mPowerExemptionManager;
+
/**
* Indicates that an unforeseen event has occurred and the app should be whitelisted to handle
* it.
*/
- public static final int EVENT_UNSPECIFIED = 0;
+ public static final int EVENT_UNSPECIFIED = PowerExemptionManager.EVENT_UNSPECIFIED;
/**
* Indicates that an SMS event has occurred and the app should be whitelisted to handle it.
*/
- public static final int EVENT_SMS = 1;
+ public static final int EVENT_SMS = PowerExemptionManager.EVENT_SMS;
/**
* Indicates that an MMS event has occurred and the app should be whitelisted to handle it.
*/
- public static final int EVENT_MMS = 2;
+ public static final int EVENT_MMS = PowerExemptionManager.EVENT_MMS;
/**
* @hide
@@ -84,12 +80,14 @@ public class PowerWhitelistManager {
/**
* Allow the temp allowlist behavior, plus allow foreground service start from background.
*/
- public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0;
+ public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED =
+ PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
/**
* Only allow the temp allowlist behavior, not allow foreground service start from
* background.
*/
- public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1;
+ public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
+ PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
/**
* The list of temp allowlist types.
@@ -107,73 +105,83 @@ public class PowerWhitelistManager {
* BG-FGS-launch is denied.
* @hide
*/
- public static final int REASON_DENIED = -1;
+ public static final int REASON_DENIED = PowerExemptionManager.REASON_DENIED;
/* Reason code range 0-9 are reserved for default reasons */
/**
* The default reason code if reason is unknown.
*/
- public static final int REASON_UNKNOWN = 0;
+ public static final int REASON_UNKNOWN = PowerExemptionManager.REASON_UNKNOWN;
/**
* Use REASON_OTHER if there is no better choice.
*/
- public static final int REASON_OTHER = 1;
+ public static final int REASON_OTHER = PowerExemptionManager.REASON_OTHER;
/* Reason code range 10-49 are reserved for BG-FGS-launch allowed proc states */
/** @hide */
- public static final int REASON_PROC_STATE_PERSISTENT = 10;
+ public static final int REASON_PROC_STATE_PERSISTENT =
+ PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
/** @hide */
- public static final int REASON_PROC_STATE_PERSISTENT_UI = 11;
+ public static final int REASON_PROC_STATE_PERSISTENT_UI =
+ PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
/** @hide */
- public static final int REASON_PROC_STATE_TOP = 12;
+ public static final int REASON_PROC_STATE_TOP = PowerExemptionManager.REASON_PROC_STATE_TOP;
/** @hide */
- public static final int REASON_PROC_STATE_BTOP = 13;
+ public static final int REASON_PROC_STATE_BTOP = PowerExemptionManager.REASON_PROC_STATE_BTOP;
/** @hide */
- public static final int REASON_PROC_STATE_FGS = 14;
+ public static final int REASON_PROC_STATE_FGS = PowerExemptionManager.REASON_PROC_STATE_FGS;
/** @hide */
- public static final int REASON_PROC_STATE_BFGS = 15;
+ public static final int REASON_PROC_STATE_BFGS = PowerExemptionManager.REASON_PROC_STATE_BFGS;
/* Reason code range 50-99 are reserved for BG-FGS-launch allowed reasons */
/** @hide */
- public static final int REASON_UID_VISIBLE = 50;
+ public static final int REASON_UID_VISIBLE = PowerExemptionManager.REASON_UID_VISIBLE;
/** @hide */
- public static final int REASON_SYSTEM_UID = 51;
+ public static final int REASON_SYSTEM_UID = PowerExemptionManager.REASON_SYSTEM_UID;
/** @hide */
- public static final int REASON_ACTIVITY_STARTER = 52;
+ public static final int REASON_ACTIVITY_STARTER = PowerExemptionManager.REASON_ACTIVITY_STARTER;
/** @hide */
- public static final int REASON_START_ACTIVITY_FLAG = 53;
+ public static final int REASON_START_ACTIVITY_FLAG =
+ PowerExemptionManager.REASON_START_ACTIVITY_FLAG;
/** @hide */
- public static final int REASON_FGS_BINDING = 54;
+ public static final int REASON_FGS_BINDING = PowerExemptionManager.REASON_FGS_BINDING;
/** @hide */
- public static final int REASON_DEVICE_OWNER = 55;
+ public static final int REASON_DEVICE_OWNER = PowerExemptionManager.REASON_DEVICE_OWNER;
/** @hide */
- public static final int REASON_PROFILE_OWNER = 56;
+ public static final int REASON_PROFILE_OWNER = PowerExemptionManager.REASON_PROFILE_OWNER;
/** @hide */
- public static final int REASON_COMPANION_DEVICE_MANAGER = 57;
+ public static final int REASON_COMPANION_DEVICE_MANAGER =
+ PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
/**
* START_ACTIVITIES_FROM_BACKGROUND permission.
* @hide
*/
- public static final int REASON_BACKGROUND_ACTIVITY_PERMISSION = 58;
+ public static final int REASON_BACKGROUND_ACTIVITY_PERMISSION =
+ PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
/**
* START_FOREGROUND_SERVICES_FROM_BACKGROUND permission.
* @hide
*/
- public static final int REASON_BACKGROUND_FGS_PERMISSION = 59;
+ public static final int REASON_BACKGROUND_FGS_PERMISSION =
+ PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION;
/** @hide */
- public static final int REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION = 60;
+ public static final int REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION =
+ PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
/** @hide */
- public static final int REASON_INSTR_BACKGROUND_FGS_PERMISSION = 61;
+ public static final int REASON_INSTR_BACKGROUND_FGS_PERMISSION =
+ PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
/** @hide */
- public static final int REASON_SYSTEM_ALERT_WINDOW_PERMISSION = 62;
+ public static final int REASON_SYSTEM_ALERT_WINDOW_PERMISSION =
+ PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
/** @hide */
- public static final int REASON_DEVICE_DEMO_MODE = 63;
+ public static final int REASON_DEVICE_DEMO_MODE = PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
/** @hide */
- public static final int REASON_EXEMPTED_PACKAGE = 64;
+ public static final int REASON_EXEMPTED_PACKAGE = PowerExemptionManager.REASON_EXEMPTED_PACKAGE;
/** @hide */
- public static final int REASON_ALLOWLISTED_PACKAGE = 65;
+ public static final int REASON_ALLOWLISTED_PACKAGE =
+ PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
/** @hide */
- public static final int REASON_APPOP = 66;
+ public static final int REASON_APPOP = PowerExemptionManager.REASON_APPOP;
/* BG-FGS-launch is allowed by temp-allowlist or system-allowlist.
Reason code for temp and system allowlist starts here.
@@ -181,117 +189,128 @@ public class PowerWhitelistManager {
/**
* Set temp-allowlist for location geofence purpose.
*/
- public static final int REASON_GEOFENCING = 100;
+ public static final int REASON_GEOFENCING = PowerExemptionManager.REASON_GEOFENCING;
/**
* Set temp-allowlist for server push messaging.
*/
- public static final int REASON_PUSH_MESSAGING = 101;
+ public static final int REASON_PUSH_MESSAGING = PowerExemptionManager.REASON_PUSH_MESSAGING;
/**
* Set temp-allowlist for server push messaging over the quota.
*/
- public static final int REASON_PUSH_MESSAGING_OVER_QUOTA = 102;
+ public static final int REASON_PUSH_MESSAGING_OVER_QUOTA =
+ PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA;
/**
* Set temp-allowlist for activity recognition.
*/
- public static final int REASON_ACTIVITY_RECOGNITION = 103;
+ public static final int REASON_ACTIVITY_RECOGNITION =
+ PowerExemptionManager.REASON_ACTIVITY_RECOGNITION;
/* Reason code range 200-299 are reserved for broadcast actions */
/**
* Broadcast ACTION_BOOT_COMPLETED.
* @hide
*/
- public static final int REASON_BOOT_COMPLETED = 200;
+ public static final int REASON_BOOT_COMPLETED = PowerExemptionManager.REASON_BOOT_COMPLETED;
/**
* Broadcast ACTION_PRE_BOOT_COMPLETED.
* @hide
*/
- public static final int REASON_PRE_BOOT_COMPLETED = 201;
+ public static final int REASON_PRE_BOOT_COMPLETED =
+ PowerExemptionManager.REASON_PRE_BOOT_COMPLETED;
/**
* Broadcast ACTION_LOCKED_BOOT_COMPLETED.
* @hide
*/
- public static final int REASON_LOCKED_BOOT_COMPLETED = 202;
+ public static final int REASON_LOCKED_BOOT_COMPLETED =
+ PowerExemptionManager.REASON_LOCKED_BOOT_COMPLETED;
/* Reason code range 300-399 are reserved for other internal reasons */
/**
* Device idle system allowlist, including EXCEPT-IDLE
* @hide
*/
- public static final int REASON_SYSTEM_ALLOW_LISTED = 300;
+ public static final int REASON_SYSTEM_ALLOW_LISTED =
+ PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
/** @hide */
- public static final int REASON_ALARM_MANAGER_ALARM_CLOCK = 301;
+ public static final int REASON_ALARM_MANAGER_ALARM_CLOCK =
+ PowerExemptionManager.REASON_ALARM_MANAGER_ALARM_CLOCK;
/**
* AlarmManagerService.
* @hide
*/
- public static final int REASON_ALARM_MANAGER_WHILE_IDLE = 302;
+ public static final int REASON_ALARM_MANAGER_WHILE_IDLE =
+ PowerExemptionManager.REASON_ALARM_MANAGER_WHILE_IDLE;
/**
* ActiveServices.
* @hide
*/
- public static final int REASON_SERVICE_LAUNCH = 303;
+ public static final int REASON_SERVICE_LAUNCH = PowerExemptionManager.REASON_SERVICE_LAUNCH;
/**
* KeyChainSystemService.
* @hide
*/
- public static final int REASON_KEY_CHAIN = 304;
+ public static final int REASON_KEY_CHAIN = PowerExemptionManager.REASON_KEY_CHAIN;
/**
* PackageManagerService.
* @hide
*/
- public static final int REASON_PACKAGE_VERIFIER = 305;
+ public static final int REASON_PACKAGE_VERIFIER = PowerExemptionManager.REASON_PACKAGE_VERIFIER;
/**
* SyncManager.
* @hide
*/
- public static final int REASON_SYNC_MANAGER = 306;
+ public static final int REASON_SYNC_MANAGER = PowerExemptionManager.REASON_SYNC_MANAGER;
/**
* DomainVerificationProxyV1.
* @hide
*/
- public static final int REASON_DOMAIN_VERIFICATION_V1 = 307;
+ public static final int REASON_DOMAIN_VERIFICATION_V1 =
+ PowerExemptionManager.REASON_DOMAIN_VERIFICATION_V1;
/**
* DomainVerificationProxyV2.
* @hide
*/
- public static final int REASON_DOMAIN_VERIFICATION_V2 = 308;
+ public static final int REASON_DOMAIN_VERIFICATION_V2 =
+ PowerExemptionManager.REASON_DOMAIN_VERIFICATION_V2;
/** @hide */
public static final int REASON_VPN = 309;
/**
* NotificationManagerService.
* @hide
*/
- public static final int REASON_NOTIFICATION_SERVICE = 310;
+ public static final int REASON_NOTIFICATION_SERVICE =
+ PowerExemptionManager.REASON_NOTIFICATION_SERVICE;
/**
* Broadcast ACTION_MY_PACKAGE_REPLACED.
* @hide
*/
- public static final int REASON_PACKAGE_REPLACED = 311;
+ public static final int REASON_PACKAGE_REPLACED = PowerExemptionManager.REASON_PACKAGE_REPLACED;
/**
* LocationProviderManager.
* @hide
*/
- public static final int REASON_LOCATION_PROVIDER = 312;
+ public static final int REASON_LOCATION_PROVIDER =
+ PowerExemptionManager.REASON_LOCATION_PROVIDER;
/**
* MediaButtonReceiver.
* @hide
*/
- public static final int REASON_MEDIA_BUTTON = 313;
+ public static final int REASON_MEDIA_BUTTON = PowerExemptionManager.REASON_MEDIA_BUTTON;
/**
* InboundSmsHandler.
* @hide
*/
- public static final int REASON_EVENT_SMS = 314;
+ public static final int REASON_EVENT_SMS = PowerExemptionManager.REASON_EVENT_SMS;
/**
* InboundSmsHandler.
* @hide
*/
- public static final int REASON_EVENT_MMS = 315;
+ public static final int REASON_EVENT_MMS = PowerExemptionManager.REASON_EVENT_MMS;
/**
* Shell app.
* @hide
*/
- public static final int REASON_SHELL = 316;
+ public static final int REASON_SHELL = PowerExemptionManager.REASON_SHELL;
/**
* The list of BG-FGS-Launch and temp-allowlist reason code.
@@ -360,26 +379,29 @@ public class PowerWhitelistManager {
public PowerWhitelistManager(@NonNull Context context) {
mContext = context;
mService = context.getSystemService(DeviceIdleManager.class).getService();
+ mPowerExemptionManager = context.getSystemService(PowerExemptionManager.class);
}
/**
* Add the specified package to the permanent power save whitelist.
+ *
+ * @deprecated Use {@link PowerExemptionManager#addToPermanentAllowList(String)} instead
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
public void addToWhitelist(@NonNull String packageName) {
- addToWhitelist(Collections.singletonList(packageName));
+ mPowerExemptionManager.addToPermanentAllowList(packageName);
}
/**
* Add the specified packages to the permanent power save whitelist.
+ *
+ * @deprecated Use {@link PowerExemptionManager#addToPermanentAllowList(List)} instead
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
public void addToWhitelist(@NonNull List<String> packageNames) {
- try {
- mService.addPowerSaveWhitelistApps(packageNames);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mPowerExemptionManager.addToPermanentAllowList(packageNames);
}
/**
@@ -388,19 +410,13 @@ public class PowerWhitelistManager {
*
* @param includingIdle Set to true if the app should be whitelisted from device idle as well
* as other power save restrictions
+ * @deprecated Use {@link PowerExemptionManager#getAllowListedAppIds(boolean)} instead
* @hide
*/
+ @Deprecated
@NonNull
public int[] getWhitelistedAppIds(boolean includingIdle) {
- try {
- if (includingIdle) {
- return mService.getAppIdWhitelist();
- } else {
- return mService.getAppIdWhitelistExceptIdle();
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mPowerExemptionManager.getAllowListedAppIds(includingIdle);
}
/**
@@ -409,18 +425,12 @@ public class PowerWhitelistManager {
*
* @param includingIdle Set to true if the app should be whitelisted from device
* idle as well as other power save restrictions
+ * @deprecated Use {@link PowerExemptionManager#isAllowListed(String, boolean)} instead
* @hide
*/
+ @Deprecated
public boolean isWhitelisted(@NonNull String packageName, boolean includingIdle) {
- try {
- if (includingIdle) {
- return mService.isPowerSaveWhitelistApp(packageName);
- } else {
- return mService.isPowerSaveWhitelistExceptIdleApp(packageName);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mPowerExemptionManager.isAllowListed(packageName, includingIdle);
}
/**
@@ -429,14 +439,12 @@ public class PowerWhitelistManager {
* whitelisted by default by the system cannot be removed.
*
* @param packageName The app to remove from the whitelist
+ * @deprecated Use {@link PowerExemptionManager#removeFromAllowList(String)} instead
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
public void removeFromWhitelist(@NonNull String packageName) {
- try {
- mService.removePowerSaveWhitelistApp(packageName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mPowerExemptionManager.removeFromAllowList(packageName);
}
/**
@@ -446,16 +454,14 @@ public class PowerWhitelistManager {
* @param durationMs How long to keep the app on the temp whitelist for (in milliseconds)
* @param reasonCode one of {@link ReasonCode}, use {@link #REASON_UNKNOWN} if not sure.
* @param reason a optional human readable reason string, could be null or empty string.
+ * @deprecated Use {@link PowerExemptionManager#addToTemporaryAllowList(
+ * String, long, int, String)} instead
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public void whitelistAppTemporarily(@NonNull String packageName, long durationMs,
@ReasonCode int reasonCode, @Nullable String reason) {
- try {
- mService.addPowerSaveTempWhitelistApp(packageName, durationMs, mContext.getUserId(),
- reasonCode, reason);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mPowerExemptionManager.addToTemporaryAllowList(packageName, durationMs, reasonCode, reason);
}
/**
@@ -463,12 +469,14 @@ public class PowerWhitelistManager {
*
* @param packageName The package to add to the temp whitelist
* @param durationMs How long to keep the app on the temp whitelist for (in milliseconds)
- * @deprecated Use {@link #whitelistAppTemporarily(String, long, int, String)} instead
+ * @deprecated Use {@link PowerExemptionManager#addToTemporaryAllowList(
+ * String, long, int, String)} instead
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public void whitelistAppTemporarily(@NonNull String packageName, long durationMs) {
- whitelistAppTemporarily(packageName, durationMs, REASON_UNKNOWN, packageName);
+ mPowerExemptionManager.addToTemporaryAllowList(
+ packageName, durationMs, REASON_UNKNOWN, packageName);
}
/**
@@ -481,13 +489,15 @@ public class PowerWhitelistManager {
* @param reason A human-readable reason explaining why the app is temp whitelisted. Only
* used for logging purposes. Could be null or empty string.
* @return The duration (in milliseconds) that the app is whitelisted for
- * @deprecated Use {@link #whitelistAppTemporarilyForEvent(String, int, int, String)} instead
+ * @deprecated Use {@link PowerExemptionManager#addToTemporaryAllowListForEvent(
+ * String, int, int, String)} instead
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public long whitelistAppTemporarilyForEvent(@NonNull String packageName,
@WhitelistEvent int event, @Nullable String reason) {
- return whitelistAppTemporarilyForEvent(packageName, event, REASON_UNKNOWN, reason);
+ return mPowerExemptionManager.addToTemporaryAllowListForEvent(
+ packageName, event, REASON_UNKNOWN, reason);
}
/**
@@ -501,47 +511,25 @@ public class PowerWhitelistManager {
* @param reason A human-readable reason explaining why the app is temp whitelisted. Only
* used for logging purposes. Could be null or empty string.
* @return The duration (in milliseconds) that the app is whitelisted for
+ * @deprecated Use {@link PowerExemptionManager#addToTemporaryAllowListForEvent(
+ * String, int, int, String)} instead
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
public long whitelistAppTemporarilyForEvent(@NonNull String packageName,
@WhitelistEvent int event, @ReasonCode int reasonCode, @Nullable String reason) {
- try {
- switch (event) {
- case EVENT_MMS:
- return mService.addPowerSaveTempWhitelistAppForMms(
- packageName, mContext.getUserId(), reasonCode, reason);
- case EVENT_SMS:
- return mService.addPowerSaveTempWhitelistAppForSms(
- packageName, mContext.getUserId(), reasonCode, reason);
- case EVENT_UNSPECIFIED:
- default:
- return mService.whitelistAppTemporarily(
- packageName, mContext.getUserId(), reasonCode, reason);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mPowerExemptionManager.addToTemporaryAllowListForEvent(
+ packageName, event, reasonCode, reason);
}
/**
* @hide
+ *
+ * @deprecated Use {@link PowerExemptionManager#getReasonCodeFromProcState(int)} instead
*/
+ @Deprecated
public static @ReasonCode int getReasonCodeFromProcState(int procState) {
- if (procState <= PROCESS_STATE_PERSISTENT) {
- return REASON_PROC_STATE_PERSISTENT;
- } else if (procState <= PROCESS_STATE_PERSISTENT_UI) {
- return REASON_PROC_STATE_PERSISTENT_UI;
- } else if (procState <= PROCESS_STATE_TOP) {
- return REASON_PROC_STATE_TOP;
- } else if (procState <= PROCESS_STATE_BOUND_TOP) {
- return REASON_PROC_STATE_BTOP;
- } else if (procState <= PROCESS_STATE_FOREGROUND_SERVICE) {
- return REASON_PROC_STATE_FGS;
- } else if (procState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- return REASON_PROC_STATE_BFGS;
- } else {
- return REASON_DENIED;
- }
+ return PowerExemptionManager.getReasonCodeFromProcState(procState);
}
/**
@@ -549,111 +537,10 @@ public class PowerWhitelistManager {
* @hide
* @param reasonCode
* @return string name of the reason code.
+ * @deprecated Use {@link PowerExemptionManager#reasonCodeToString(int)} instead
*/
+ @Deprecated
public static String reasonCodeToString(@ReasonCode int reasonCode) {
- switch (reasonCode) {
- case REASON_DENIED:
- return "DENIED";
- case REASON_UNKNOWN:
- return "UNKNOWN";
- case REASON_OTHER:
- return "OTHER";
- case REASON_PROC_STATE_PERSISTENT:
- return "PROC_STATE_PERSISTENT";
- case REASON_PROC_STATE_PERSISTENT_UI:
- return "PROC_STATE_PERSISTENT_UI";
- case REASON_PROC_STATE_TOP:
- return "PROC_STATE_TOP";
- case REASON_PROC_STATE_BTOP:
- return "PROC_STATE_BTOP";
- case REASON_PROC_STATE_FGS:
- return "PROC_STATE_FGS";
- case REASON_PROC_STATE_BFGS:
- return "PROC_STATE_BFGS";
- case REASON_UID_VISIBLE:
- return "UID_VISIBLE";
- case REASON_SYSTEM_UID:
- return "SYSTEM_UID";
- case REASON_ACTIVITY_STARTER:
- return "ACTIVITY_STARTER";
- case REASON_START_ACTIVITY_FLAG:
- return "START_ACTIVITY_FLAG";
- case REASON_FGS_BINDING:
- return "FGS_BINDING";
- case REASON_DEVICE_OWNER:
- return "DEVICE_OWNER";
- case REASON_PROFILE_OWNER:
- return "PROFILE_OWNER";
- case REASON_COMPANION_DEVICE_MANAGER:
- return "COMPANION_DEVICE_MANAGER";
- case REASON_BACKGROUND_ACTIVITY_PERMISSION:
- return "BACKGROUND_ACTIVITY_PERMISSION";
- case REASON_BACKGROUND_FGS_PERMISSION:
- return "BACKGROUND_FGS_PERMISSION";
- case REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION:
- return "INSTR_BACKGROUND_ACTIVITY_PERMISSION";
- case REASON_INSTR_BACKGROUND_FGS_PERMISSION:
- return "INSTR_BACKGROUND_FGS_PERMISSION";
- case REASON_SYSTEM_ALERT_WINDOW_PERMISSION:
- return "SYSTEM_ALERT_WINDOW_PERMISSION";
- case REASON_DEVICE_DEMO_MODE:
- return "DEVICE_DEMO_MODE";
- case REASON_EXEMPTED_PACKAGE:
- return "EXEMPTED_PACKAGE";
- case REASON_ALLOWLISTED_PACKAGE:
- return "ALLOWLISTED_PACKAGE";
- case REASON_APPOP:
- return "APPOP";
- case REASON_GEOFENCING:
- return "GEOFENCING";
- case REASON_PUSH_MESSAGING:
- return "PUSH_MESSAGING";
- case REASON_PUSH_MESSAGING_OVER_QUOTA:
- return "PUSH_MESSAGING_OVER_QUOTA";
- case REASON_ACTIVITY_RECOGNITION:
- return "ACTIVITY_RECOGNITION";
- case REASON_BOOT_COMPLETED:
- return "BOOT_COMPLETED";
- case REASON_PRE_BOOT_COMPLETED:
- return "PRE_BOOT_COMPLETED";
- case REASON_LOCKED_BOOT_COMPLETED:
- return "LOCKED_BOOT_COMPLETED";
- case REASON_SYSTEM_ALLOW_LISTED:
- return "SYSTEM_ALLOW_LISTED";
- case REASON_ALARM_MANAGER_ALARM_CLOCK:
- return "ALARM_MANAGER_ALARM_CLOCK";
- case REASON_ALARM_MANAGER_WHILE_IDLE:
- return "ALARM_MANAGER_WHILE_IDLE";
- case REASON_SERVICE_LAUNCH:
- return "SERVICE_LAUNCH";
- case REASON_KEY_CHAIN:
- return "KEY_CHAIN";
- case REASON_PACKAGE_VERIFIER:
- return "PACKAGE_VERIFIER";
- case REASON_SYNC_MANAGER:
- return "SYNC_MANAGER";
- case REASON_DOMAIN_VERIFICATION_V1:
- return "DOMAIN_VERIFICATION_V1";
- case REASON_DOMAIN_VERIFICATION_V2:
- return "DOMAIN_VERIFICATION_V2";
- case REASON_VPN:
- return "VPN";
- case REASON_NOTIFICATION_SERVICE:
- return "NOTIFICATION_SERVICE";
- case REASON_PACKAGE_REPLACED:
- return "PACKAGE_REPLACED";
- case REASON_LOCATION_PROVIDER:
- return "LOCATION_PROVIDER";
- case REASON_MEDIA_BUTTON:
- return "MEDIA_BUTTON";
- case REASON_EVENT_SMS:
- return "EVENT_SMS";
- case REASON_EVENT_MMS:
- return "EVENT_MMS";
- case REASON_SHELL:
- return "SHELL";
- default:
- return "(unknown:" + reasonCode + ")";
- }
+ return PowerExemptionManager.reasonCodeToString(reasonCode);
}
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 5a3125a0373b..c0940d6b81bc 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -10501,6 +10501,7 @@ package android.content {
field public static final String DEVICE_POLICY_SERVICE = "device_policy";
field public static final String DISPLAY_HASH_SERVICE = "display_hash";
field public static final String DISPLAY_SERVICE = "display";
+ field public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification";
field public static final String DOWNLOAD_SERVICE = "download";
field public static final String DROPBOX_SERVICE = "dropbox";
field public static final String EUICC_SERVICE = "euicc";
@@ -42015,6 +42016,7 @@ package android.telephony {
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public int getDeviceToDeviceStatusSharing(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions();
method public static int getSlotIndex(int);
method @Nullable public int[] getSubscriptionIds(int);
@@ -42027,6 +42029,7 @@ package android.telephony {
method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharing(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int);
method public void setSubscriptionOverrideCongested(int, boolean, long);
method public void setSubscriptionOverrideCongested(int, boolean, @NonNull int[], long);
@@ -42038,6 +42041,11 @@ package android.telephony {
field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
field public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
field public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
+ field public static final int D2D_SHARING_ALL = 3; // 0x3
+ field public static final int D2D_SHARING_ALL_CONTACTS = 1; // 0x1
+ field public static final int D2D_SHARING_DISABLED = 0; // 0x0
+ field public static final int D2D_SHARING_STARRED_CONTACTS = 2; // 0x2
+ field public static final String D2D_STATUS_SHARING = "d2d_sharing_status";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
field public static final int DATA_ROAMING_ENABLE = 1; // 0x1
field public static final int DEFAULT_SUBSCRIPTION_ID = 2147483647; // 0x7fffffff
@@ -51451,7 +51459,6 @@ package android.view.inputmethod {
method public int describeContents();
method public void dump(android.util.Printer, String);
method public android.content.ComponentName getComponent();
- method public int getConfigChanges();
method public String getId();
method public int getIsDefaultResourceId();
method public String getPackageName();
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6019ab56dea7..bfc205b9f9a6 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2162,7 +2162,6 @@ package android.content {
field public static final int BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND = 262144; // 0x40000
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
- field public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification";
field public static final String ETHERNET_SERVICE = "ethernet";
field public static final String EUICC_CARD_SERVICE = "euicc_card";
field public static final String FONT_SERVICE = "font";
@@ -2174,7 +2173,6 @@ package android.content {
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
- field public static final String POWER_EXEMPTION_SERVICE = "power_exemption";
field public static final String REBOOT_READINESS_SERVICE = "reboot_readiness";
field public static final String ROLLBACK_SERVICE = "rollback";
field public static final String SEARCH_UI_SERVICE = "search_ui";
@@ -2241,6 +2239,7 @@ package android.content {
field @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES) public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE = "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE";
field public static final String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
+ field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_PERMISSION_HISTORY = "android.intent.action.REVIEW_PERMISSION_HISTORY";
field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED";
field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
@@ -7521,12 +7520,12 @@ package android.net.util {
package android.net.vcn {
public class VcnManager {
- method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener);
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.vcn.VcnNetworkPolicyResult applyVcnNetworkPolicy(@NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties);
- method public void removeVcnNetworkPolicyListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void removeVcnNetworkPolicyChangeListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener);
}
- public static interface VcnManager.VcnNetworkPolicyListener {
+ public static interface VcnManager.VcnNetworkPolicyChangeListener {
method public void onPolicyChanged();
}
@@ -8184,6 +8183,7 @@ package android.os {
field public static final int EVENT_MMS = 2; // 0x2
field public static final int EVENT_SMS = 1; // 0x1
field public static final int EVENT_UNSPECIFIED = 0; // 0x0
+ field public static final int REASON_ACCOUNT_TRANSFER = 104; // 0x68
field public static final int REASON_ACTIVITY_RECOGNITION = 103; // 0x67
field public static final int REASON_GEOFENCING = 100; // 0x64
field public static final int REASON_OTHER = 1; // 0x1
@@ -8224,25 +8224,25 @@ package android.os {
field public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1; // 0x1
}
- public class PowerWhitelistManager {
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
- method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void removeFromWhitelist(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long, int, @Nullable String);
+ @Deprecated public class PowerWhitelistManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void addToWhitelist(@NonNull java.util.List<java.lang.String>);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void removeFromWhitelist(@NonNull String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long, int, @Nullable String);
method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void whitelistAppTemporarily(@NonNull String, long);
method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, @Nullable String);
- method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, int, @Nullable String);
- field public static final int EVENT_MMS = 2; // 0x2
- field public static final int EVENT_SMS = 1; // 0x1
- field public static final int EVENT_UNSPECIFIED = 0; // 0x0
- field public static final int REASON_ACTIVITY_RECOGNITION = 103; // 0x67
- field public static final int REASON_GEOFENCING = 100; // 0x64
- field public static final int REASON_OTHER = 1; // 0x1
- field public static final int REASON_PUSH_MESSAGING = 101; // 0x65
- field public static final int REASON_PUSH_MESSAGING_OVER_QUOTA = 102; // 0x66
- field public static final int REASON_UNKNOWN = 0; // 0x0
- field public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
- field public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
+ method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public long whitelistAppTemporarilyForEvent(@NonNull String, int, int, @Nullable String);
+ field @Deprecated public static final int EVENT_MMS = 2; // 0x2
+ field @Deprecated public static final int EVENT_SMS = 1; // 0x1
+ field @Deprecated public static final int EVENT_UNSPECIFIED = 0; // 0x0
+ field @Deprecated public static final int REASON_ACTIVITY_RECOGNITION = 103; // 0x67
+ field @Deprecated public static final int REASON_GEOFENCING = 100; // 0x64
+ field @Deprecated public static final int REASON_OTHER = 1; // 0x1
+ field @Deprecated public static final int REASON_PUSH_MESSAGING = 101; // 0x65
+ field @Deprecated public static final int REASON_PUSH_MESSAGING_OVER_QUOTA = 102; // 0x66
+ field @Deprecated public static final int REASON_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0
+ field @Deprecated public static final int TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1
}
public class RecoverySystem {
@@ -10363,6 +10363,7 @@ package android.telecom {
public abstract class CallDiagnosticService extends android.app.Service {
ctor public CallDiagnosticService();
+ method @NonNull public java.util.concurrent.Executor getExecutor();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onBluetoothCallQualityReportReceived(@NonNull android.telecom.BluetoothCallQualityReport);
method public abstract void onCallAudioStateChanged(@NonNull android.telecom.CallAudioState);
@@ -10435,16 +10436,12 @@ package android.telecom {
ctor public DiagnosticCall();
method public final void clearDiagnosticMessage(int);
method public final void displayDiagnosticMessage(int, @NonNull CharSequence);
- method @NonNull public android.telecom.Call.Details getCallDetails();
method public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details);
method @Nullable public abstract CharSequence onCallDisconnected(int, int);
method @Nullable public abstract CharSequence onCallDisconnected(@NonNull android.telephony.ims.ImsReasonInfo);
method public abstract void onCallQualityReceived(@NonNull android.telephony.CallQuality);
method public abstract void onReceiveDeviceToDeviceMessage(int, int);
method public final void sendDeviceToDeviceMessage(int, int);
- field public static final int AUDIO_CODEC_AMR_NB = 3; // 0x3
- field public static final int AUDIO_CODEC_AMR_WB = 2; // 0x2
- field public static final int AUDIO_CODEC_EVS = 1; // 0x1
field public static final int BATTERY_STATE_CHARGING = 3; // 0x3
field public static final int BATTERY_STATE_GOOD = 2; // 0x2
field public static final int BATTERY_STATE_LOW = 1; // 0x1
@@ -10454,9 +10451,6 @@ package android.telecom {
field public static final int MESSAGE_CALL_NETWORK_TYPE = 1; // 0x1
field public static final int MESSAGE_DEVICE_BATTERY_STATE = 3; // 0x3
field public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4; // 0x4
- field public static final int NETWORK_TYPE_IWLAN = 2; // 0x2
- field public static final int NETWORK_TYPE_LTE = 1; // 0x1
- field public static final int NETWORK_TYPE_NR = 3; // 0x3
}
public abstract class InCallService extends android.app.Service {
@@ -11478,7 +11472,7 @@ package android.telephony {
}
public static interface TelephonyCallback.AllowedNetworkTypesListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onAllowedNetworkTypesChanged(@NonNull java.util.Map<java.lang.Integer,java.lang.Long>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onAllowedNetworkTypesChanged(int, long);
}
public static interface TelephonyCallback.CallAttributesListener {
@@ -11962,7 +11956,7 @@ package android.telephony.data {
method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>);
- method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(@IntRange(from=android.telephony.data.DataCallResponse.PDU_SESSION_ID_NOT_SET, to=15) int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
@@ -13039,6 +13033,7 @@ package android.telephony.ims {
method public void onAutoConfigurationErrorReceived(int, @NonNull String);
method public void onConfigurationChanged(@NonNull byte[]);
method public void onConfigurationReset();
+ method public void onPreProvisioningReceived(@NonNull byte[]);
method public void onRemoved();
}
@@ -13508,6 +13503,7 @@ package android.telephony.ims.stub {
method public int getConfigInt(int);
method public String getConfigString(int);
method public final void notifyAutoConfigurationErrorReceived(int, @NonNull String);
+ method public final void notifyPreProvisioningReceived(@NonNull byte[]);
method public final void notifyProvisionedValueChanged(int, int);
method public final void notifyProvisionedValueChanged(int, String);
method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1713e2d50b81..9fde79171cf6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -699,7 +699,8 @@ package android.content {
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
field public static final String DREAM_SERVICE = "dream";
field public static final String FONT_SERVICE = "font";
- field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
+ field public static final String POWER_EXEMPTION_SERVICE = "power_exemption";
+ field @Deprecated public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
field public static final String TEST_NETWORK_SERVICE = "test_network";
}
@@ -2733,10 +2734,6 @@ package android.view.inputmethod {
method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>);
}
- public final class InputMethodInfo implements android.os.Parcelable {
- ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
- }
-
public final class InputMethodManager {
method public int getDisplayId();
method public boolean hasActiveInputConnection(@Nullable android.view.View);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index dd1bc7c61547..d310e8f0ef5c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -56,6 +56,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -200,9 +201,12 @@ public class AppOpsManager {
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
public static final long SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE = 151105954L;
+ private static final String FULL_LOG = "privacy_attribution_tag_full_log_enabled";
private static final int MAX_UNFORWARDED_OPS = 10;
+ private static Boolean sFullLog = null;
+
final Context mContext;
@UnsupportedAppUsage
@@ -6972,6 +6976,26 @@ public class AppOpsManager {
AppOpsManager(Context context, IAppOpsService service) {
mContext = context;
mService = service;
+
+ if (mContext != null) {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ if (pm != null && pm.checkPermission(Manifest.permission.READ_DEVICE_CONFIG,
+ mContext.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_PRIVACY,
+ mContext.getMainExecutor(), properties -> {
+ if (properties.getKeyset().contains(FULL_LOG)) {
+ sFullLog = properties.getBoolean(FULL_LOG, false);
+ }
+ });
+ return;
+ }
+ } catch (Exception e) {
+ // This manager was made before DeviceConfig is ready, so it's a low-level
+ // system app. We likely don't care about its logs.
+ }
+ }
+ sFullLog = false;
}
/**
@@ -9110,10 +9134,20 @@ public class AppOpsManager {
StringBuilder sb = new StringBuilder();
for (int i = firstInteresting; i <= lastInteresting; i++) {
+ if (sFullLog == null) {
+ try {
+ sFullLog = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ FULL_LOG, false);
+ } catch (SecurityException e) {
+ // This should not happen, but it may, in rare cases
+ sFullLog = false;
+ }
+ }
+
if (i != firstInteresting) {
sb.append('\n');
}
- if (sb.length() + trace[i].toString().length() > 600) {
+ if (!sFullLog && sb.length() + trace[i].toString().length() > 600) {
break;
}
sb.append(trace[i]);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0509e3f77c1f..25234592f4c4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3713,6 +3713,9 @@ public abstract class Context {
* usage statistics.
* <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardware_properties")
* <dd> A {@link android.os.HardwarePropertiesManager} for accessing hardware properties.
+ * <dt> {@link #DOMAIN_VERIFICATION_SERVICE} ("domain_verification")
+ * <dd> A {@link android.content.pm.verify.domain.DomainVerificationManager} for accessing
+ * web domain approval state.
* </dl>
*
* <p>Note: System services obtained via this API may be closely associated with
@@ -3794,6 +3797,8 @@ public abstract class Context {
* @see android.app.usage.NetworkStatsManager
* @see android.os.HardwarePropertiesManager
* @see #HARDWARE_PROPERTIES_SERVICE
+ * @see #DOMAIN_VERIFICATION_SERVICE
+ * @see android.content.pm.verify.domain.DomainVerificationManager
*/
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
@@ -3813,7 +3818,8 @@ public abstract class Context {
* {@link android.view.inputmethod.InputMethodManager},
* {@link android.app.UiModeManager}, {@link android.app.DownloadManager},
* {@link android.os.BatteryManager}, {@link android.app.job.JobScheduler},
- * {@link android.app.usage.NetworkStatsManager}.
+ * {@link android.app.usage.NetworkStatsManager},
+ * {@link android.content.pm.verify.domain.DomainVerificationManager}.
* </p>
*
* <p>
@@ -4833,7 +4839,8 @@ public abstract class Context {
* @hide
*/
@TestApi
- @SuppressLint("ServiceName") // TODO: This should be renamed to POWER_WHITELIST_SERVICE
+ @Deprecated
+ @SuppressLint("ServiceName")
public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
/**
@@ -4842,7 +4849,7 @@ public abstract class Context {
* @see #getSystemService(String)
* @hide
*/
- @SystemApi
+ @TestApi
public static final String POWER_EXEMPTION_SERVICE = "power_exemption";
/**
@@ -5544,12 +5551,13 @@ public abstract class Context {
public static final String GAME_SERVICE = "game";
/**
- * Use with {@link #getSystemService(String)} to access domain verification service.
+ * Use with {@link #getSystemService(String)} to access
+ * {@link android.content.pm.verify.domain.DomainVerificationManager} to retrieve approval and
+ * user state for declared web domains.
*
* @see #getSystemService(String)
- * @hide
+ * @see android.content.pm.verify.domain.DomainVerificationManager
*/
- @SystemApi
public static final String DOMAIN_VERIFICATION_SERVICE = "domain_verification";
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 04f93ca6991b..c601aabb582b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2172,6 +2172,29 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.REVIEW_PERMISSION_USAGE";
/**
+ * Activity action: Launch UI to review the timeline history of permissions.
+ * <p>
+ * Input: {@link #EXTRA_PERMISSION_GROUP_NAME} specifies the permission group name
+ * that will be displayed by the launched UI.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ * <p class="note">
+ * This requires {@link android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS} permission.
+ * </p>
+ *
+ * @see #EXTRA_PERMISSION_GROUP_NAME
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REVIEW_PERMISSION_HISTORY =
+ "android.intent.action.REVIEW_PERMISSION_HISTORY";
+
+ /**
* Activity action: Launch UI to review ongoing app uses of permissions.
* <p>
* Input: {@link #EXTRA_DURATION_MILLIS} specifies the minimum number of milliseconds of recent
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index 745c39b460fa..79b70f2bd5ee 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -23,32 +23,34 @@ package android.content.pm;
oneway interface IDataLoaderStatusListener {
/** The DataLoader process died, binder disconnected or class destroyed. */
const int DATA_LOADER_DESTROYED = 0;
+ /** The system is in process of binding to the DataLoader. */
+ const int DATA_LOADER_BINDING = 1;
/** DataLoader process is running and bound to. */
- const int DATA_LOADER_BOUND = 1;
+ const int DATA_LOADER_BOUND = 2;
/** DataLoader has handled onCreate(). */
- const int DATA_LOADER_CREATED = 2;
+ const int DATA_LOADER_CREATED = 3;
/** DataLoader can receive missing pages and read pages notifications,
* and ready to provide data. */
- const int DATA_LOADER_STARTED = 3;
+ const int DATA_LOADER_STARTED = 4;
/** DataLoader no longer ready to provide data and is not receiving
* any notifications from IncFS. */
- const int DATA_LOADER_STOPPED = 4;
+ const int DATA_LOADER_STOPPED = 5;
/** DataLoader streamed everything necessary to continue installation. */
- const int DATA_LOADER_IMAGE_READY = 5;
+ const int DATA_LOADER_IMAGE_READY = 6;
/** Installation can't continue as DataLoader failed to stream necessary data. */
- const int DATA_LOADER_IMAGE_NOT_READY = 6;
+ const int DATA_LOADER_IMAGE_NOT_READY = 7;
/** DataLoader instance can't run at the moment, but might recover later.
* It's up to system to decide if the app is still usable. */
- const int DATA_LOADER_UNAVAILABLE = 7;
+ const int DATA_LOADER_UNAVAILABLE = 8;
/** DataLoader reports that this instance is invalid and can never be restored.
* Warning: this is a terminal status that data loader should use carefully and
* the system should almost never use - e.g. only if all recovery attempts
* fail and all retry limits are exceeded. */
- const int DATA_LOADER_UNRECOVERABLE = 8;
+ const int DATA_LOADER_UNRECOVERABLE = 9;
/** There are no known issues with the data stream. */
const int STREAM_HEALTHY = 0;
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 9198eb74d1f8..5cfcd667632b 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -171,7 +171,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
SomeArgs args = (SomeArgs) msg.obj;
try {
inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1,
- (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3);
+ (IInputMethodPrivilegedOperations) args.arg2);
} finally {
args.recycle();
}
@@ -280,10 +280,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privOps, int configChanges) {
+ IInputMethodPrivilegedOperations privOps) {
mCaller.executeOrSendMessage(
- mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps,
- configChanges));
+ mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 40a0fc4e8339..7e2be01feb01 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -70,7 +70,6 @@ import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -132,7 +131,6 @@ import android.widget.TextView;
import android.window.WindowMetricsHelper;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
@@ -515,8 +513,6 @@ public class InputMethodService extends AbstractInputMethodService {
private boolean mIsAutomotive;
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
- private Configuration mLastKnownConfig;
- private int mHandledConfigChanges;
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
@@ -592,13 +588,12 @@ public class InputMethodService extends AbstractInputMethodService {
@MainThread
@Override
public final void initializeInternal(@NonNull IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
+ IInputMethodPrivilegedOperations privilegedOperations) {
if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) {
Log.w(TAG, "The token has already registered, ignore this initialization.");
return;
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
- mHandledConfigChanges = configChanges;
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
updateInputMethodDisplay(displayId);
@@ -826,9 +821,6 @@ public class InputMethodService extends AbstractInputMethodService {
setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
}
final boolean isVisible = isInputViewShown();
- if (isVisible && getResources() != null) {
- mLastKnownConfig = new Configuration(getResources().getConfiguration());
- }
final boolean visibilityChanged = isVisible != wasVisible;
if (resultReceiver != null) {
resultReceiver.send(visibilityChanged
@@ -1436,30 +1428,10 @@ public class InputMethodService extends AbstractInputMethodService {
* state: {@link #onStartInput} if input is active, and
* {@link #onCreateInputView} and {@link #onStartInputView} and related
* appropriate functions if the UI is displayed.
- * <p>Starting with {@link Build.VERSION_CODES#S}, IMEs can opt into handling configuration
- * changes themselves instead of being restarted with
- * {@link android.R.styleable#InputMethod_configChanges}.
*/
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- if (shouldImeRestartForConfig(newConfig)) {
- resetStateForNewConfiguration();
- }
- }
-
- /**
- * @return {@code true} if {@link InputMethodService} needs to restart to handle
- * .{@link #onConfigurationChanged(Configuration)}
- */
- @VisibleForTesting
- boolean shouldImeRestartForConfig(@NonNull Configuration newConfig) {
- if (mLastKnownConfig == null) {
- return true;
- }
- // If the new config is the same as the config this Service is already running with,
- // then don't bother calling resetStateForNewConfiguration.
- int unhandledDiff = (mLastKnownConfig.diffPublicOnly(newConfig) & ~mHandledConfigChanges);
- return unhandledDiff != 0;
+ resetStateForNewConfiguration();
}
private void resetStateForNewConfiguration() {
@@ -3209,17 +3181,7 @@ public class InputMethodService extends AbstractInputMethodService {
requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS);
}
}
-
- @VisibleForTesting
- void setLastKnownConfig(@NonNull Configuration config) {
- mLastKnownConfig = config;
- }
-
- @VisibleForTesting
- void setHandledConfigChanges(int configChanges) {
- mHandledConfigChanges = configChanges;
- }
-
+
void startExtractingText(boolean inputChanged) {
final ExtractEditText eet = mExtractEditText;
if (eet != null && getCurrentInputStarted()
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 8ebf757760c3..062438c6e5db 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -73,7 +73,8 @@ import java.util.concurrent.Executor;
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
- private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+ private static final Map<
+ VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
@NonNull private final Context mContext;
@@ -93,13 +94,13 @@ public class VcnManager {
}
/**
- * Get all currently registered VcnNetworkPolicyListeners for testing purposes.
+ * Get all currently registered VcnNetworkPolicyChangeListeners for testing purposes.
*
* @hide
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
@NonNull
- public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+ public static Map<VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
getAllPolicyListeners() {
return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS);
}
@@ -162,14 +163,14 @@ public class VcnManager {
}
// TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using
- // the new VcnNetworkPolicyListener API
+ // the new VcnNetworkPolicyChangeListener API
/**
* VcnUnderlyingNetworkPolicyListener is the interface through which internal system components
* can register to receive updates for VCN-underlying Network policies from the System Server.
*
* @hide
*/
- public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {}
+ public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyChangeListener {}
/**
* Add a listener for VCN-underlying network policy updates.
@@ -185,7 +186,7 @@ public class VcnManager {
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public void addVcnUnderlyingNetworkPolicyListener(
@NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
- addVcnNetworkPolicyListener(executor, listener);
+ addVcnNetworkPolicyChangeListener(executor, listener);
}
/**
@@ -198,7 +199,7 @@ public class VcnManager {
*/
public void removeVcnUnderlyingNetworkPolicyListener(
@NonNull VcnUnderlyingNetworkPolicyListener listener) {
- removeVcnNetworkPolicyListener(listener);
+ removeVcnNetworkPolicyChangeListener(listener);
}
/**
@@ -233,20 +234,20 @@ public class VcnManager {
}
/**
- * VcnNetworkPolicyListener is the interface through which internal system components (e.g.
- * Network Factories) can register to receive updates for VCN-underlying Network policies from
- * the System Server.
+ * VcnNetworkPolicyChangeListener is the interface through which internal system components
+ * (e.g. Network Factories) can register to receive updates for VCN-underlying Network policies
+ * from the System Server.
*
* <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks
- * should register a VcnNetworkPolicyListener. VcnManager will then use this listener to notify
- * the registrant when VCN Network policies change. Upon receiving this signal, the listener
- * must check {@link VcnManager} for the current Network policy result for each of its Networks
- * via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
+ * should register a VcnNetworkPolicyChangeListener. VcnManager will then use this listener to
+ * notify the registrant when VCN Network policies change. Upon receiving this signal, the
+ * listener must check {@link VcnManager} for the current Network policy result for each of its
+ * Networks via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
*
* @hide
*/
@SystemApi
- public interface VcnNetworkPolicyListener {
+ public interface VcnNetworkPolicyChangeListener {
/**
* Notifies the implementation that the VCN's underlying Network policy has changed.
*
@@ -260,20 +261,21 @@ public class VcnManager {
/**
* Add a listener for VCN-underlying Network policy updates.
*
- * <p>A {@link VcnNetworkPolicyListener} is eligible to begin receiving callbacks once it is
- * registered. No callbacks are guaranteed upon registration.
+ * <p>A {@link VcnNetworkPolicyChangeListener} is eligible to begin receiving callbacks once it
+ * is registered. No callbacks are guaranteed upon registration.
*
* @param executor the Executor that will be used for invoking all calls to the specified
* Listener
- * @param listener the VcnNetworkPolicyListener to be added
+ * @param listener the VcnNetworkPolicyChangeListener to be added
* @throws SecurityException if the caller does not have permission NETWORK_FACTORY
- * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered
+ * @throws IllegalStateException if the specified VcnNetworkPolicyChangeListener is already
+ * registered
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public void addVcnNetworkPolicyListener(
- @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) {
+ public void addVcnNetworkPolicyChangeListener(
+ @NonNull Executor executor, @NonNull VcnNetworkPolicyChangeListener listener) {
requireNonNull(executor, "executor must not be null");
requireNonNull(listener, "listener must not be null");
@@ -292,15 +294,18 @@ public class VcnManager {
}
/**
- * Remove the specified VcnNetworkPolicyListener from VcnManager.
+ * Remove the specified VcnNetworkPolicyChangeListener from VcnManager.
*
* <p>If the specified listener is not currently registered, this is a no-op.
*
- * @param listener the VcnNetworkPolicyListener that will be removed
+ * @param listener the VcnNetworkPolicyChangeListener that will be removed
+ * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
* @hide
*/
@SystemApi
- public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) {
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void removeVcnNetworkPolicyChangeListener(
+ @NonNull VcnNetworkPolicyChangeListener listener) {
requireNonNull(listener, "listener must not be null");
VcnUnderlyingNetworkPolicyListenerBinder binder =
@@ -320,8 +325,9 @@ public class VcnManager {
* Applies the network policy for a {@link android.net.Network} with the given parameters.
*
* <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
- * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider
- * MUST poll for the updated Network policy based on that Network's capabilities and properties.
+ * may have changed via {@link VcnNetworkPolicyChangeListener#onPolicyChanged()}, a Network
+ * Provider MUST poll for the updated Network policy based on that Network's capabilities and
+ * properties.
*
* @param networkCapabilities the NetworkCapabilities to be used in determining the Network
* policy result for this Network.
@@ -532,17 +538,18 @@ public class VcnManager {
}
/**
- * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server.
+ * Binder wrapper for added VcnNetworkPolicyChangeListeners to receive signals from System
+ * Server.
*
* @hide
*/
private static class VcnUnderlyingNetworkPolicyListenerBinder
extends IVcnUnderlyingNetworkPolicyListener.Stub {
@NonNull private final Executor mExecutor;
- @NonNull private final VcnNetworkPolicyListener mListener;
+ @NonNull private final VcnNetworkPolicyChangeListener mListener;
private VcnUnderlyingNetworkPolicyListenerBinder(
- Executor executor, VcnNetworkPolicyListener listener) {
+ Executor executor, VcnNetworkPolicyChangeListener listener) {
mExecutor = executor;
mListener = listener;
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 66f7bd9d8dee..4c26e2f33fb2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -995,6 +995,15 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getScreenOnMeasuredBatteryConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the uid's cpu usage, derived from
+ * on device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCpuMeasuredBatteryConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) used by this uid for each
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
* type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
@@ -2521,6 +2530,15 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getScreenDozeMeasuredBatteryConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the cpu, derived from on device power
+ * measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCpuMeasuredBatteryConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) that each
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
* type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}) consumed.
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index b003d238c268..b90d438ffb93 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -208,6 +208,28 @@ public abstract class Vibrator {
public abstract boolean hasAmplitudeControl();
/**
+ * Gets the resonant frequency of the vibrator.
+ *
+ * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or
+ * this vibrator is a composite of multiple physical devices.
+ * @hide
+ */
+ public float getResonantFrequency() {
+ return Float.NaN;
+ }
+
+ /**
+ * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator.
+ *
+ * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown or
+ * this vibrator is a composite of multiple physical devices.
+ * @hide
+ */
+ public float getQFactor() {
+ return Float.NaN;
+ }
+
+ /**
* Configure an always-on haptics effect.
*
* @param alwaysOnId The board-specific always-on ID to configure.
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
index 50d2de3da965..3121b952281e 100644
--- a/core/java/android/os/VibratorInfo.java
+++ b/core/java/android/os/VibratorInfo.java
@@ -42,21 +42,27 @@ public final class VibratorInfo implements Parcelable {
private final SparseBooleanArray mSupportedEffects;
@Nullable
private final SparseBooleanArray mSupportedPrimitives;
+ private final float mResonantFrequency;
+ private final float mQFactor;
VibratorInfo(Parcel in) {
mId = in.readInt();
mCapabilities = in.readLong();
mSupportedEffects = in.readSparseBooleanArray();
mSupportedPrimitives = in.readSparseBooleanArray();
+ mResonantFrequency = in.readFloat();
+ mQFactor = in.readFloat();
}
/** @hide */
public VibratorInfo(int id, long capabilities, int[] supportedEffects,
- int[] supportedPrimitives) {
+ int[] supportedPrimitives, float resonantFrequency, float qFactor) {
mId = id;
mCapabilities = capabilities;
mSupportedEffects = toSparseBooleanArray(supportedEffects);
mSupportedPrimitives = toSparseBooleanArray(supportedPrimitives);
+ mResonantFrequency = resonantFrequency;
+ mQFactor = qFactor;
}
@Override
@@ -65,6 +71,8 @@ public final class VibratorInfo implements Parcelable {
dest.writeLong(mCapabilities);
dest.writeSparseBooleanArray(mSupportedEffects);
dest.writeSparseBooleanArray(mSupportedPrimitives);
+ dest.writeFloat(mResonantFrequency);
+ dest.writeFloat(mQFactor);
}
@Override
@@ -83,12 +91,15 @@ public final class VibratorInfo implements Parcelable {
VibratorInfo that = (VibratorInfo) o;
return mId == that.mId && mCapabilities == that.mCapabilities
&& Objects.equals(mSupportedEffects, that.mSupportedEffects)
- && Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives);
+ && Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives)
+ && Objects.equals(mResonantFrequency, that.mResonantFrequency)
+ && Objects.equals(mQFactor, that.mQFactor);
}
@Override
public int hashCode() {
- return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives);
+ return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives,
+ mResonantFrequency, mQFactor);
}
@Override
@@ -99,6 +110,8 @@ public final class VibratorInfo implements Parcelable {
+ ", mCapabilities flags=" + Long.toBinaryString(mCapabilities)
+ ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames())
+ ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames())
+ + ", mResonantFrequency=" + mResonantFrequency
+ + ", mQFactor=" + mQFactor
+ '}';
}
@@ -156,6 +169,26 @@ public final class VibratorInfo implements Parcelable {
return (mCapabilities & capability) == capability;
}
+ /**
+ * Gets the resonant frequency of the vibrator.
+ *
+ * @return the resonant frequency of the vibrator, or {@link Float#NaN NaN} if it's unknown or
+ * this vibrator is a composite of multiple physical devices.
+ */
+ public float getResonantFrequency() {
+ return mResonantFrequency;
+ }
+
+ /**
+ * Gets the <a href="https://en.wikipedia.org/wiki/Q_factor">Q factor</a> of the vibrator.
+ *
+ * @return the Q factor of the vibrator, or {@link Float#NaN NaN} if it's unknown or
+ * this vibrator is a composite of multiple physical devices.
+ */
+ public float getQFactor() {
+ return mQFactor;
+ }
+
private String[] getCapabilitiesNames() {
List<String> names = new ArrayList<>();
if (hasCapability(IVibrator.CAP_ON_CALLBACK)) {
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 4c9e77c35135..7e3a0f30e75c 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -111,8 +111,7 @@ public class PermissionUsageHelper {
private static boolean shouldShowLocationIndicator() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_INDICATORS_ENABLED, false)
- || shouldShowPermissionsHub();
+ PROPERTY_LOCATION_INDICATORS_ENABLED, false);
}
private static long getRecentThreshold(Long now) {
@@ -326,10 +325,10 @@ public class PermissionUsageHelper {
}
if (packageName.equals(SYSTEM_PKG)
- || (!isUserSensitive(packageName, user, op)
+ || (!shouldShowPermissionsHub()
+ && !isUserSensitive(packageName, user, op)
&& !isLocationProvider(packageName, user)
- && !isAppPredictor(packageName, user))
- && !isSpeechRecognizerUsage(op, packageName)) {
+ && !isSpeechRecognizerUsage(op, packageName))) {
continue;
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 8a4812a42c8a..374de9ccb2f4 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5310,5 +5310,12 @@ public final class Telephony {
* @hide
*/
public static final String COLUMN_VOIMS_OPT_IN_STATUS = "voims_opt_in_status";
+
+ /**
+ * TelephonyProvider column name for device to device sharing status.
+ *
+ * @hide
+ */
+ public static final String COLUMN_D2D_STATUS_SHARING = "d2d_sharing_status";
}
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index bbe887f500a9..e9a79e70fd74 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -20,7 +20,6 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.compat.annotation.ChangeId;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
@@ -1577,7 +1576,7 @@ public class PhoneStateListener {
// default implementation empty
}
- public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) {
+ public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) {
// default implementation empty
}
}
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 2cadda25a9d3..e3d3dec60151 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -546,9 +546,6 @@ public class TelephonyCallback {
/**
* Event for changes to allowed network list based on all active subscriptions.
*
- * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
- * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
- *
* @hide
* @see AllowedNetworkTypesListener#onAllowedNetworkTypesChanged
*/
@@ -1265,30 +1262,34 @@ public class TelephonyCallback {
public interface AllowedNetworkTypesListener {
/**
* Callback invoked when the current allowed network type list has changed on the
- * registered subscription.
+ * registered subscription for a specified reason.
* Note, the registered subscription is associated with {@link TelephonyManager} object
- * on which
- * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}
+ * on which {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}
* was called.
* If this TelephonyManager object was created with
* {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
* given subscription ID. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
- * @param allowedNetworkTypesList Map associating all allowed network type reasons
- * ({@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER},
- * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER},
- * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER}, and
- * {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}) with reason's allowed
- * network type values.
+ * @param reason an allowed network type reasons.
+ * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER
+ * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER
+ * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER
+ * @see TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G
+ *
+ * @param allowedNetworkType an allowed network type bitmask value. (for example,
+ * the long bitmask value is {{@link TelephonyManager#NETWORK_TYPE_BITMASK_NR}|
+ * {@link TelephonyManager#NETWORK_TYPE_BITMASK_LTE}})
+ *
* For example:
- * map{{TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER, long type value},
- * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_POWER, long type value},
- * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_CARRIER, long type value},
- * {TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, long type value}}
+ * If the latest allowed network type is changed by user, then the system
+ * notifies the {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_USER} and
+ * long type value}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- void onAllowedNetworkTypesChanged(@NonNull Map<Integer, Long> allowedNetworkTypesList);
+ void onAllowedNetworkTypesChanged(
+ @TelephonyManager.AllowedNetworkTypesReason int reason,
+ @TelephonyManager.NetworkTypeBitMask long allowedNetworkType);
}
/**
@@ -1707,14 +1708,15 @@ public class TelephonyCallback {
enabled, reason)));
}
- public void onAllowedNetworkTypesChanged(Map allowedNetworkTypesList) {
+ public void onAllowedNetworkTypesChanged(int reason, long allowedNetworkType) {
AllowedNetworkTypesListener listener =
(AllowedNetworkTypesListener) mTelephonyCallbackWeakRef.get();
if (listener == null) return;
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
- () -> listener.onAllowedNetworkTypesChanged(allowedNetworkTypesList)));
+ () -> listener.onAllowedNetworkTypesChanged(reason,
+ allowedNetworkType)));
}
}
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 9cda4ae79335..3fa63d8c1a9c 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -825,16 +825,18 @@ public class TelephonyRegistryManager {
}
/**
- * Notify emergency number list changed on certain subscription.
- *
- * @param slotIndex for which emergency number list changed. Can be derived from subId except
- * when subId is invalid.
- * @param subId for which emergency number list changed.
+ * Notify the allowed network types has changed for a specific subscription and the specific
+ * reason.
+ * @param slotIndex for which allowed network types changed.
+ * @param subId for which allowed network types changed.
+ * @param reason an allowed network type reasons.
+ * @param allowedNetworkType an allowed network type bitmask value.
*/
public void notifyAllowedNetworkTypesChanged(int slotIndex, int subId,
- Map<Integer, Long> allowedNetworkTypeList) {
+ int reason, long allowedNetworkType) {
try {
- sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, allowedNetworkTypeList);
+ sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, reason,
+ allowedNetworkType);
} catch (RemoteException ex) {
// system process is dead
}
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index 3880131324fc..f61ab2985163 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -16,14 +16,26 @@
package android.util;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.Formatter;
+import java.util.Locale;
+
/**
* @hide
*/
public final class Slog {
+ @GuardedBy("sMessageBuilder")
+ private static final StringBuilder sMessageBuilder = new StringBuilder();
+
+ @GuardedBy("sMessageBuilder")
+ private static final Formatter sFormatter = new Formatter(sMessageBuilder, Locale.ENGLISH);
+
private Slog() {
}
@@ -37,6 +49,15 @@ public final class Slog {
msg + '\n' + Log.getStackTraceString(tr));
}
+ /**
+ * Logs a {@link Log.VERBOSE} message.
+ */
+ public static void v(String tag, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.VERBOSE)) return;
+
+ v(tag, getMessage(format, args));
+ }
+
@UnsupportedAppUsage
public static int d(String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, Log.DEBUG, tag, msg);
@@ -48,6 +69,15 @@ public final class Slog {
msg + '\n' + Log.getStackTraceString(tr));
}
+ /**
+ * Logs a {@link Log.DEBUG} message.
+ */
+ public static void d(String tag, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.DEBUG)) return;
+
+ d(tag, getMessage(format, args));
+ }
+
@UnsupportedAppUsage
public static int i(String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, Log.INFO, tag, msg);
@@ -58,6 +88,15 @@ public final class Slog {
msg + '\n' + Log.getStackTraceString(tr));
}
+ /**
+ * Logs a {@link Log.INFO} message.
+ */
+ public static void i(String tag, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.INFO)) return;
+
+ i(tag, getMessage(format, args));
+ }
+
@UnsupportedAppUsage
public static int w(String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, Log.WARN, tag, msg);
@@ -73,6 +112,24 @@ public final class Slog {
return Log.println_native(Log.LOG_ID_SYSTEM, Log.WARN, tag, Log.getStackTraceString(tr));
}
+ /**
+ * Logs a {@link Log.WARN} message.
+ */
+ public static void w(String tag, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.WARN)) return;
+
+ w(tag, getMessage(format, args));
+ }
+
+ /**
+ * Logs a {@link Log.WARN} message with an exception
+ */
+ public static void w(String tag, Exception exception, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.WARN)) return;
+
+ w(tag, getMessage(format, args), exception);
+ }
+
@UnsupportedAppUsage
public static int e(String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, Log.ERROR, tag, msg);
@@ -85,6 +142,24 @@ public final class Slog {
}
/**
+ * Logs a {@link Log.ERROR} message.
+ */
+ public static void e(String tag, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.ERROR)) return;
+
+ e(tag, getMessage(format, args));
+ }
+
+ /**
+ * Logs a {@link Log.ERROR} message with an exception
+ */
+ public static void e(String tag, Exception exception, String format, @Nullable Object... args) {
+ if (!Log.isLoggable(tag, Log.ERROR)) return;
+
+ e(tag, getMessage(format, args), exception);
+ }
+
+ /**
* Like {@link Log#wtf(String, String)}, but will never cause the caller to crash, and
* will always be handled asynchronously. Primarily for use by coding running within
* the system process.
@@ -95,6 +170,21 @@ public final class Slog {
}
/**
+ * Logs a {@code wtf} message.
+ */
+ public static void wtf(String tag, String format, @Nullable Object... args) {
+ wtf(tag, getMessage(format, args));
+ }
+
+ /**
+ * Logs a {@code wtf} message with an exception.
+ */
+ public static void wtf(String tag, Exception exception, String format,
+ @Nullable Object... args) {
+ wtf(tag, getMessage(format, args), exception);
+ }
+
+ /**
* Like {@link #wtf(String, String)}, but does not output anything to the log.
*/
public static void wtfQuiet(String tag, String msg) {
@@ -134,5 +224,13 @@ public final class Slog {
public static int println(int priority, String tag, String msg) {
return Log.println_native(Log.LOG_ID_SYSTEM, priority, tag, msg);
}
-}
+ private static String getMessage(String format, @Nullable Object... args) {
+ synchronized (sMessageBuilder) {
+ sFormatter.format(format, args);
+ String message = sMessageBuilder.toString();
+ sMessageBuilder.setLength(0);
+ return message;
+ }
+ }
+}
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 02a97888cffd..aa1acc1217df 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.os.Build;
@@ -25,6 +26,8 @@ import android.text.method.MetaKeyKeyListener;
import android.util.AndroidRuntimeException;
import android.util.SparseIntArray;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.text.Normalizer;
/**
@@ -297,6 +300,8 @@ public class KeyCharacterMap implements Parcelable {
private static native char nativeGetDisplayLabel(long ptr, int keyCode);
private static native int nativeGetKeyboardType(long ptr);
private static native KeyEvent[] nativeGetEvents(long ptr, char[] chars);
+ private static native KeyCharacterMap nativeObtainEmptyKeyCharacterMap(int deviceId);
+ private static native boolean nativeEquals(long ptr1, long ptr2);
private KeyCharacterMap(Parcel in) {
if (in == null) {
@@ -323,6 +328,18 @@ public class KeyCharacterMap implements Parcelable {
}
/**
+ * Obtain empty key character map
+ * @param deviceId The input device ID
+ * @return The KeyCharacterMap object
+ * @hide
+ */
+ @VisibleForTesting
+ @Nullable
+ public static KeyCharacterMap obtainEmptyMap(int deviceId) {
+ return nativeObtainEmptyKeyCharacterMap(deviceId);
+ }
+
+ /**
* Loads the key character maps for the keyboard with the specified device id.
*
* @param deviceId The device id of the keyboard.
@@ -729,6 +746,18 @@ public class KeyCharacterMap implements Parcelable {
return 0;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof KeyCharacterMap)) {
+ return false;
+ }
+ KeyCharacterMap peer = (KeyCharacterMap) obj;
+ if (mPtr == 0 || peer.mPtr == 0) {
+ return mPtr == peer.mPtr;
+ }
+ return nativeEquals(mPtr, peer.mPtr);
+ }
+
/**
* Thrown by {@link KeyCharacterMap#load} when a key character map could not be loaded.
*/
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index 6ade5e622eab..de4554b9e624 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -105,7 +105,7 @@ public interface InputMethod {
*/
@MainThread
default void initializeInternal(IBinder token, int displayId,
- IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
+ IInputMethodPrivilegedOperations privilegedOperations) {
updateInputMethodDisplay(displayId);
attachToken(token);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 25712f8bf9b8..5d876a6f62d3 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,23 +18,19 @@ package android.view.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
-import android.inputmethodservice.InputMethodService;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -64,7 +60,6 @@ import java.util.List;
* @attr ref android.R.styleable#InputMethod_isDefault
* @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
* @attr ref android.R.styleable#InputMethod_supportsInlineSuggestions
- * @attr ref android.R.styleable#InputMethod_configChanges
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -123,12 +118,6 @@ public final class InputMethodInfo implements Parcelable {
private final boolean mInlineSuggestionsEnabled;
/**
- * The flag for configurations IME assumes the responsibility for handling in
- * {@link InputMethodService#onConfigurationChanged(Configuration)}}.
- */
- private final int mHandledConfigChanges;
-
- /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -214,8 +203,6 @@ public final class InputMethodInfo implements Parcelable {
false);
inlineSuggestionsEnabled = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_supportsInlineSuggestions, false);
- mHandledConfigChanges = sa.getInt(
- com.android.internal.R.styleable.InputMethod_configChanges, 0);
sa.recycle();
final int depth = parser.getDepth();
@@ -300,7 +287,6 @@ public final class InputMethodInfo implements Parcelable {
mIsVrOnly = source.readBoolean();
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
- mHandledConfigChanges = source.readInt();
mForceDefault = false;
}
@@ -312,22 +298,7 @@ public final class InputMethodInfo implements Parcelable {
this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* inlineSuggestionsEnabled */, false /* isVrOnly */,
- 0 /* handledConfigChanges */);
- }
-
- /**
- * Temporary API for creating a built-in input method for test.
- * @hide
- */
- @TestApi
- public InputMethodInfo(@NonNull String packageName, @NonNull String className,
- @NonNull CharSequence label, @NonNull String settingsActivity,
- int handledConfigChanges) {
- this(buildFakeResolveInfo(packageName, className, label), false /* isAuxIme */,
- settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
- false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- false /* inlineSuggestionsEnabled */, false /* isVrOnly */, handledConfigChanges);
+ false /* inlineSuggestionsEnabled */, false /* isVrOnly */);
}
/**
@@ -339,7 +310,7 @@ public final class InputMethodInfo implements Parcelable {
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
true /* supportsSwitchingToNextInputMethod */, false /* inlineSuggestionsEnabled */,
- false /* isVrOnly */, 0 /* handledconfigChanges */);
+ false /* isVrOnly */);
}
/**
@@ -350,8 +321,7 @@ public final class InputMethodInfo implements Parcelable {
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean isVrOnly) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly,
- 0 /* handledConfigChanges */);
+ supportsSwitchingToNextInputMethod, false /* inlineSuggestionsEnabled */, isVrOnly);
}
/**
@@ -361,7 +331,7 @@ public final class InputMethodInfo implements Parcelable {
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
boolean supportsSwitchingToNextInputMethod, boolean inlineSuggestionsEnabled,
- boolean isVrOnly, int handledConfigChanges) {
+ boolean isVrOnly) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -373,7 +343,6 @@ public final class InputMethodInfo implements Parcelable {
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
mInlineSuggestionsEnabled = inlineSuggestionsEnabled;
mIsVrOnly = isVrOnly;
- mHandledConfigChanges = handledConfigChanges;
}
private static ResolveInfo buildFakeResolveInfo(String packageName, String className,
@@ -520,17 +489,6 @@ public final class InputMethodInfo implements Parcelable {
}
}
- /**
- * Returns the bit mask of kinds of configuration changes that this IME
- * can handle itself (without being restarted by the system).
- *
- * @attr ref android.R.styleable#InputMethod_configChanges
- */
- @ActivityInfo.Config
- public int getConfigChanges() {
- return mHandledConfigChanges;
- }
-
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
@@ -621,7 +579,6 @@ public final class InputMethodInfo implements Parcelable {
dest.writeBoolean(mIsVrOnly);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
- dest.writeInt(mHandledConfigChanges);
}
/**
diff --git a/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
index b4f216ba87fa..1d865c2513cf 100644
--- a/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
+++ b/core/java/com/android/internal/graphics/palette/WSMeansQuantizer.java
@@ -75,7 +75,7 @@ public class WSMeansQuantizer implements Quantizer {
// Note: they don't _have_ to be ignored, for example, we could instead turn them
// opaque. Traditionally, including outside Android, quantizers ignore transparent
// pixels, so that strategy was chosen.
- int alpha = (pixel >> 24);
+ int alpha = (pixel >> 24) & 0xff;
if (alpha < 255) {
continue;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9ecb0ad09bc4..11466f4bc042 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6976,6 +6976,11 @@ public class BatteryStatsImpl extends BatteryStats {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE);
}
+ @Override
+ public long getCpuMeasuredBatteryConsumptionUC() {
+ return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
+ }
+
/**
* Returns the consumption (in microcoulombs) that the given standard power bucket consumed.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable
@@ -8482,6 +8487,11 @@ public class BatteryStatsImpl extends BatteryStats {
return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
}
+ @Override
+ public long getCpuMeasuredBatteryConsumptionUC() {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
+ }
+
void initNetworkActivityLocked() {
detachIfNotNull(mNetworkByteActivityCounters);
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 97f727ba72c5..b15543a26b4c 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -85,12 +85,14 @@ public class CpuPowerCalculator extends PowerCalculator {
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, app.getBatteryStatsUid(), result);
+ calculateApp(app, app.getBatteryStatsUid(), query, result);
}
}
- private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, Result result) {
- calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED, result);
+ private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
+ BatteryUsageStatsQuery query, Result result) {
+ calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED,
+ query.shouldForceUsePowerProfileModel(), result);
app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, result.durationMs)
@@ -112,7 +114,7 @@ public class CpuPowerCalculator extends PowerCalculator {
}
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, Result result) {
- calculatePowerAndDuration(u, statsType, result);
+ calculatePowerAndDuration(u, statsType, false, result);
app.cpuPowerMah = result.powerMah;
app.cpuTimeMs = result.durationMs;
@@ -120,46 +122,16 @@ public class CpuPowerCalculator extends PowerCalculator {
app.packageWithHighestDrain = result.packageWithHighestDrain;
}
- private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType, Result result) {
+ private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType,
+ boolean forceUsePowerProfileModel, Result result) {
long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
- // Constant battery drain when CPU is active
- double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime());
-
- // Additional per-cluster battery drain
- long[] cpuClusterTimes = u.getCpuClusterTimes();
- if (cpuClusterTimes != null) {
- if (cpuClusterTimes.length == mNumCpuClusters) {
- for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
- double power = calculatePerCpuClusterPowerMah(cluster,
- cpuClusterTimes[cluster]);
- powerMah += power;
- if (DEBUG) {
- Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster
- + " clusterTimeMs=" + cpuClusterTimes[cluster]
- + " power=" + formatCharge(power));
- }
- }
- } else {
- Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
- + mNumCpuClusters + " actual # " + cpuClusterTimes.length);
- }
- }
-
- // Additional per-frequency battery drain
- for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
- final int speedsForCluster = mPerCpuFreqPowerEstimators[cluster].length;
- for (int speed = 0; speed < speedsForCluster; speed++) {
- final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
- final double power = calculatePerCpuFreqPowerMah(cluster, speed,
- timeUs / 1000);
- if (DEBUG) {
- Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
- + speed + " timeUs=" + timeUs + " power="
- + formatCharge(power));
- }
- powerMah += power;
- }
+ final double powerMah;
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
+ if (forceUsePowerProfileModel || consumptionUC == BatteryStats.POWER_DATA_UNAVAILABLE) {
+ powerMah = calculateUidModeledPowerMah(u, statsType);
+ } else {
+ powerMah = uCtoMah(consumptionUC);
}
if (DEBUG && (durationMs != 0 || powerMah != 0)) {
@@ -208,6 +180,48 @@ public class CpuPowerCalculator extends PowerCalculator {
result.packageWithHighestDrain = packageWithHighestDrain;
}
+ private double calculateUidModeledPowerMah(BatteryStats.Uid u, int statsType) {
+ // Constant battery drain when CPU is active
+ double powerMah = calculateActiveCpuPowerMah(u.getCpuActiveTime());
+
+ // Additional per-cluster battery drain
+ long[] cpuClusterTimes = u.getCpuClusterTimes();
+ if (cpuClusterTimes != null) {
+ if (cpuClusterTimes.length == mNumCpuClusters) {
+ for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
+ double power = calculatePerCpuClusterPowerMah(cluster,
+ cpuClusterTimes[cluster]);
+ powerMah += power;
+ if (DEBUG) {
+ Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster
+ + " clusterTimeMs=" + cpuClusterTimes[cluster]
+ + " power=" + formatCharge(power));
+ }
+ }
+ } else {
+ Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
+ + mNumCpuClusters + " actual # " + cpuClusterTimes.length);
+ }
+ }
+
+ // Additional per-frequency battery drain
+ for (int cluster = 0; cluster < mNumCpuClusters; cluster++) {
+ final int speedsForCluster = mPerCpuFreqPowerEstimators[cluster].length;
+ for (int speed = 0; speed < speedsForCluster; speed++) {
+ final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
+ final double power = calculatePerCpuFreqPowerMah(cluster, speed,
+ timeUs / 1000);
+ if (DEBUG) {
+ Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
+ + speed + " timeUs=" + timeUs + " power="
+ + formatCharge(power));
+ }
+ powerMah += power;
+ }
+ }
+ return powerMah;
+ }
+
/**
* Calculates active CPU power consumption.
*
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 85114e59cc2d..b57b4b959334 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -72,5 +72,5 @@ oneway interface IPhoneStateListener {
void onBarringInfoChanged(in BarringInfo barringInfo);
void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs);
void onDataEnabledChanged(boolean enabled, int reason);
- void onAllowedNetworkTypesChanged(in Map allowedNetworkTypeList);
+ void onAllowedNetworkTypesChanged(in int reason, in long allowedNetworkType);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 95e0a3b524c5..83691ee64103 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -95,5 +95,5 @@ interface ITelephonyRegistry {
void notifyPhysicalChannelConfigForSubscriber(in int subId,
in List<PhysicalChannelConfig> configs);
void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason);
- void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in Map allowedNetworkTypeList);
+ void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in int reason, in long allowedNetworkType);
}
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 8d82e33dc29f..c33637353984 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -35,8 +35,7 @@ import com.android.internal.view.InlineSuggestionsRequestInfo;
* {@hide}
*/
oneway interface IInputMethod {
- void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps,
- int configChanges);
+ void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
in IInlineSuggestionsRequestCallback cb);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3bc0ef4ee3a0..94ac183517a2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -637,6 +637,12 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
char saveResolvedClassesDelayMsOptsBuf[
sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX];
+ char madviseWillNeedFileSizeVdex[
+ sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];
+ char madviseWillNeedFileSizeOdex[
+ sizeof("-XMadviseWillNeedOdexFileSize:")-1 + PROPERTY_VALUE_MAX];
+ char madviseWillNeedFileSizeArt[
+ sizeof("-XMadviseWillNeedArtFileSize:")-1 + PROPERTY_VALUE_MAX];
char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
@@ -845,6 +851,22 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:");
/*
+ * Use default platform configuration as limits for madvising,
+ * when no properties are specified.
+ */
+ parseRuntimeOption("dalvik.vm.madvise.vdexfile.size",
+ madviseWillNeedFileSizeVdex,
+ "-XMadviseWillNeedVdexFileSize:");
+
+ parseRuntimeOption("dalvik.vm.madvise.odexfile.size",
+ madviseWillNeedFileSizeOdex,
+ "-XMadviseWillNeedOdexFileSize:");
+
+ parseRuntimeOption("dalvik.vm.madvise.artfile.size",
+ madviseWillNeedFileSizeArt,
+ "-XMadviseWillNeedArtFileSize:");
+
+ /*
* Profile related options.
*/
parseRuntimeOption("dalvik.vm.hot-startup-method-samples", hotstartupsamplesOptsBuf,
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index f7b3f309ed12..2e4be145d54d 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -1509,7 +1509,9 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
res = JNI_TRUE;
} else {
jniThrowException(env, "java/util/NoSuchElementException",
- "Death link does not exist");
+ base::StringPrintf("Death link does not exist (%s)",
+ statusToString(err).c_str())
+ .c_str());
}
}
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index ebc507a8381e..469e577829d8 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -16,9 +16,10 @@
#include <android_runtime/AndroidRuntime.h>
-#include <input/KeyCharacterMap.h>
-#include <input/Input.h>
#include <binder/Parcel.h>
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <input/KeyCharacterMap.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
@@ -75,6 +76,10 @@ jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId,
reinterpret_cast<jlong>(nativeMap));
}
+static jobject nativeObtainEmptyKeyCharacterMap(JNIEnv* env, jobject /* clazz */, jint deviceId) {
+ return android_view_KeyCharacterMap_create(env, deviceId, nullptr);
+}
+
static jlong nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (!parcel) {
@@ -224,33 +229,37 @@ static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jlong ptr,
return result;
}
+static jboolean nativeEquals(JNIEnv* env, jobject clazz, jlong ptr1, jlong ptr2) {
+ const std::shared_ptr<KeyCharacterMap>& map1 =
+ (reinterpret_cast<NativeKeyCharacterMap*>(ptr1))->getMap();
+ const std::shared_ptr<KeyCharacterMap>& map2 =
+ (reinterpret_cast<NativeKeyCharacterMap*>(ptr2))->getMap();
+ if (map1 == nullptr || map2 == nullptr) {
+ return map1 == map2;
+ }
+ return static_cast<jboolean>(*map1 == *map2);
+}
/*
* JNI registration.
*/
static const JNINativeMethod g_methods[] = {
- /* name, signature, funcPtr */
- { "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
- (void*)nativeReadFromParcel },
- { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
- (void*)nativeWriteToParcel },
- { "nativeDispose", "(J)V",
- (void*)nativeDispose },
- { "nativeGetCharacter", "(JII)C",
- (void*)nativeGetCharacter },
- { "nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
- (void*)nativeGetFallbackAction },
- { "nativeGetNumber", "(JI)C",
- (void*)nativeGetNumber },
- { "nativeGetMatch", "(JI[CI)C",
- (void*)nativeGetMatch },
- { "nativeGetDisplayLabel", "(JI)C",
- (void*)nativeGetDisplayLabel },
- { "nativeGetKeyboardType", "(J)I",
- (void*)nativeGetKeyboardType },
- { "nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;",
- (void*)nativeGetEvents },
+ /* name, signature, funcPtr */
+ {"nativeReadFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeReadFromParcel},
+ {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel},
+ {"nativeDispose", "(J)V", (void*)nativeDispose},
+ {"nativeGetCharacter", "(JII)C", (void*)nativeGetCharacter},
+ {"nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
+ (void*)nativeGetFallbackAction},
+ {"nativeGetNumber", "(JI)C", (void*)nativeGetNumber},
+ {"nativeGetMatch", "(JI[CI)C", (void*)nativeGetMatch},
+ {"nativeGetDisplayLabel", "(JI)C", (void*)nativeGetDisplayLabel},
+ {"nativeGetKeyboardType", "(J)I", (void*)nativeGetKeyboardType},
+ {"nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;", (void*)nativeGetEvents},
+ {"nativeObtainEmptyKeyCharacterMap", "(I)Landroid/view/KeyCharacterMap;",
+ (void*)nativeObtainEmptyKeyCharacterMap},
+ {"nativeEquals", "(JJ)Z", (void*)nativeEquals},
};
int register_android_view_KeyCharacterMap(JNIEnv* env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 99ad6d100e55..f92276171b26 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5419,6 +5419,8 @@
intents}.
<p>Protection level: normal -->
<permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
+ android:label="@string/permlab_fullScreenIntent"
+ android:description="@string/permdesc_fullScreenIntent"
android:protectionLevel="normal" />
<!-- @SystemApi Allows requesting the framework broadcast the
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5412db623c85..6ebd8786b5f1 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3564,16 +3564,6 @@
<attr name="__removed2" format="boolean" />
<!-- Specifies whether the IME supports showing inline suggestions. -->
<attr name="supportsInlineSuggestions" format="boolean" />
- <!-- Specify one or more configuration changes that the IME will handle itself. If not
- specified, the IME will be restarted if any of these configuration changes happen in
- the system. Otherwise, the IME will remain running and its
- {@link android.inputmethodservice.InputMethodService#onConfigurationChanged}
- method is called with the new configuration.
- <p>Note that all of these configuration changes can impact the
- resource values seen by the application, so you will generally need
- to re-retrieve all resources (including view layouts, drawables, etc)
- to correctly handle any configuration change.-->
- <attr name="configChanges" />
</declare-styleable>
<!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 387c065175be..8d92c66764d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -889,6 +889,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_expandStatusBar">Allows the app to expand or collapse the status bar.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_fullScreenIntent">display notifications as full screen activities on a locked device</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_fullScreenIntent">Allows the app to display notifications as full screen activities on a locked device</string>
+
<!-- Title of an application permission, listed so the user can install application shortcuts
in their Launcher -->
<string name="permlab_install_shortcut">install shortcuts</string>
diff --git a/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java b/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java
deleted file mode 100644
index 4863cfe588ba..000000000000
--- a/core/tests/coretests/src/android/inputmethodservice/InputMethodServiceTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.inputmethodservice;
-
-import static android.content.res.Configuration.KEYBOARD_12KEY;
-import static android.content.res.Configuration.NAVIGATION_NONAV;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-
-import static junit.framework.Assert.assertFalse;
-
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.os.Build;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.rule.ServiceTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.TimeoutException;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class InputMethodServiceTest {
- private InputMethodService mService;
- private Context mContext;
- @Rule
- public final ServiceTestRule serviceRule = new ServiceTestRule();
-
- @Before
- public void setUp() throws TimeoutException {
- mContext = getInstrumentation().getContext();
- mService = new InputMethodService();
- }
-
- @Test
- public void testShouldImeRestartForConfig() throws Exception {
- // Make sure we preserve Pre-S behavior i.e. Service restarts.
- mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.R;
- Configuration config = mContext.getResources().getConfiguration();
- mService.setLastKnownConfig(config);
- assertTrue("IME should restart for Pre-S",
- mService.shouldImeRestartForConfig(config));
-
- // IME shouldn't restart on targetSdk S+ (with no config changes).
- mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.S;
- assertFalse("IME shouldn't restart for S+",
- mService.shouldImeRestartForConfig(config));
-
- // Screen density changed but IME doesn't handle congfigChanges
- config.densityDpi = 99;
- assertTrue("IME should restart for unhandled configChanges",
- mService.shouldImeRestartForConfig(config));
-
- // opt-in IME to handle config changes.
- mService.setHandledConfigChanges(ActivityInfo.CONFIG_DENSITY);
- assertFalse("IME shouldn't restart for S+ since it handles configChanges",
- mService.shouldImeRestartForConfig(config));
- }
-}
diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java
index c06405affc1b..09c36dd261bd 100644
--- a/core/tests/coretests/src/android/os/VibratorInfoTest.java
+++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java
@@ -16,9 +16,10 @@
package android.os;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import android.hardware.vibrator.IVibrator;
import android.platform.test.annotations.Presubmit;
@@ -33,72 +34,128 @@ public class VibratorInfoTest {
@Test
public void testHasAmplitudeControl() {
- assertFalse(createInfo(/* capabilities= */ 0).hasAmplitudeControl());
- assertTrue(createInfo(IVibrator.CAP_COMPOSE_EFFECTS
- | IVibrator.CAP_AMPLITUDE_CONTROL).hasAmplitudeControl());
+ VibratorInfo noCapabilities = new InfoBuilder().build();
+ assertFalse(noCapabilities.hasAmplitudeControl());
+ VibratorInfo composeAndAmplitudeControl = new InfoBuilder()
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS
+ | IVibrator.CAP_AMPLITUDE_CONTROL)
+ .build();
+ assertTrue(composeAndAmplitudeControl.hasAmplitudeControl());
}
@Test
public void testHasCapabilities() {
- assertTrue(createInfo(IVibrator.CAP_COMPOSE_EFFECTS)
- .hasCapability(IVibrator.CAP_COMPOSE_EFFECTS));
- assertFalse(createInfo(IVibrator.CAP_COMPOSE_EFFECTS)
- .hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL));
+ VibratorInfo info = new InfoBuilder()
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .build();
+ assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS));
+ assertFalse(info.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL));
}
@Test
public void testIsEffectSupported() {
- VibratorInfo info = new VibratorInfo(/* id= */ 0, /* capabilities= */0,
- new int[]{VibrationEffect.EFFECT_CLICK}, null);
+ VibratorInfo noEffects = new InfoBuilder().build();
+ VibratorInfo canClick = new InfoBuilder()
+ .setSupportedEffects(VibrationEffect.EFFECT_CLICK)
+ .build();
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN,
- createInfo(/* capabilities= */ 0).isEffectSupported(VibrationEffect.EFFECT_CLICK));
+ noEffects.isEffectSupported(VibrationEffect.EFFECT_CLICK));
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES,
- info.isEffectSupported(VibrationEffect.EFFECT_CLICK));
+ canClick.isEffectSupported(VibrationEffect.EFFECT_CLICK));
assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO,
- info.isEffectSupported(VibrationEffect.EFFECT_TICK));
+ canClick.isEffectSupported(VibrationEffect.EFFECT_TICK));
}
@Test
public void testIsPrimitiveSupported() {
- VibratorInfo info = new VibratorInfo(/* id= */ 0, IVibrator.CAP_COMPOSE_EFFECTS,
- null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+ VibratorInfo info = new InfoBuilder()
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .build();
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
// Returns false when there is no compose capability.
- info = new VibratorInfo(/* id= */ 0, /* capabilities= */ 0,
- null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+ info = new InfoBuilder()
+ .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .build();
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
}
@Test
public void testEquals() {
- VibratorInfo empty = new VibratorInfo(1, 0, null, null);
- VibratorInfo complete = new VibratorInfo(1, IVibrator.CAP_AMPLITUDE_CONTROL,
- new int[]{VibrationEffect.EFFECT_CLICK},
- new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK});
+ InfoBuilder completeBuilder = new InfoBuilder()
+ .setId(1)
+ .setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
+ .setSupportedEffects(VibrationEffect.EFFECT_CLICK)
+ .setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .setQFactor(2f)
+ .setResonantFrequency(150f);
+ VibratorInfo complete = completeBuilder.build();
assertEquals(complete, complete);
- assertEquals(complete, new VibratorInfo(1, IVibrator.CAP_AMPLITUDE_CONTROL,
- new int[]{VibrationEffect.EFFECT_CLICK},
- new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}));
-
- assertFalse(empty.equals(new VibratorInfo(1, 0, new int[]{}, new int[]{})));
- assertFalse(complete.equals(new VibratorInfo(1, IVibrator.CAP_COMPOSE_EFFECTS,
- new int[]{VibrationEffect.EFFECT_CLICK},
- new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
- assertFalse(complete.equals(new VibratorInfo(1, IVibrator.CAP_AMPLITUDE_CONTROL,
- new int[]{}, new int[]{})));
- assertFalse(complete.equals(new VibratorInfo(1, IVibrator.CAP_AMPLITUDE_CONTROL,
- null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})));
- assertFalse(complete.equals(new VibratorInfo(1, IVibrator.CAP_AMPLITUDE_CONTROL,
- new int[]{VibrationEffect.EFFECT_CLICK}, null)));
+ assertEquals(complete, completeBuilder.build());
+
+ VibratorInfo completeWithComposeControl = completeBuilder
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .build();
+ assertNotEquals(complete, completeWithComposeControl);
+
+ VibratorInfo completeWithNoEffects = completeBuilder
+ .setSupportedEffects()
+ .setSupportedPrimitives()
+ .build();
+ assertNotEquals(complete, completeWithNoEffects);
+
+ VibratorInfo completeWithUnknownEffects = completeBuilder
+ .setSupportedEffects(null)
+ .build();
+ assertNotEquals(complete, completeWithNoEffects);
+
+ VibratorInfo completeWithUnknownPrimitives = completeBuilder
+ .setSupportedPrimitives(null)
+ .build();
+ assertNotEquals(complete, completeWithUnknownPrimitives);
+
+ VibratorInfo completeWithDifferentF0 = completeBuilder
+ .setResonantFrequency(complete.getResonantFrequency() + 3f)
+ .build();
+ assertNotEquals(complete, completeWithDifferentF0);
+
+ VibratorInfo completeWithUnknownF0 = completeBuilder
+ .setResonantFrequency(Float.NaN)
+ .build();
+ assertNotEquals(complete, completeWithUnknownF0);
+
+ VibratorInfo completeWithUnknownQFactor = completeBuilder
+ .setQFactor(Float.NaN)
+ .build();
+ assertNotEquals(complete, completeWithUnknownQFactor);
+
+ VibratorInfo completeWithDifferentQFactor = completeBuilder
+ .setQFactor(complete.getQFactor() + 3f)
+ .build();
+ assertNotEquals(complete, completeWithDifferentQFactor);
+
+ VibratorInfo empty = new InfoBuilder().setId(1).build();
+ VibratorInfo emptyWithKnownSupport = new InfoBuilder()
+ .setId(1)
+ .setSupportedEffects()
+ .setSupportedPrimitives()
+ .build();
+ assertNotEquals(empty, emptyWithKnownSupport);
}
@Test
- public void testSerialization() {
- VibratorInfo original = new VibratorInfo(1, IVibrator.CAP_COMPOSE_EFFECTS,
- new int[]{VibrationEffect.EFFECT_CLICK}, null);
+ public void testParceling() {
+ VibratorInfo original = new InfoBuilder()
+ .setId(1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedEffects(VibrationEffect.EFFECT_CLICK)
+ .setSupportedPrimitives(null)
+ .setResonantFrequency(1.3f)
+ .setQFactor(Float.NaN)
+ .build();
Parcel parcel = Parcel.obtain();
original.writeToParcel(parcel, 0);
@@ -107,7 +164,47 @@ public class VibratorInfoTest {
assertEquals(original, restored);
}
- private static VibratorInfo createInfo(long capabilities) {
- return new VibratorInfo(/* id= */ 0, capabilities, null, null);
+ private static class InfoBuilder {
+ private int mId = 0;
+ private int mCapabilities = 0;
+ private int[] mSupportedEffects = null;
+ private int[] mSupportedPrimitives = null;
+ private float mResonantFrequency = Float.NaN;
+ private float mQFactor = Float.NaN;
+
+ public InfoBuilder setId(int id) {
+ mId = id;
+ return this;
+ }
+
+ public InfoBuilder setCapabilities(int capabilities) {
+ mCapabilities = capabilities;
+ return this;
+ }
+
+ public InfoBuilder setSupportedEffects(int... supportedEffects) {
+ mSupportedEffects = supportedEffects;
+ return this;
+ }
+
+ public InfoBuilder setSupportedPrimitives(int... supportedPrimitives) {
+ mSupportedPrimitives = supportedPrimitives;
+ return this;
+ }
+
+ public InfoBuilder setResonantFrequency(float resonantFrequency) {
+ mResonantFrequency = resonantFrequency;
+ return this;
+ }
+
+ public InfoBuilder setQFactor(float qFactor) {
+ mQFactor = qFactor;
+ return this;
+ }
+
+ public VibratorInfo build() {
+ return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives,
+ mResonantFrequency, mQFactor);
+ }
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
index 70888905d7c8..10ff3a47a7d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
@@ -19,18 +19,22 @@ package com.android.internal.os;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.os.BatteryConsumer;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.power.MeasuredEnergyStats;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -81,6 +85,10 @@ public class CpuPowerCalculatorTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
+ final boolean[] supportedPowerBuckets =
+ new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
+ supportedPowerBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true;
+
mStatsRule.getBatteryStats()
.setUserInfoProvider(mMockUserInfoProvider)
.setKernelCpuSpeedReaders(mMockKernelCpuSpeedReaders)
@@ -88,7 +96,8 @@ public class CpuPowerCalculatorTest {
.setKernelCpuUidClusterTimeReader(mMockKernelCpuUidClusterTimeReader)
.setKernelCpuUidUserSysTimeReader(mMockKernelCpuUidUserSysTimeReader)
.setKernelCpuUidActiveTimeReader(mMockKerneCpuUidActiveTimeReader)
- .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader);
+ .setSystemServerCpuThreadReader(mMockSystemServerCpuThreadReader)
+ .initMeasuredEnergyStatsLocked(supportedPowerBuckets, 0);
}
@Test
@@ -103,28 +112,28 @@ public class CpuPowerCalculatorTest {
// User/System CPU time
doAnswer(invocation -> {
- final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0);
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
// User/system time in microseconds
callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000});
callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000});
return null;
- }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(any());
+ }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any());
// Active CPU time
doAnswer(invocation -> {
- final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(0);
+ final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1);
callback.onUidCpuTime(APP_UID1, 1111L);
callback.onUidCpuTime(APP_UID2, 3333L);
return null;
- }).when(mMockKerneCpuUidActiveTimeReader).readDelta(any());
+ }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any());
// Per-cluster CPU time
doAnswer(invocation -> {
- final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(0);
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222});
callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444});
return null;
- }).when(mMockKernelCpuUidClusterTimeReader).readDelta(any());
+ }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any());
mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, null);
@@ -134,7 +143,8 @@ public class CpuPowerCalculatorTest {
CpuPowerCalculator calculator =
new CpuPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ calculator);
UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU))
@@ -150,4 +160,64 @@ public class CpuPowerCalculatorTest {
.isWithin(PRECISION).of(2.672322);
assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull();
}
+
+ @Test
+ public void testMeasuredEnergyBasedModel() {
+ when(mMockUserInfoProvider.exists(anyInt())).thenReturn(true);
+
+ when(mMockKernelCpuSpeedReaders[0].readDelta()).thenReturn(new long[]{1000, 2000});
+ when(mMockKernelCpuSpeedReaders[1].readDelta()).thenReturn(new long[]{3000, 4000});
+
+ when(mMockCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(false);
+
+ // User/System CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ // User/system time in microseconds
+ callback.onUidCpuTime(APP_UID1, new long[]{1111000, 2222000});
+ callback.onUidCpuTime(APP_UID2, new long[]{3333000, 4444000});
+ return null;
+ }).when(mMockKernelCpuUidUserSysTimeReader).readDelta(anyBoolean(), any());
+
+ // Active CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<Long> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, 1111L);
+ callback.onUidCpuTime(APP_UID2, 3333L);
+ return null;
+ }).when(mMockKerneCpuUidActiveTimeReader).readDelta(anyBoolean(), any());
+
+ // Per-cluster CPU time
+ doAnswer(invocation -> {
+ final KernelCpuUidTimeReader.Callback<long[]> callback = invocation.getArgument(1);
+ callback.onUidCpuTime(APP_UID1, new long[]{1111, 2222});
+ callback.onUidCpuTime(APP_UID2, new long[]{3333, 4444});
+ return null;
+ }).when(mMockKernelCpuUidClusterTimeReader).readDelta(anyBoolean(), any());
+
+ final long[] clusterChargesUC = new long[]{13577531, 24688642};
+ mStatsRule.getBatteryStats().updateCpuTimeLocked(true, true, clusterChargesUC);
+
+ mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("foo").addCpuTimeLocked(4321, 1234);
+ mStatsRule.getUidStats(APP_UID1).getProcessStatsLocked("bar").addCpuTimeLocked(5432, 2345);
+
+ CpuPowerCalculator calculator =
+ new CpuPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(calculator);
+
+ UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
+ assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU))
+ .isEqualTo(3333);
+ assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isWithin(PRECISION).of(3.18877);
+ assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar");
+
+ UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+ assertThat(uidConsumer2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU))
+ .isEqualTo(7777);
+ assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isWithin(PRECISION).of(7.44072);
+ assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull();
+ }
}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 77a38a9bb1a0..b3a180d70fe2 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -154,6 +154,7 @@
<assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="media" />
<assign-permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" uid="media" />
+ <assign-permission name="android.permission.REGISTER_STATS_PULL_ATOM" uid="media" />
<assign-permission name="android.permission.INTERNET" uid="media" />
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 55015696ff47..35b1c169f283 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -121,4 +121,22 @@ public class AndroidKeyStoreMaintenance {
return SYSTEM_ERROR;
}
}
+
+ /**
+ * Queries user state from Keystore 2.0.
+ *
+ * @param userId - Android user id of the user.
+ * @return UserState enum variant as integer if successful or an error
+ */
+ public static int getState(int userId) {
+ try {
+ return getService().getState(userId);
+ } catch (ServiceSpecificException e) {
+ Log.e(TAG, "getState failed", e);
+ return e.errorCode;
+ } catch (Exception e) {
+ Log.e(TAG, "Can not connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 93658e69eac8..937f01ce3767 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -43,6 +43,7 @@ import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeystoreResponse;
import android.security.keystore.UserNotAuthenticatedException;
+import android.security.maintenance.UserState;
import android.system.keystore2.Domain;
import android.util.Log;
@@ -196,6 +197,19 @@ public class KeyStore {
public State state(int userId) {
final int ret;
try {
+ if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) {
+ int userState = AndroidKeyStoreMaintenance.getState(userId);
+ switch (userState) {
+ case UserState.UNINITIALIZED:
+ return KeyStore.State.UNINITIALIZED;
+ case UserState.LSKF_UNLOCKED:
+ return KeyStore.State.UNLOCKED;
+ case UserState.LSKF_LOCKED:
+ return KeyStore.State.LOCKED;
+ default:
+ throw new AssertionError(KeyStore.VALUE_CORRUPTED);
+ }
+ }
ret = mBinder.getState(userId);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 1b5dc8bdbcaa..3f03302de474 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -38,6 +38,14 @@ filegroup {
path: "src",
}
+filegroup {
+ name: "wm_shell-aidls",
+ srcs: [
+ "src/**/*.aidl",
+ ],
+ path: "src",
+}
+
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
filegroup {
name: "wm_shell-sources-kt",
@@ -98,7 +106,7 @@ android_library {
":wm_shell_protolog_src",
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
":wm_shell-sources-kt",
- "src/**/I*.aidl",
+ ":wm_shell-aidls",
],
resource_dirs: [
"res",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index eaed24d6195a..d451f4a0661b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -47,21 +47,7 @@ public final class ShellCommandHandlerImpl {
private final ShellExecutor mMainExecutor;
private final HandlerImpl mImpl = new HandlerImpl();
- public static ShellCommandHandler create(
- ShellTaskOrganizer shellTaskOrganizer,
- Optional<LegacySplitScreenController> legacySplitScreenOptional,
- Optional<SplitScreenController> splitScreenOptional,
- Optional<Pip> pipOptional,
- Optional<OneHandedController> oneHandedOptional,
- Optional<HideDisplayCutoutController> hideDisplayCutout,
- Optional<AppPairsController> appPairsOptional,
- ShellExecutor mainExecutor) {
- return new ShellCommandHandlerImpl(shellTaskOrganizer, legacySplitScreenOptional,
- splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
- appPairsOptional, mainExecutor).mImpl;
- }
-
- private ShellCommandHandlerImpl(
+ public ShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
@@ -80,6 +66,10 @@ public final class ShellCommandHandlerImpl {
mMainExecutor = mainExecutor;
}
+ public ShellCommandHandler asShellCommandHandler() {
+ return mImpl;
+ }
+
/** Dumps WM Shell internal state. */
private void dump(PrintWriter pw) {
mShellTaskOrganizer.dump(pw, "");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 85bd24c1c2bf..6f4550c2a89e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -26,7 +26,7 @@ import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -47,44 +47,20 @@ public class ShellInitImpl {
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
- private final Optional<StartingSurface> mStartingSurfaceOptional;
+ private final StartingWindowController mStartingWindow;
private final InitImpl mImpl = new InitImpl();
- public static ShellInit create(DisplayImeController displayImeController,
+ public ShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurfaceOptional,
- Optional<PipTouchHandler> pipTouchHandlerOptional,
- FullscreenTaskListener fullscreenTaskListener,
- Transitions transitions,
- ShellExecutor mainExecutor) {
- return new ShellInitImpl(displayImeController,
- dragAndDropController,
- shellTaskOrganizer,
- legacySplitScreenOptional,
- splitScreenOptional,
- appPairsOptional,
- startingSurfaceOptional,
- pipTouchHandlerOptional,
- fullscreenTaskListener,
- transitions,
- mainExecutor).mImpl;
- }
-
- private ShellInitImpl(DisplayImeController displayImeController,
- DragAndDropController dragAndDropController,
- ShellTaskOrganizer shellTaskOrganizer,
- Optional<LegacySplitScreenController> legacySplitScreenOptional,
- Optional<SplitScreenController> splitScreenOptional,
- Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurfaceOptional,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
+ StartingWindowController startingWindow,
ShellExecutor mainExecutor) {
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
@@ -96,17 +72,21 @@ public class ShellInitImpl {
mPipTouchHandlerOptional = pipTouchHandlerOptional;
mTransitions = transitions;
mMainExecutor = mainExecutor;
- mStartingSurfaceOptional = startingSurfaceOptional;
+ mStartingWindow = startingWindow;
+ }
+
+ public ShellInit asShellInit() {
+ return mImpl;
}
private void init() {
// Start listening for display changes
mDisplayImeController.startMonitorDisplays();
+ // Setup the shell organizer
mShellTaskOrganizer.addListenerForType(
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
- mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface);
- // Register the shell organizer
+ mShellTaskOrganizer.initStartingWindow(mStartingWindow);
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index fcb53cd890b7..94d13eab4299 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -48,7 +48,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.wm.shell.startingsurface.StartingWindowController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -133,7 +133,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>();
private final Object mLock = new Object();
- private StartingSurface mStartingSurface;
+ private StartingWindowController mStartingWindow;
/**
* In charge of showing size compat UI. Can be {@code null} if device doesn't support size
@@ -184,8 +184,8 @@ public class ShellTaskOrganizer extends TaskOrganizer {
/**
* @hide
*/
- public void initStartingSurface(StartingSurface startingSurface) {
- mStartingSurface = startingSurface;
+ public void initStartingWindow(StartingWindowController startingWindow) {
+ mStartingWindow = startingWindow;
}
/**
@@ -302,23 +302,23 @@ public class ShellTaskOrganizer extends TaskOrganizer {
@Override
public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
- if (mStartingSurface != null) {
- mStartingSurface.addStartingWindow(info, appToken);
+ if (mStartingWindow != null) {
+ mStartingWindow.addStartingWindow(info, appToken);
}
}
@Override
public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
boolean playRevealAnimation) {
- if (mStartingSurface != null) {
- mStartingSurface.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ if (mStartingWindow != null) {
+ mStartingWindow.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
}
}
@Override
public void copySplashScreenView(int taskId) {
- if (mStartingSurface != null) {
- mStartingSurface.copySplashScreenView(taskId);
+ if (mStartingWindow != null) {
+ mStartingWindow.copySplashScreenView(taskId);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java
new file mode 100644
index 000000000000..b29058b1f204
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ExecutorUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.Manifest;
+import android.util.Slog;
+
+import java.util.function.Consumer;
+
+/**
+ * Helpers for working with executors
+ */
+public class ExecutorUtils {
+
+ /**
+ * Checks that the caller has the MANAGE_ACTIVITY_TASKS permission and executes the given
+ * callback.
+ */
+ public static <T> void executeRemoteCallWithTaskPermission(RemoteCallable<T> controllerInstance,
+ String log, Consumer<T> callback) {
+ executeRemoteCallWithTaskPermission(controllerInstance, log, callback,
+ false /* blocking */);
+ }
+
+ /**
+ * Checks that the caller has the MANAGE_ACTIVITY_TASKS permission and executes the given
+ * callback.
+ */
+ public static <T> void executeRemoteCallWithTaskPermission(RemoteCallable<T> controllerInstance,
+ String log, Consumer<T> callback, boolean blocking) {
+ if (controllerInstance == null) return;
+
+ final RemoteCallable<T> controller = controllerInstance;
+ controllerInstance.getContext().enforceCallingPermission(
+ Manifest.permission.MANAGE_ACTIVITY_TASKS, log);
+ if (blocking) {
+ try {
+ controllerInstance.getRemoteCallExecutor().executeBlocking(() -> {
+ callback.accept((T) controller);
+ });
+ } catch (InterruptedException e) {
+ Slog.e("ExecutorUtils", "Remote call failed", e);
+ }
+ } else {
+ controllerInstance.getRemoteCallExecutor().execute(() -> {
+ callback.accept((T) controller);
+ });
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java
new file mode 100644
index 000000000000..30f535ba940c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/RemoteCallable.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.content.Context;
+
+/**
+ * An interface for controllers that can receive remote calls.
+ */
+public interface RemoteCallable<T> {
+ /**
+ * Returns a context used for permission checking.
+ */
+ Context getContext();
+
+ /**
+ * Returns the executor to post the handler callback to.
+ */
+ ShellExecutor getRemoteCallExecutor();
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index aab2334f8255..9a09ca43d1d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -235,7 +235,7 @@ public class DragAndDropPolicy {
mStarter.startShortcut(packageName, id, stage, position, opts, user);
} else {
mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT),
- mContext, null, stage, position, opts);
+ null, stage, position, opts);
}
}
@@ -295,7 +295,7 @@ public class DragAndDropPolicy {
@Nullable Bundle options);
void startShortcut(String packageName, String shortcutId, @StageType int stage,
@StagePosition int position, @Nullable Bundle options, UserHandle user);
- void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
+ void startIntent(PendingIntent intent, Intent fillInIntent,
@StageType int stage, @StagePosition int position,
@Nullable Bundle options);
void enterSplitScreen(int taskId, boolean leftOrTop);
@@ -337,9 +337,8 @@ public class DragAndDropPolicy {
}
@Override
- public void startIntent(PendingIntent intent, Context context,
- @Nullable Intent fillInIntent, int stage, int position,
- @Nullable Bundle options) {
+ public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, int stage,
+ int position, @Nullable Bundle options) {
try {
intent.send(mContext, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl
new file mode 100644
index 000000000000..008b5087d7da
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/IOneHanded.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.onehanded;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the OneHanded feature.
+ */
+interface IOneHanded {
+
+ /**
+ * Enters one handed mode.
+ */
+ oneway void startOneHanded() = 1;
+
+ /**
+ * Exits one handed mode.
+ */
+ oneway void stopOneHanded() = 2;
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 4f31c370108d..a7e9a0135de0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -26,6 +26,14 @@ import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEv
*/
@ExternalThread
public interface OneHanded {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate OneHanded.
+ */
+ default IOneHanded createExternalInterface() {
+ return null;
+ }
+
/**
* Return one handed settings enabled or not.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 5fc7c987899f..8022c1b6e047 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -18,6 +18,10 @@ package com.android.wm.shell.onehanded;
import static android.os.UserHandle.USER_CURRENT;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
+import android.Manifest;
+import android.annotation.BinderThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.om.IOverlayManager;
@@ -43,6 +47,8 @@ import com.android.internal.logging.UiEventLogger;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ExecutorUtils;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
@@ -54,7 +60,7 @@ import java.io.PrintWriter;
/**
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
-public class OneHandedController {
+public class OneHandedController implements RemoteCallable<OneHandedController> {
private static final String TAG = "OneHandedController";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
@@ -239,6 +245,16 @@ public class OneHandedController {
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
/**
* Set one handed enabled or disabled when user update settings
*/
@@ -567,8 +583,22 @@ public class OneHandedController {
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
@ExternalThread
private class OneHandedImpl implements OneHanded {
+ private IOneHandedImpl mIOneHanded;
+
+ @Override
+ public IOneHanded createExternalInterface() {
+ if (mIOneHanded != null) {
+ mIOneHanded.invalidate();
+ }
+ mIOneHanded = new IOneHandedImpl(OneHandedController.this);
+ return mIOneHanded;
+ }
+
@Override
public boolean isOneHandedEnabled() {
// This is volatile so return directly
@@ -637,4 +667,39 @@ public class OneHandedController {
});
}
}
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IOneHandedImpl extends IOneHanded.Stub {
+ private OneHandedController mController;
+
+ IOneHandedImpl(OneHandedController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
+ }
+
+ @Override
+ public void startOneHanded() {
+ executeRemoteCallWithTaskPermission(mController, "startOneHanded",
+ (controller) -> {
+ controller.startOneHanded();
+ });
+ }
+
+ @Override
+ public void stopOneHanded() {
+ executeRemoteCallWithTaskPermission(mController, "stopOneHanded",
+ (controller) -> {
+ controller.stopOneHanded();
+ });
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
new file mode 100644
index 000000000000..a6ffa6e44584
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip;
+
+import android.app.PictureInPictureParams;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+
+import com.android.wm.shell.pip.IPipAnimationListener;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the Pip feature.
+ */
+interface IPip {
+
+ /**
+ * Notifies that Activity is about to be swiped to home with entering PiP transition and
+ * queries the destination bounds for PiP depends on Launcher's rotation and shelf height.
+ *
+ * @param componentName ComponentName represents the Activity
+ * @param activityInfo ActivityInfo tied to the Activity
+ * @param pictureInPictureParams PictureInPictureParams tied to the Activity
+ * @param launcherRotation Launcher rotation to calculate the PiP destination bounds
+ * @param shelfHeight Shelf height of launcher to calculate the PiP destination bounds
+ * @return destination bounds the PiP window should land into
+ */
+ Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo,
+ in PictureInPictureParams pictureInPictureParams,
+ int launcherRotation, int shelfHeight) = 1;
+
+ /**
+ * Notifies the swiping Activity to PiP onto home transition is finished
+ *
+ * @param componentName ComponentName represents the Activity
+ * @param destinationBounds the destination bounds the PiP window lands into
+ */
+ oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds) = 2;
+
+ /**
+ * Sets listener to get pinned stack animation callbacks.
+ */
+ oneway void setPinnedStackAnimationListener(IPipAnimationListener listener) = 3;
+
+ /**
+ * Sets the shelf height and visibility.
+ */
+ oneway void setShelfHeight(boolean visible, int shelfHeight) = 4;
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
index 97aa512ea7df..2569b780c1bb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IPinnedStackAnimationListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.pip;
/**
- * Listener interface that Launcher attaches to SystemUI to get
- * pinned stack animation callbacks.
+ * Listener interface that Launcher attaches to SystemUI to get Pip animation callbacks.
*/
-oneway interface IPinnedStackAnimationListener {
+oneway interface IPipAnimationListener {
/**
- * Notifies the pinned stack animation is started.
+ * Notifies the listener that the Pip animation is started.
*/
- void onPinnedStackAnimationStarted();
+ void onPipAnimationStarted();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index d14c3e3c0dd4..6d4773bdeb1f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -16,15 +16,10 @@
package com.android.wm.shell.pip;
-import android.annotation.Nullable;
-import android.app.PictureInPictureParams;
-import android.content.ComponentName;
-import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import com.android.wm.shell.common.annotations.ExternalThread;
-import com.android.wm.shell.pip.phone.PipTouchHandler;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -34,6 +29,14 @@ import java.util.function.Consumer;
*/
@ExternalThread
public interface Pip {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate PIP.
+ */
+ default IPip createExternalInterface() {
+ return null;
+ }
+
/**
* Expand PIP, it's possible that specific request to activate the window via Alt-tab.
*/
@@ -109,30 +112,6 @@ public interface Pip {
default void showPictureInPictureMenu() {}
/**
- * Called by Launcher when swiping an auto-pip enabled Activity to home starts
- * @param componentName {@link ComponentName} represents the Activity entering PiP
- * @param activityInfo {@link ActivityInfo} tied to the Activity
- * @param pictureInPictureParams {@link PictureInPictureParams} tied to the Activity
- * @param launcherRotation Rotation Launcher is in
- * @param shelfHeight Shelf height when landing PiP window onto Launcher
- * @return Destination bounds of PiP window based on the parameters passed in
- */
- default Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) {
- return null;
- }
-
- /**
- * Called by Launcher when swiping an auto-pip enable Activity to home finishes
- * @param componentName {@link ComponentName} represents the Activity entering PiP
- * @param destinationBounds Destination bounds of PiP window
- */
- default void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- return;
- }
-
- /**
* Called by NavigationBar in order to listen in for PiP bounds change. This is mostly used
* for times where the PiP bounds could conflict with SystemUI elements, such as a stashed
* PiP and the Back-from-Edge gesture.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 9a584c67f97c..501b90ea6828 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -21,8 +21,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
+import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
@@ -33,6 +35,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -44,6 +47,7 @@ import android.view.DisplayInfo;
import android.view.WindowManagerGlobal;
import android.window.WindowContainerTransaction;
+import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -51,9 +55,13 @@ import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ExecutorUtils;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.pip.IPip;
+import com.android.wm.shell.pip.IPipAnimationListener;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
@@ -71,7 +79,8 @@ import java.util.function.Consumer;
/**
* Manages the picture-in-picture (PIP) UI and states for Phones.
*/
-public class PipController implements PipTransitionController.PipTransitionCallback {
+public class PipController implements PipTransitionController.PipTransitionCallback,
+ RemoteCallable<PipController> {
private static final String TAG = "PipController";
private Context mContext;
@@ -85,12 +94,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private PipBoundsState mPipBoundsState;
private PipTouchHandler mTouchHandler;
private PipTransitionController mPipTransitionController;
- protected final PipImpl mImpl = new PipImpl();
+ protected final PipImpl mImpl;
private final Rect mTmpInsetBounds = new Rect();
private boolean mIsInFixedRotation;
- private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
+ private IPipAnimationListener mPinnedStackAnimationRecentsCallback;
protected PhonePipMenuController mMenuController;
protected PipTaskOrganizer mPipTaskOrganizer;
@@ -264,6 +273,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
mContext = context;
+ mImpl = new PipImpl();
mWindowManagerShellWrapper = windowManagerShellWrapper;
mDisplayController = displayController;
mPipBoundsAlgorithm = pipBoundsAlgorithm;
@@ -366,6 +376,16 @@ public class PipController implements PipTransitionController.PipTransitionCallb
});
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
private void onConfigurationChanged(Configuration newConfig) {
mPipBoundsAlgorithm.onConfigurationChanged(mContext);
mTouchHandler.onConfigurationChanged();
@@ -474,7 +494,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mPipTaskOrganizer.setOneShotAnimationType(animationType);
}
- private void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
+ private void setPinnedStackAnimationListener(IPipAnimationListener callback) {
mPinnedStackAnimationRecentsCallback = callback;
}
@@ -512,7 +532,11 @@ public class PipController implements PipTransitionController.PipTransitionCallb
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
if (mPinnedStackAnimationRecentsCallback != null) {
- mPinnedStackAnimationRecentsCallback.accept(true);
+ try {
+ mPinnedStackAnimationRecentsCallback.onPipAnimationStarted();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call onPinnedStackAnimationStarted()", e);
+ }
}
}
@@ -638,7 +662,21 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mPipInputConsumer.dump(pw, innerPrefix);
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
private class PipImpl implements Pip {
+ private IPipImpl mIPip;
+
+ @Override
+ public IPip createExternalInterface() {
+ if (mIPip != null) {
+ mIPip.invalidate();
+ }
+ mIPip = new IPipImpl(PipController.this);
+ return mIPip;
+ }
+
@Override
public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
mMainExecutor.execute(() -> {
@@ -696,13 +734,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public void setPinnedStackAnimationListener(Consumer<Boolean> callback) {
- mMainExecutor.execute(() -> {
- PipController.this.setPinnedStackAnimationListener(callback);
- });
- }
-
- @Override
public void setPinnedStackAnimationType(int animationType) {
mMainExecutor.execute(() -> {
PipController.this.setPinnedStackAnimationType(animationType);
@@ -724,37 +755,99 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams, int launcherRotation,
- int shelfHeight) {
- Rect[] result = new Rect[1];
+ public void dump(PrintWriter pw) {
try {
mMainExecutor.executeBlocking(() -> {
- result[0] = PipController.this.startSwipePipToHome(componentName, activityInfo,
- pictureInPictureParams, launcherRotation, shelfHeight);
+ PipController.this.dump(pw);
});
} catch (InterruptedException e) {
- Slog.e(TAG, "Failed to start swipe pip to home");
+ Slog.e(TAG, "Failed to dump PipController in 2s");
}
+ }
+ }
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IPipImpl extends IPip.Stub {
+ private PipController mController;
+ private IPipAnimationListener mListener;
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final PipController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.setPinnedStackAnimationListener(null);
+ });
+ }
+ };
+
+ IPipImpl(PipController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
+ }
+
+ @Override
+ public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
+ PictureInPictureParams pictureInPictureParams, int launcherRotation,
+ int shelfHeight) {
+ Rect[] result = new Rect[1];
+ executeRemoteCallWithTaskPermission(mController, "startSwipePipToHome",
+ (controller) -> {
+ result[0] = controller.startSwipePipToHome(componentName, activityInfo,
+ pictureInPictureParams, launcherRotation, shelfHeight);
+ }, true /* blocking */);
return result[0];
}
@Override
public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- mMainExecutor.execute(() -> {
- PipController.this.stopSwipePipToHome(componentName, destinationBounds);
- });
+ executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome",
+ (controller) -> {
+ controller.stopSwipePipToHome(componentName, destinationBounds);
+ });
}
@Override
- public void dump(PrintWriter pw) {
- try {
- mMainExecutor.executeBlocking(() -> {
- PipController.this.dump(pw);
- });
- } catch (InterruptedException e) {
- Slog.e(TAG, "Failed to dump PipController in 2s");
- }
+ public void setShelfHeight(boolean visible, int height) {
+ executeRemoteCallWithTaskPermission(mController, "setShelfHeight",
+ (controller) -> {
+ controller.setShelfHeight(visible, height);
+ });
+ }
+
+ @Override
+ public void setPinnedStackAnimationListener(IPipAnimationListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "setPinnedStackAnimationListener",
+ (controller) -> {
+ if (mListener != null) {
+ // Reset the old death recipient
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ // Register the death recipient for the new listener to clear the listener
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.setPinnedStackAnimationListener(listener);
+ });
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
new file mode 100644
index 000000000000..0c46eaba18ae
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the splitscreen feature.
+ */
+interface ISplitScreen {
+
+ /**
+ * Registers a split screen listener.
+ */
+ oneway void registerSplitScreenListener(in ISplitScreenListener listener) = 1;
+
+ /**
+ * Unregisters a split screen listener.
+ */
+ oneway void unregisterSplitScreenListener(in ISplitScreenListener listener) = 2;
+
+ /**
+ * Hides the side-stage if it is currently visible.
+ */
+ oneway void setSideStageVisibility(boolean visible) = 3;
+
+ /**
+ * Removes a task from the side stage.
+ */
+ oneway void removeFromSideStage(int taskId) = 4;
+
+ /**
+ * Removes the split-screen stages.
+ */
+ oneway void exitSplitScreen() = 5;
+
+ /**
+ * @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible.
+ */
+ oneway void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 6;
+
+ /**
+ * Starts a task in a stage.
+ */
+ oneway void startTask(int taskId, int stage, int position, in Bundle options) = 7;
+
+ /**
+ * Starts a shortcut in a stage.
+ */
+ oneway void startShortcut(String packageName, String shortcutId, int stage, int position,
+ in Bundle options, in UserHandle user) = 8;
+
+ /**
+ * Starts an activity in a stage.
+ */
+ oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int stage,
+ int position, in Bundle options) = 9;
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl
index 54242bece2b6..faab4c2009cf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISplitScreenListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreenListener.aidl
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.splitscreen;
/**
* Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
*/
oneway interface ISplitScreenListener {
+
+ /**
+ * Called when the stage position changes.
+ */
void onStagePositionChanged(int stage, int position);
+
+ /**
+ * Called when a task changes stages.
+ */
void onTaskStageChanged(int taskId, int stage, boolean visible);
-}
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 25a84bd46484..340b55d7f446 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -35,7 +35,7 @@ import com.android.wm.shell.draganddrop.DragAndDropPolicy;
* TODO: Figure out which of these are actually needed outside of the Shell
*/
@ExternalThread
-public interface SplitScreen extends DragAndDropPolicy.Starter {
+public interface SplitScreen {
/**
* Stage position isn't specified normally meaning to use what ever it is currently set to.
*/
@@ -89,35 +89,10 @@ public interface SplitScreen extends DragAndDropPolicy.Starter {
void onTaskStageChanged(int taskId, @StageType int stage, boolean visible);
}
- /** @return {@code true} if split-screen is currently visible. */
- boolean isSplitScreenVisible();
- /** Moves a task in the side-stage of split-screen. */
- boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition);
- /** Moves a task in the side-stage of split-screen. */
- boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- @StagePosition int sideStagePosition);
- /** Removes a task from the side-stage of split-screen. */
- boolean removeFromSideStage(int taskId);
- /** Sets the position of the side-stage. */
- void setSideStagePosition(@StagePosition int sideStagePosition);
- /** Hides the side-stage if it is currently visible. */
- void setSideStageVisibility(boolean visible);
-
- /** Removes the split-screen stages. */
- void exitSplitScreen();
- /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */
- void exitSplitScreenOnHide(boolean exitSplitScreenOnHide);
- /** Gets the stage bounds. */
- void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds);
-
- void registerSplitScreenListener(SplitScreenListener listener);
- void unregisterSplitScreenListener(SplitScreenListener listener);
-
- void startTask(int taskId,
- @StageType int stage, @StagePosition int position, @Nullable Bundle options);
- void startShortcut(String packageName, String shortcutId, @StageType int stage,
- @StagePosition int position, @Nullable Bundle options, UserHandle user);
- void startIntent(PendingIntent intent, Context context,
- @Nullable Intent fillInIntent, @StageType int stage,
- @StagePosition int position, @Nullable Bundle options);
+ /**
+ * Returns a binder that can be passed to an external process to manipulate SplitScreen.
+ */
+ default ISplitScreen createExternalInterface() {
+ return null;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index bb6f6f259a1e..d4362efe462d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.splitscreen;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
@@ -34,19 +35,24 @@ import android.content.Intent;
import android.content.pm.LauncherApps;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
+import androidx.annotation.BinderThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
+import com.android.wm.shell.splitscreen.ISplitScreenListener;
import java.io.PrintWriter;
@@ -55,7 +61,8 @@ import java.io.PrintWriter;
* {@link SplitScreen}.
* @see StageCoordinator
*/
-public class SplitScreenController implements DragAndDropPolicy.Starter {
+public class SplitScreenController implements DragAndDropPolicy.Starter,
+ RemoteCallable<SplitScreenController> {
private static final String TAG = SplitScreenController.class.getSimpleName();
private final ShellTaskOrganizer mTaskOrganizer;
@@ -84,6 +91,16 @@ public class SplitScreenController implements DragAndDropPolicy.Starter {
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
public void onOrganizerRegistered() {
if (mStageCoordinator == null) {
// TODO: Multi-display
@@ -172,13 +189,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter {
}
}
- public void startIntent(PendingIntent intent, Context context,
- Intent fillInIntent, @SplitScreen.StageType int stage,
- @SplitScreen.StagePosition int position, @Nullable Bundle options) {
+ public void startIntent(PendingIntent intent, Intent fillInIntent,
+ @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
+ @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
- intent.send(context, 0, fillInIntent, null, null, null, options);
+ intent.send(mContext, 0, fillInIntent, null, null, null, options);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to launch activity", e);
}
@@ -242,121 +259,170 @@ public class SplitScreenController implements DragAndDropPolicy.Starter {
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
+ @ExternalThread
private class SplitScreenImpl implements SplitScreen {
- @Override
- public boolean isSplitScreenVisible() {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.isSplitScreenVisible();
- }, Boolean.class);
- }
+ private ISplitScreenImpl mISplitScreen;
@Override
- public boolean moveToSideStage(int taskId, int sideStagePosition) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.moveToSideStage(taskId, sideStagePosition);
- }, Boolean.class);
+ public ISplitScreen createExternalInterface() {
+ if (mISplitScreen != null) {
+ mISplitScreen.invalidate();
+ }
+ mISplitScreen = new ISplitScreenImpl(SplitScreenController.this);
+ return mISplitScreen;
}
+ }
- @Override
- public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
- int sideStagePosition) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.moveToSideStage(task, sideStagePosition);
- }, Boolean.class);
- }
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class ISplitScreenImpl extends ISplitScreen.Stub {
+ private SplitScreenController mController;
+ private ISplitScreenListener mListener;
+ private final SplitScreen.SplitScreenListener mSplitScreenListener =
+ new SplitScreen.SplitScreenListener() {
+ @Override
+ public void onStagePositionChanged(int stage, int position) {
+ try {
+ if (mListener != null) {
+ mListener.onStagePositionChanged(stage, position);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "onStagePositionChanged", e);
+ }
+ }
- @Override
- public boolean removeFromSideStage(int taskId) {
- return mMainExecutor.executeBlockingForResult(() -> {
- return SplitScreenController.this.removeFromSideStage(taskId);
- }, Boolean.class);
+ @Override
+ public void onTaskStageChanged(int taskId, int stage, boolean visible) {
+ try {
+ if (mListener != null) {
+ mListener.onTaskStageChanged(taskId, stage, visible);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "onTaskStageChanged", e);
+ }
+ }
+ };
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final SplitScreenController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.unregisterSplitScreenListener(mSplitScreenListener);
+ });
+ }
+ };
+
+ public ISplitScreenImpl(SplitScreenController controller) {
+ mController = controller;
}
- @Override
- public void setSideStagePosition(int sideStagePosition) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.setSideStagePosition(sideStagePosition);
- });
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
}
@Override
- public void setSideStageVisibility(boolean visible) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.setSideStageVisibility(visible);
- });
+ public void registerSplitScreenListener(ISplitScreenListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "registerSplitScreenListener",
+ (controller) -> {
+ if (mListener != null) {
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.registerSplitScreenListener(mSplitScreenListener);
+ });
}
@Override
- public void enterSplitScreen(int taskId, boolean leftOrTop) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.enterSplitScreen(taskId, leftOrTop);
- });
+ public void unregisterSplitScreenListener(ISplitScreenListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "unregisterSplitScreenListener",
+ (controller) -> {
+ if (mListener != null) {
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ mListener = null;
+ controller.unregisterSplitScreenListener(mSplitScreenListener);
+ });
}
@Override
public void exitSplitScreen() {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.exitSplitScreen();
- });
+ executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
+ (controller) -> {
+ controller.exitSplitScreen();
+ });
}
@Override
public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.exitSplitScreenOnHide(exitSplitScreenOnHide);
- });
+ executeRemoteCallWithTaskPermission(mController, "exitSplitScreenOnHide",
+ (controller) -> {
+ controller.exitSplitScreenOnHide(exitSplitScreenOnHide);
+ });
}
@Override
- public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
- try {
- mMainExecutor.executeBlocking(() -> {
- SplitScreenController.this.getStageBounds(outTopOrLeftBounds,
- outBottomOrRightBounds);
- });
- } catch (InterruptedException e) {
- Slog.e(TAG, "Failed to get stage bounds in 2s");
- }
- }
-
- @Override
- public void registerSplitScreenListener(SplitScreenListener listener) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.registerSplitScreenListener(listener);
- });
+ public void setSideStageVisibility(boolean visible) {
+ executeRemoteCallWithTaskPermission(mController, "setSideStageVisibility",
+ (controller) -> {
+ controller.setSideStageVisibility(visible);
+ });
}
@Override
- public void unregisterSplitScreenListener(SplitScreenListener listener) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.unregisterSplitScreenListener(listener);
- });
+ public void removeFromSideStage(int taskId) {
+ executeRemoteCallWithTaskPermission(mController, "removeFromSideStage",
+ (controller) -> {
+ controller.removeFromSideStage(taskId);
+ });
}
@Override
public void startTask(int taskId, int stage, int position, @Nullable Bundle options) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startTask(taskId, stage, position, options);
- });
+ executeRemoteCallWithTaskPermission(mController, "startTask",
+ (controller) -> {
+ controller.startTask(taskId, stage, position, options);
+ });
}
@Override
public void startShortcut(String packageName, String shortcutId, int stage, int position,
@Nullable Bundle options, UserHandle user) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startShortcut(packageName, shortcutId, stage, position,
- options, user);
- });
+ executeRemoteCallWithTaskPermission(mController, "startShortcut",
+ (controller) -> {
+ controller.startShortcut(packageName, shortcutId, stage, position,
+ options, user);
+ });
}
@Override
- public void startIntent(PendingIntent intent, Context context, Intent fillInIntent,
- int stage, int position, @Nullable Bundle options) {
- mMainExecutor.execute(() -> {
- SplitScreenController.this.startIntent(intent, context, fillInIntent, stage,
- position, options);
- });
+ public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position,
+ @Nullable Bundle options) {
+ executeRemoteCallWithTaskPermission(mController, "startIntent",
+ (controller) -> {
+ controller.startIntent(intent, fillInIntent, stage, position, options);
+ });
}
}
-
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl
new file mode 100644
index 000000000000..546c406ef453
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindow.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.startingsurface;
+
+import com.android.wm.shell.startingsurface.IStartingWindowListener;
+
+/**
+ * Interface that is exposed to remote callers to manipulate starting windows.
+ */
+interface IStartingWindow {
+ /**
+ * Sets listener to get task launching callbacks.
+ */
+ oneway void setStartingWindowListener(IStartingWindowListener listener) = 43;
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
index eb3e60cec5c5..f562c8fc4f85 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IStartingWindowListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/IStartingWindowListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.shared.recents;
+package com.android.wm.shell.startingsurface;
/**
* Listener interface that Launcher attaches to SystemUI to get
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
index f258286f2d17..079d68973852 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
@@ -16,35 +16,15 @@
package com.android.wm.shell.startingsurface;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.view.SurfaceControl;
-import android.window.StartingWindowInfo;
-
-import java.util.function.BiConsumer;
/**
* Interface to engage starting window feature.
*/
public interface StartingSurface {
- /**
- * Called when a task need a starting window.
- */
- void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken);
- /**
- * Called when the content of a task is ready to show, starting window can be removed.
- */
- void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
- boolean playRevealAnimation);
- /**
- * Called when the Task wants to copy the splash screen.
- * @param taskId
- */
- void copySplashScreenView(int taskId);
/**
- * Registers the starting window listener.
- *
- * @param listener The callback when need a starting window.
+ * Returns a binder that can be passed to an external process to manipulate starting windows.
*/
- void setStartingWindowListener(BiConsumer<Integer, Integer> listener);
+ default IStartingWindow createExternalInterface() {
+ return null;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index a694e525a761..b6ca86989690 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -25,6 +25,8 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
import android.content.Context;
@@ -37,6 +39,9 @@ import android.window.StartingWindowInfo;
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
+import androidx.annotation.BinderThread;
+
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
@@ -58,7 +63,7 @@ import java.util.function.BiConsumer;
* constructor to keep everything synchronized.
* @hide
*/
-public class StartingWindowController {
+public class StartingWindowController implements RemoteCallable<StartingWindowController> {
private static final String TAG = StartingWindowController.class.getSimpleName();
static final boolean DEBUG_SPLASH_SCREEN = false;
static final boolean DEBUG_TASK_SNAPSHOT = false;
@@ -68,17 +73,17 @@ public class StartingWindowController {
private BiConsumer<Integer, Integer> mTaskLaunchingCallback;
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
+ private final Context mContext;
private final ShellExecutor mSplashScreenExecutor;
// For Car Launcher
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor) {
- mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor,
- new TransactionPool());
- mSplashScreenExecutor = splashScreenExecutor;
+ this(context, splashScreenExecutor, new TransactionPool());
}
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor,
TransactionPool pool) {
+ mContext = context;
mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, pool);
mSplashScreenExecutor = splashScreenExecutor;
}
@@ -90,6 +95,16 @@ public class StartingWindowController {
return mImpl;
}
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mSplashScreenExecutor;
+ }
+
private static class StartingTypeChecker {
TaskSnapshot mSnapshot;
@@ -188,59 +203,121 @@ public class StartingWindowController {
/**
* Called when a task need a starting window.
*/
- void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
- final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
- final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (mTaskLaunchingCallback != null) {
- mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
- }
- if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
- } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
- final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
- mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
- }
- // If prefer don't show, then don't show!
+ public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ mSplashScreenExecutor.execute(() -> {
+ final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
+ final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
+ if (mTaskLaunchingCallback != null) {
+ mTaskLaunchingCallback.accept(runningTaskInfo.taskId, suggestionType);
+ }
+ if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
+ } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
+ final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
+ mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+ }
+ // If prefer don't show, then don't show!
+ });
}
- void copySplashScreenView(int taskId) {
- mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ public void copySplashScreenView(int taskId) {
+ mSplashScreenExecutor.execute(() -> {
+ mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ });
}
/**
* Called when the content of a task is ready to show, starting window can be removed.
*/
- void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
+ public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
boolean playRevealAnimation) {
- mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ mSplashScreenExecutor.execute(() -> {
+ mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
+ });
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
private class StartingSurfaceImpl implements StartingSurface {
+ private IStartingWindowImpl mIStartingWindow;
@Override
- public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.addStartingWindow(windowInfo, appToken));
+ public IStartingWindowImpl createExternalInterface() {
+ if (mIStartingWindow != null) {
+ mIStartingWindow.invalidate();
+ }
+ mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this);
+ return mIStartingWindow;
}
+ }
- @Override
- public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
- boolean playRevealAnimation) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.removeStartingWindow(taskId, leash, frame,
- playRevealAnimation));
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IStartingWindowImpl extends IStartingWindow.Stub {
+ private StartingWindowController mController;
+ private IStartingWindowListener mListener;
+ private final BiConsumer<Integer, Integer> mStartingWindowListener =
+ this::notifyIStartingWindowListener;
+ private final IBinder.DeathRecipient mListenerDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ final StartingWindowController controller = mController;
+ controller.getRemoteCallExecutor().execute(() -> {
+ mListener = null;
+ controller.setStartingWindowListener(null);
+ });
+ }
+ };
+
+ public IStartingWindowImpl(StartingWindowController controller) {
+ mController = controller;
}
- @Override
- public void copySplashScreenView(int taskId) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.copySplashScreenView(taskId));
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mController = null;
}
@Override
- public void setStartingWindowListener(BiConsumer<Integer, Integer> listener) {
- mSplashScreenExecutor.execute(() ->
- StartingWindowController.this.setStartingWindowListener(listener));
+ public void setStartingWindowListener(IStartingWindowListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "setStartingWindowListener",
+ (controller) -> {
+ if (mListener != null) {
+ // Reset the old death recipient
+ mListener.asBinder().unlinkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ }
+ if (listener != null) {
+ try {
+ listener.asBinder().linkToDeath(mListenerDeathRecipient,
+ 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
+ }
+ mListener = listener;
+ controller.setStartingWindowListener(mStartingWindowListener);
+ });
+ }
+
+ private void notifyIStartingWindowListener(int taskId, int supportedType) {
+ if (mListener == null) {
+ return;
+ }
+
+ try {
+ mListener.onTaskLaunching(taskId, supportedType);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to notify task launching", e);
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
new file mode 100644
index 000000000000..dffc700a3690
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/IShellTransitions.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.window.IRemoteTransition;
+import android.window.TransitionFilter;
+
+/**
+ * Interface that is exposed to remote callers to manipulate the transitions feature.
+ */
+interface IShellTransitions {
+
+ /**
+ * Registers a remote transition handler.
+ */
+ oneway void registerRemote(in TransitionFilter filter,
+ in IRemoteTransition remoteTransition) = 1;
+
+ /**
+ * Unregisters a remote transition handler.
+ */
+ oneway void unregisterRemote(in IRemoteTransition remoteTransition) = 2;
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index ac93a17b4014..9667f4b6a8c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.transition;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
@@ -23,6 +25,7 @@ import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import android.view.SurfaceControl;
import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
@@ -31,6 +34,8 @@ import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
+import androidx.annotation.BinderThread;
+
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
@@ -42,6 +47,8 @@ import java.util.ArrayList;
* if the request includes a specific remote.
*/
public class RemoteTransitionHandler implements Transitions.TransitionHandler {
+ private static final String TAG = "RemoteTransitionHandler";
+
private final ShellExecutor mMainExecutor;
/** Includes remotes explicitly requested by, eg, ActivityOptions */
@@ -51,15 +58,33 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler {
private final ArrayList<Pair<TransitionFilter, IRemoteTransition>> mFilters =
new ArrayList<>();
+ private final IBinder.DeathRecipient mTransitionDeathRecipient =
+ new IBinder.DeathRecipient() {
+ @Override
+ @BinderThread
+ public void binderDied() {
+ mMainExecutor.execute(() -> {
+ mFilters.clear();
+ });
+ }
+ };
+
RemoteTransitionHandler(@NonNull ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
}
void addFiltered(TransitionFilter filter, IRemoteTransition remote) {
+ try {
+ remote.asBinder().linkToDeath(mTransitionDeathRecipient, 0 /* flags */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death");
+ return;
+ }
mFilters.add(new Pair<>(filter, remote));
}
void removeFiltered(IRemoteTransition remote) {
+ remote.asBinder().unlinkToDeath(mTransitionDeathRecipient, 0 /* flags */);
for (int i = mFilters.size() - 1; i >= 0; --i) {
if (mFilters.get(i).second == remote) {
mFilters.remove(i);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
index 85bbf74d56b9..bc42c6e2f12c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ShellTransitions.java
@@ -26,7 +26,15 @@ import com.android.wm.shell.common.annotations.ExternalThread;
* Interface to manage remote transitions.
*/
@ExternalThread
-public interface RemoteTransitions {
+public interface ShellTransitions {
+
+ /**
+ * Returns a binder that can be passed to an external process to manipulate remote transitions.
+ */
+ default IShellTransitions createExternalInterface() {
+ return null;
+ }
+
/**
* Registers a remote transition.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 677db10d07a7..ca1b53d4d46b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -23,6 +23,8 @@ import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -51,6 +53,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
@@ -60,7 +63,7 @@ import java.util.ArrayList;
import java.util.Arrays;
/** Plays transition animations */
-public class Transitions {
+public class Transitions implements RemoteCallable<Transitions> {
static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
@@ -73,7 +76,7 @@ public class Transitions {
private final ShellExecutor mAnimExecutor;
private final TransitionPlayerImpl mPlayerImpl;
private final RemoteTransitionHandler mRemoteTransitionHandler;
- private final RemoteTransitionImpl mImpl = new RemoteTransitionImpl();
+ private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
@@ -87,10 +90,6 @@ public class Transitions {
/** Keeps track of currently tracked transitions and all the animations associated with each */
private final ArrayMap<IBinder, ActiveTransition> mActiveTransitions = new ArrayMap<>();
- public static RemoteTransitions asRemoteTransitions(Transitions transitions) {
- return transitions.mImpl;
- }
-
public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
@NonNull Context context, @NonNull ShellExecutor mainExecutor,
@NonNull ShellExecutor animExecutor) {
@@ -126,6 +125,20 @@ public class Transitions {
mRemoteTransitionHandler = null;
}
+ public ShellTransitions asRemoteTransitions() {
+ return mImpl;
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
+ }
+
private void dispatchAnimScaleSetting(float scale) {
for (int i = mHandlers.size() - 1; i >= 0; --i) {
mHandlers.get(i).setAnimScaleSetting(scale);
@@ -134,8 +147,8 @@ public class Transitions {
/** Create an empty/non-registering transitions object for system-ui tests. */
@VisibleForTesting
- public static RemoteTransitions createEmptyForTesting() {
- return new RemoteTransitions() {
+ public static ShellTransitions createEmptyForTesting() {
+ return new ShellTransitions() {
@Override
public void registerRemote(@androidx.annotation.NonNull TransitionFilter filter,
@androidx.annotation.NonNull IRemoteTransition remoteTransition) {
@@ -426,24 +439,74 @@ public class Transitions {
}
}
+ /**
+ * The interface for calls from outside the Shell, within the host process.
+ */
@ExternalThread
- private class RemoteTransitionImpl implements RemoteTransitions {
+ private class ShellTransitionImpl implements ShellTransitions {
+ private IShellTransitionsImpl mIShellTransitions;
+
+ @Override
+ public IShellTransitions createExternalInterface() {
+ if (mIShellTransitions != null) {
+ mIShellTransitions.invalidate();
+ }
+ mIShellTransitions = new IShellTransitionsImpl(Transitions.this);
+ return mIShellTransitions;
+ }
+
@Override
public void registerRemote(@NonNull TransitionFilter filter,
@NonNull IRemoteTransition remoteTransition) {
mMainExecutor.execute(() -> {
- Transitions.this.registerRemote(filter, remoteTransition);
+ mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
});
}
@Override
public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
mMainExecutor.execute(() -> {
- Transitions.this.unregisterRemote(remoteTransition);
+ mRemoteTransitionHandler.removeFiltered(remoteTransition);
});
}
}
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IShellTransitionsImpl extends IShellTransitions.Stub {
+ private Transitions mTransitions;
+
+ IShellTransitionsImpl(Transitions transitions) {
+ mTransitions = transitions;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ void invalidate() {
+ mTransitions = null;
+ }
+
+ @Override
+ public void registerRemote(@NonNull TransitionFilter filter,
+ @NonNull IRemoteTransition remoteTransition) {
+ executeRemoteCallWithTaskPermission(mTransitions, "registerRemote",
+ (transitions) -> {
+ transitions.mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
+ });
+ }
+
+ @Override
+ public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+ executeRemoteCallWithTaskPermission(mTransitions, "unregisterRemote",
+ (transitions) -> {
+ transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition);
+ });
+ }
+ }
+
private class SettingsObserver extends ContentObserver {
SettingsObserver() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index c1c4c6dd08d7..2f2bbba11646 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -205,7 +205,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -217,12 +217,12 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -234,12 +234,12 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -251,7 +251,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -263,7 +263,7 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@@ -276,13 +276,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@@ -295,13 +295,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
- verify(mSplitScreenStarter).startIntent(any(), any(), any(),
+ verify(mSplitScreenStarter).startIntent(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index c0ef7be8b673..7e45f952d389 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -226,8 +226,6 @@ void AssetManager2::BuildDynamicRefTable() {
}
void AssetManager2::DumpToLog() const {
- base::ScopedLogSeverity _log(base::INFO);
-
LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this);
std::string list;
@@ -1721,7 +1719,6 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) {
}
void Theme::Dump() const {
- base::ScopedLogSeverity _log(base::INFO);
LOG(INFO) << base::StringPrintf("Theme(this=%p, AssetManager2=%p)", this, asset_manager_);
for (int p = 0; p < packages_.size(); p++) {
diff --git a/media/jni/soundpool/Sound.cpp b/media/jni/soundpool/Sound.cpp
index f8b4bdb1f4d5..50e0d336f981 100644
--- a/media/jni/soundpool/Sound.cpp
+++ b/media/jni/soundpool/Sound.cpp
@@ -99,8 +99,8 @@ static status_t decode(int fd, int64_t offset, int64_t length,
__func__);
break;
}
- int sampleSize = AMediaExtractor_readSampleData(ex.get(), buf, bufsize);
- ALOGV("%s: read %d", __func__, sampleSize);
+ ssize_t sampleSize = AMediaExtractor_readSampleData(ex.get(), buf, bufsize);
+ ALOGV("%s: read %zd", __func__, sampleSize);
if (sampleSize < 0) {
sampleSize = 0;
sawInputEOS = true;
@@ -124,8 +124,8 @@ static status_t decode(int fd, int64_t offset, int64_t length,
}
AMediaCodecBufferInfo info;
- const int status = AMediaCodec_dequeueOutputBuffer(codec.get(), &info, 1);
- ALOGV("%s: dequeueoutput returned: %d", __func__, status);
+ const ssize_t status = AMediaCodec_dequeueOutputBuffer(codec.get(), &info, 1);
+ ALOGV("%s: dequeueoutput returned: %zd", __func__, status);
if (status >= 0) {
if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
ALOGV("%s: output EOS", __func__);
@@ -167,10 +167,10 @@ static status_t decode(int fd, int64_t offset, int64_t length,
} else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
ALOGV("%s: no output buffer right now", __func__);
} else if (status <= AMEDIA_ERROR_BASE) {
- ALOGE("%s: decode error: %d", __func__, status);
+ ALOGE("%s: decode error: %zd", __func__, status);
break;
} else {
- ALOGV("%s: unexpected info code: %d", __func__, status);
+ ALOGV("%s: unexpected info code: %zd", __func__, status);
}
}
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index abb0f1208bc2..95fe000bd2c2 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -320,7 +320,8 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
// audio track while the new one is being started and avoids processing them with
// wrong audio audio buffer size (mAudioBufferSize)
auto toggle = mToggle ^ 1;
- void* userData = (void*)((uintptr_t)this | toggle);
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
+ void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle);
audio_channel_mask_t soundChannelMask = sound->getChannelMask();
// When sound contains a valid channel mask, use it as is.
// Otherwise, use stream count to calculate channel mask.
@@ -391,6 +392,7 @@ exit:
void Stream::staticCallback(int event, void* user, void* info)
{
const auto userAsInt = (uintptr_t)user;
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
auto stream = reinterpret_cast<Stream*>(userAsInt & ~1);
stream->callback(event, info, int(userAsInt & 1), 0 /* tries */);
}
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 502ee00b583e..8b84bf3eb8d8 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -330,7 +330,7 @@ ssize_t StreamManager::removeFromQueues_l(
// streams on mProcessingStreams are undergoing processing by the StreamManager thread
// and do not participate in normal stream migration.
- return found;
+ return (ssize_t)found;
}
void StreamManager::addToRestartQueue_l(Stream *stream) {
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 357cc63bd41e..a66d99fbd9f4 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -34,7 +34,8 @@ static struct fields_t {
jclass mSoundPoolClass;
} fields;
static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) {
- return (SoundPool*)env->GetLongField(thiz, fields.mNativeContext);
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
+ return reinterpret_cast<SoundPool*>(env->GetLongField(thiz, fields.mNativeContext));
}
static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
struct audio_attributes_fields_t {
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 09e9675a3277..f98a959346d3 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -41,6 +41,7 @@ android_library {
srcs: [
"src/**/*.java",
"src/**/I*.aidl",
+ ":wm_shell-aidls",
],
static_libs: [
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 49e86f55bb9e..2103de2ae85c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -16,11 +16,6 @@
package com.android.systemui.shared.recents;
-import android.app.PendingIntent;
-import android.app.PictureInPictureParams;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -28,26 +23,15 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.view.MotionEvent;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.shared.recents.ISplitScreenListener;
-import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;
/**
* Temporary callbacks into SystemUI.
- * Next id = 44
*/
interface ISystemUiProxy {
/**
- * Proxies SurfaceControl.screenshotToBuffer().
- * @Removed
- * GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
- * int maxLayer, boolean useIdentityTransform, int rotation) = 0;
- */
-
- /**
* Begins screen pinning on the provided {@param taskId}.
*/
void startScreenPinning(int taskId) = 1;
@@ -121,11 +105,6 @@ interface ISystemUiProxy {
void stopScreenPinning() = 17;
/**
- * Sets the shelf height and visibility.
- */
- void setShelfHeight(boolean visible, int shelfHeight) = 20;
-
- /**
* Handle the provided image as if it was a screenshot.
*
* Deprecated, use handleImageBundleAsScreenshot with image bundle and UserTask
@@ -145,27 +124,12 @@ interface ISystemUiProxy {
void notifySwipeToHomeFinished() = 23;
/**
- * Sets listener to get pinned stack animation callbacks.
- */
- void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) = 24;
-
- /**
* Notifies that quickstep will switch to a new task
* @param rotation indicates which Surface.Rotation the gesture was started in
*/
void onQuickSwitchToNewTask(int rotation) = 25;
/**
- * Start the one-handed mode.
- */
- void startOneHandedMode() = 26;
-
- /**
- * Stop the one-handed mode.
- */
- void stopOneHandedMode() = 27;
-
- /**
* Handle the provided image as if it was a screenshot.
*/
void handleImageBundleAsScreenshot(in Bundle screenImageBundle, in Rect locationInScreen,
@@ -176,88 +140,5 @@ interface ISystemUiProxy {
*/
void expandNotificationPanel() = 29;
- /**
- * Notifies that Activity is about to be swiped to home with entering PiP transition and
- * queries the destination bounds for PiP depends on Launcher's rotation and shelf height.
- *
- * @param componentName ComponentName represents the Activity
- * @param activityInfo ActivityInfo tied to the Activity
- * @param pictureInPictureParams PictureInPictureParams tied to the Activity
- * @param launcherRotation Launcher rotation to calculate the PiP destination bounds
- * @param shelfHeight Shelf height of launcher to calculate the PiP destination bounds
- * @return destination bounds the PiP window should land into
- */
- Rect startSwipePipToHome(in ComponentName componentName, in ActivityInfo activityInfo,
- in PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) = 30;
-
- /**
- * Notifies the swiping Activity to PiP onto home transition is finished
- *
- * @param componentName ComponentName represents the Activity
- * @param destinationBounds the destination bounds the PiP window lands into
- */
- void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds) = 31;
-
- /**
- * Registers a RemoteTransitionCompat that will handle transitions. This parameter bundles an
- * IRemoteTransition and a filter that must pass for it.
- */
- void registerRemoteTransition(in RemoteTransitionCompat remoteTransition) = 32;
-
- /** Unegisters a RemoteTransitionCompat that will handle transitions. */
- void unregisterRemoteTransition(in RemoteTransitionCompat remoteTransition) = 33;
-
-// SplitScreen APIs...copied from SplitScreen.java
- /**
- * Stage position isn't specified normally meaning to use what ever it is currently set to.
- */
- //int STAGE_POSITION_UNDEFINED = -1;
- /**
- * Specifies that a stage is positioned at the top half of the screen if
- * in portrait mode or at the left half of the screen if in landscape mode.
- */
- //int STAGE_POSITION_TOP_OR_LEFT = 0;
- /**
- * Specifies that a stage is positioned at the bottom half of the screen if
- * in portrait mode or at the right half of the screen if in landscape mode.
- */
- //int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
-
- /**
- * Stage type isn't specified normally meaning to use what ever the default is.
- * E.g. exit split-screen and launch the app in fullscreen.
- */
- //int STAGE_TYPE_UNDEFINED = -1;
- /**
- * The main stage type.
- * @see MainStage
- */
- //int STAGE_TYPE_MAIN = 0;
- /**
- * The side stage type.
- * @see SideStage
- */
- //int STAGE_TYPE_SIDE = 1;
-
- void registerSplitScreenListener(in ISplitScreenListener listener) = 34;
- void unregisterSplitScreenListener(in ISplitScreenListener listener) = 35;
-
- /** Hides the side-stage if it is currently visible. */
- void setSideStageVisibility(in boolean visible) = 36;
- /** Removes the split-screen stages. */
- void exitSplitScreen() = 37;
- /** @param exitSplitScreenOnHide if to exit split-screen if both stages are not visible. */
- void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) = 38;
- void startTask(in int taskId, in int stage, in int position, in Bundle options) = 39;
- void startShortcut(in String packageName, in String shortcutId, in int stage, in int position,
- in Bundle options, in UserHandle user) = 40;
- void startIntent(
- in PendingIntent intent, in Intent fillInIntent, in int stage, in int position,
- in Bundle options) = 41;
- void removeFromSideStage(in int taskId) = 42;
- /**
- * Sets listener to get task launching callbacks.
- */
- void setStartingWindowListener(IStartingWindowListener listener) = 43;
+ // Next id = 44
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 937c1df10315..41840afc4995 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -41,6 +41,18 @@ public class QuickStepContract {
public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
+ // See IPip.aidl
+ public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip";
+ // See ISplitScreen.aidl
+ public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen";
+ // See IOneHanded.aidl
+ public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed";
+ // See IShellTransitions.aidl
+ public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS =
+ "extra_shell_shell_transitions";
+ // See IStartingWindow.aidl
+ public static final String KEY_EXTRA_SHELL_STARTING_WINDOW =
+ "extra_shell_starting_window";
public static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 2040347de1b5..e53f5c97bb5c 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -20,7 +20,6 @@ import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.media.AudioManager.ACTION_MICROPHONE_MUTE_CHANGED;
-import android.Manifest;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -43,6 +42,7 @@ import androidx.annotation.WorkerThread;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
@@ -370,13 +370,9 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
}
// TODO ntmyren: remove after teamfood is finished
- private boolean shouldShowAppPredictor(String pkgName) {
- if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, "permissions_hub_2_enabled",
- false)) {
- return false;
- }
- return mPackageManager.checkPermission(Manifest.permission.MANAGE_APP_PREDICTIONS, pkgName)
- == PackageManager.PERMISSION_GRANTED;
+ private boolean showSystemApps() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED, false);
}
/**
@@ -399,8 +395,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
return true;
}
// TODO ntmyren: Replace this with more robust check if this moves beyond teamfood
- if ((appOpCode == AppOpsManager.OP_CAMERA && isLocationProvider(packageName))
- || shouldShowAppPredictor(packageName)
+ if (((showSystemApps() && !packageName.equals("android"))
+ || appOpCode == AppOpsManager.OP_CAMERA && isLocationProvider(packageName))
|| isSpeechRecognizerUsage(appOpCode, packageName)) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
index 62058a965c09..98a703f595d2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
@@ -21,6 +21,9 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.PointF;
import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.Build;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.TypedValue;
import java.util.ArrayList;
@@ -32,6 +35,10 @@ import java.util.List;
public class UdfpsEnrollHelper {
private static final String TAG = "UdfpsEnrollHelper";
+ private static final String SCALE_OVERRIDE =
+ "com.android.systemui.biometrics.UdfpsEnrollHelper.scale";
+ private static final float SCALE = 0.5f;
+
// Enroll with two center touches before going to guided enrollment
private static final int NUM_CENTER_TOUCHES = 2;
@@ -39,9 +46,10 @@ public class UdfpsEnrollHelper {
void onEnrollmentProgress(int remaining, int totalSteps);
}
+ @NonNull private final Context mContext;
// IUdfpsOverlayController reason
private final int mEnrollReason;
- private final List<PointF> mGuidedEnrollmentPoints;
+ @NonNull private final List<PointF> mGuidedEnrollmentPoints;
private int mTotalSteps = -1;
private int mRemainingSteps = -1;
@@ -53,6 +61,7 @@ public class UdfpsEnrollHelper {
@Nullable Listener mListener;
public UdfpsEnrollHelper(@NonNull Context context, int reason) {
+ mContext = context;
mEnrollReason = reason;
mGuidedEnrollmentPoints = new ArrayList<>();
@@ -121,9 +130,15 @@ public class UdfpsEnrollHelper {
@NonNull
PointF getNextGuidedEnrollmentPoint() {
+ float scale = SCALE;
+ if (Build.IS_ENG || Build.IS_USERDEBUG) {
+ scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ SCALE_OVERRIDE, SCALE,
+ UserHandle.USER_CURRENT);
+ }
final int index = mLocationsEnrolled - NUM_CENTER_TOUCHES;
final PointF originalPoint = mGuidedEnrollmentPoints
.get(index % mGuidedEnrollmentPoints.size());
- return new PointF(originalPoint.x * 0.5f, originalPoint.y * 0.5f);
+ return new PointF(originalPoint.x * scale, originalPoint.y * scale);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 8f79de518419..ed3d5ec33b41 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -34,7 +34,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -87,7 +87,7 @@ public interface SysUIComponent {
Builder setShellCommandHandler(Optional<ShellCommandHandler> shellDump);
@BindsInstance
- Builder setTransitions(RemoteTransitions t);
+ Builder setTransitions(ShellTransitions t);
@BindsInstance
Builder setStartingSurface(Optional<StartingSurface> s);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index 1b77d1c16639..bbd95b4d0c90 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -33,7 +33,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.util.Optional;
@@ -98,7 +98,7 @@ public interface WMComponent {
Optional<TaskViewFactory> getTaskViewFactory();
@WMSingleton
- RemoteTransitions getTransitions();
+ ShellTransitions getTransitions();
@WMSingleton
Optional<StartingSurface> getStartingSurface();
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
index 03c184336364..f87ea7c61ca8 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
@@ -214,9 +214,7 @@ class PrivacyDialogController(
private fun filterType(type: PrivacyType?): PrivacyType? {
return type?.let {
- if (privacyItemController.allIndicatorsAvailable) {
- it
- } else if ((it == PrivacyType.TYPE_CAMERA || it == PrivacyType.TYPE_MICROPHONE) &&
+ if ((it == PrivacyType.TYPE_CAMERA || it == PrivacyType.TYPE_MICROPHONE) &&
privacyItemController.micCameraAvailable) {
it
} else if (it == PrivacyType.TYPE_LOCATION && privacyItemController.locationAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 1e0451601e50..03d6154706eb 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -68,8 +68,6 @@ class PrivacyItemController @Inject constructor(
addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
}
const val TAG = "PrivacyItemController"
- private const val ALL_INDICATORS =
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
private const val DEFAULT_ALL_INDICATORS = false
@@ -83,11 +81,6 @@ class PrivacyItemController @Inject constructor(
@Synchronized get() = field.toList() // Returns a shallow copy of the list
@Synchronized set
- private fun isAllIndicatorsEnabled(): Boolean {
- return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- ALL_INDICATORS, DEFAULT_ALL_INDICATORS)
- }
-
private fun isMicCameraEnabled(): Boolean {
return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
MIC_CAMERA, DEFAULT_MIC_CAMERA)
@@ -120,34 +113,29 @@ class PrivacyItemController @Inject constructor(
uiExecutor.execute(notifyChanges)
}
- var allIndicatorsAvailable = isAllIndicatorsEnabled()
- private set
var micCameraAvailable = isMicCameraEnabled()
private set
var locationAvailable = isLocationEnabled()
+ var allIndicatorsAvailable = micCameraAvailable && locationAvailable
+
private val devicePropertiesChangedListener =
object : DeviceConfig.OnPropertiesChangedListener {
override fun onPropertiesChanged(properties: DeviceConfig.Properties) {
if (DeviceConfig.NAMESPACE_PRIVACY.equals(properties.getNamespace()) &&
- (properties.keyset.contains(ALL_INDICATORS) ||
- properties.keyset.contains(MIC_CAMERA) ||
+ (properties.keyset.contains(MIC_CAMERA) ||
properties.keyset.contains(LOCATION))) {
// Running on the ui executor so can iterate on callbacks
- if (properties.keyset.contains(ALL_INDICATORS)) {
- allIndicatorsAvailable = properties.getBoolean(ALL_INDICATORS,
- DEFAULT_ALL_INDICATORS)
- callbacks.forEach { it.get()?.onFlagAllChanged(allIndicatorsAvailable) }
- }
-
if (properties.keyset.contains(MIC_CAMERA)) {
micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA)
+ allIndicatorsAvailable = micCameraAvailable && locationAvailable
callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) }
}
if (properties.keyset.contains(LOCATION)) {
locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION)
+ allIndicatorsAvailable = micCameraAvailable && locationAvailable
callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) }
}
internalUiExecutor.updateListeningState()
@@ -163,8 +151,7 @@ class PrivacyItemController @Inject constructor(
active: Boolean
) {
// Check if we care about this code right now
- if (!allIndicatorsAvailable &&
- (code in OPS_LOCATION && !locationAvailable)) {
+ if (code in OPS_LOCATION && !locationAvailable) {
return
}
val userId = UserHandle.getUserId(uid)
@@ -231,7 +218,7 @@ class PrivacyItemController @Inject constructor(
*/
private fun setListeningState() {
val listen = !callbacks.isEmpty() and
- (allIndicatorsAvailable || micCameraAvailable || locationAvailable)
+ (micCameraAvailable || locationAvailable)
if (listening == listen) return
listening = listen
if (listening) {
@@ -338,7 +325,7 @@ class PrivacyItemController @Inject constructor(
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null
}
- if (type == PrivacyType.TYPE_LOCATION && (!allIndicatorsAvailable && !locationAvailable)) {
+ if (type == PrivacyType.TYPE_LOCATION && !locationAvailable) {
return null
}
val app = PrivacyApplication(appOpItem.packageName, appOpItem.uid)
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
index 0fa7b59d0e54..5ab7bd88e49b 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
+++ b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java
@@ -88,7 +88,6 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
private boolean mViewAndWindowAdded;
private ObjectAnimator mAnimator;
- private boolean mAllIndicatorsFlagEnabled;
private boolean mMicCameraIndicatorFlagEnabled;
private boolean mLocationIndicatorEnabled;
private List<PrivacyItem> mPrivacyItems;
@@ -111,12 +110,10 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
mIconMarginStart = Math.round(res.getDimension(R.dimen.privacy_chip_icon_margin));
mIconSize = res.getDimensionPixelSize(R.dimen.privacy_chip_icon_size);
- mAllIndicatorsFlagEnabled = privacyItemController.getAllIndicatorsAvailable();
mMicCameraIndicatorFlagEnabled = privacyItemController.getMicCameraAvailable();
mLocationIndicatorEnabled = privacyItemController.getLocationAvailable();
if (DEBUG) {
- Log.d(TAG, "allIndicators: " + mAllIndicatorsFlagEnabled);
Log.d(TAG, "micCameraIndicators: " + mMicCameraIndicatorFlagEnabled);
Log.d(TAG, "locationIndicators: " + mLocationIndicatorEnabled);
}
@@ -135,12 +132,6 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
}
@Override
- public void onFlagAllChanged(boolean flag) {
- if (DEBUG) Log.d(TAG, "all indicators enabled: " + flag);
- mAllIndicatorsFlagEnabled = flag;
- }
-
- @Override
public void onFlagMicCameraChanged(boolean flag) {
if (DEBUG) Log.d(TAG, "mic/camera indicators enabled: " + flag);
mMicCameraIndicatorFlagEnabled = flag;
@@ -155,8 +146,8 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
private void updateUI() {
if (DEBUG) Log.d(TAG, mPrivacyItems.size() + " privacy items");
- if ((mMicCameraIndicatorFlagEnabled || mAllIndicatorsFlagEnabled
- || mLocationIndicatorEnabled) && !mPrivacyItems.isEmpty()) {
+ if ((mMicCameraIndicatorFlagEnabled || mLocationIndicatorEnabled)
+ && !mPrivacyItems.isEmpty()) {
if (mState == STATE_NOT_SHOWN || mState == STATE_DISAPPEARING) {
showIndicator();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 8f99a9e9c1be..e7828c366b64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -355,7 +355,6 @@ public class QuickQSPanel extends QSPanel {
setClipToPadding(false);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
- lp.gravity = Gravity.CENTER_HORIZONTAL;
setLayoutParams(lp);
setMaxColumns(4);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index e3c39aa77402..eedcdab68b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -97,7 +97,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private boolean mListening;
private AlarmClockInfo mNextAlarm;
- private boolean mAllIndicatorsEnabled;
private boolean mMicCameraIndicatorsEnabled;
private boolean mLocationIndicatorsEnabled;
private boolean mPrivacyChipLogged;
@@ -151,14 +150,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
@Override
- public void onFlagAllChanged(boolean flag) {
- if (mAllIndicatorsEnabled != flag) {
- mAllIndicatorsEnabled = flag;
- update();
- }
- }
-
- @Override
public void onFlagMicCameraChanged(boolean flag) {
if (mMicCameraIndicatorsEnabled != flag) {
mMicCameraIndicatorsEnabled = flag;
@@ -270,7 +261,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mRingerContainer.setOnClickListener(mOnClickListener);
mPrivacyChip.setOnClickListener(mOnClickListener);
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
@@ -321,7 +311,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
mNextAlarmController.addCallback(mNextAlarmChangeCallback);
mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
// Get the most up to date info
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
mPrivacyItemController.addCallback(mPICCallback);
@@ -353,13 +342,13 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
private List<String> getIgnoredIconSlots() {
ArrayList<String> ignored = new ArrayList<>();
if (getChipEnabled()) {
- if (mAllIndicatorsEnabled || mMicCameraIndicatorsEnabled) {
+ if (mMicCameraIndicatorsEnabled) {
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_camera));
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_microphone));
}
- if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) {
+ if (mLocationIndicatorsEnabled) {
ignored.add(mView.getResources().getString(
com.android.internal.R.string.status_bar_location));
}
@@ -368,7 +357,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
}
private boolean getChipEnabled() {
- return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled || mAllIndicatorsEnabled;
+ return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled;
}
private boolean isZenOverridingRinger() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index a87bfd83916a..5a714f2ed384 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -25,6 +25,11 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
@@ -35,15 +40,12 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_T
import android.annotation.FloatRange;
import android.app.ActivityTaskManager;
-import android.app.PendingIntent;
-import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -57,14 +59,12 @@ import android.os.Looper;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.util.ArraySet;
import android.util.Log;
import android.view.InputMonitor;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.accessibility.AccessibilityManager;
-import android.window.IRemoteTransition;
import androidx.annotation.NonNull;
@@ -83,15 +83,11 @@ import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.recents.IOverviewProxy;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.shared.recents.ISplitScreenListener;
-import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -103,7 +99,7 @@ import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -111,7 +107,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
import javax.inject.Inject;
@@ -151,12 +146,11 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final ScreenshotHelper mScreenshotHelper;
private final Optional<OneHanded> mOneHandedOptional;
private final CommandQueue mCommandQueue;
- private final RemoteTransitions mShellTransitions;
+ private final ShellTransitions mShellTransitions;
private final Optional<StartingSurface> mStartingSurface;
private Region mActiveNavBarRegion;
- private IPinnedStackAnimationListener mIPinnedStackAnimationListener;
private IOverviewProxy mOverviewProxy;
private int mConnectionBackoffAttempts;
private boolean mBound;
@@ -169,8 +163,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
private float mWindowCornerRadius;
private boolean mSupportsRoundedCornersOnWindows;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
- private final ArraySet<IRemoteTransition> mRemoteTransitions = new ArraySet<>();
- private IStartingWindowListener mIStartingWindowListener;
@VisibleForTesting
public ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@@ -388,20 +380,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
- public void setShelfHeight(boolean visible, int shelfHeight) {
- if (!verifyCaller("setShelfHeight")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(
- pip -> pip.setShelfHeight(visible, shelfHeight));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void handleImageAsScreenshot(Bitmap screenImage, Rect locationInScreen,
Insets visibleInsets, int taskId) {
// Deprecated
@@ -429,36 +407,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
- public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) {
- if (!verifyCaller("setPinnedStackAnimationListener")) {
- return;
- }
- mIPinnedStackAnimationListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(
- pip -> pip.setPinnedStackAnimationListener(mPinnedStackAnimationCallback));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setStartingWindowListener(IStartingWindowListener listener) {
- if (!verifyCaller("setStartingWindowListener")) {
- return;
- }
- mIStartingWindowListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mStartingSurface.ifPresent(s ->
- s.setStartingWindowListener(mStartingWindowListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void onQuickSwitchToNewTask(@Surface.Rotation int rotation) {
if (!verifyCaller("onQuickSwitchToNewTask")) {
return;
@@ -472,32 +420,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
- public void startOneHandedMode() {
- if (!verifyCaller("startOneHandedMode")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mOneHandedOptional.ifPresent(oneHanded -> oneHanded.startOneHanded());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void stopOneHandedMode() {
- if (!verifyCaller("stopOneHandedMode")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mOneHandedOptional.ifPresent(oneHanded -> oneHanded.stopOneHanded());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
Insets visibleInsets, Task.TaskKey task) {
mScreenshotHelper.provideScreenshot(
@@ -525,190 +447,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
- @Override
- public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
- PictureInPictureParams pictureInPictureParams,
- int launcherRotation, int shelfHeight) {
- if (!verifyCaller("startSwipePipToHome")) {
- return null;
- }
- final long binderToken = Binder.clearCallingIdentity();
- try {
- return mPipOptional.map(pip ->
- pip.startSwipePipToHome(componentName, activityInfo,
- pictureInPictureParams, launcherRotation, shelfHeight))
- .orElse(null);
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
- if (!verifyCaller("stopSwipePipToHome")) {
- return;
- }
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mPipOptional.ifPresent(pip -> pip.stopSwipePipToHome(
- componentName, destinationBounds));
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void registerRemoteTransition(RemoteTransitionCompat remoteTransition) {
- if (!verifyCaller("registerRemoteTransition")) return;
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mRemoteTransitions.add(remoteTransition.getTransition());
- mShellTransitions.registerRemote(
- remoteTransition.getFilter(), remoteTransition.getTransition());
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) {
- if (!verifyCaller("registerRemoteTransition")) return;
- final long binderToken = Binder.clearCallingIdentity();
- try {
- mRemoteTransitions.remove(remoteTransition.getTransition());
- mShellTransitions.unregisterRemote(remoteTransition.getTransition());
- } finally {
- Binder.restoreCallingIdentity(binderToken);
- }
- }
-
- @Override
- public void registerSplitScreenListener(ISplitScreenListener listener) {
- if (!verifyCaller("registerSplitScreenListener")) {
- return;
- }
- mISplitScreenListener = listener;
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.registerSplitScreenListener(mSplitScreenListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void unregisterSplitScreenListener(ISplitScreenListener listener) {
- if (!verifyCaller("unregisterSplitScreenListener")) {
- return;
- }
- mISplitScreenListener = null;
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.unregisterSplitScreenListener(mSplitScreenListener));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void setSideStageVisibility(boolean visible) {
- if (!verifyCaller("setSideStageVisibility")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.setSideStageVisibility(visible));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void exitSplitScreen() {
- if (!verifyCaller("exitSplitScreen")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.exitSplitScreen());
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
- if (!verifyCaller("exitSplitScreenOnHide")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s -> s.exitSplitScreenOnHide(exitSplitScreenOnHide));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startTask(int taskId, int stage, int position, Bundle options) {
- if (!verifyCaller("startTask")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.startTask(taskId, stage, position, options));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startShortcut(String packageName, String shortcutId, int stage, int position,
- Bundle options, UserHandle user) {
- if (!verifyCaller("startShortcut")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s ->
- s.startShortcut(packageName, shortcutId, stage, position, options, user));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void startIntent(PendingIntent intent, Intent fillInIntent,
- int stage, int position, Bundle options) {
- if (!verifyCaller("startIntent")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(s ->
- s.startIntent(intent, mContext, fillInIntent, stage, position, options));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void removeFromSideStage(int taskId) {
- if (!verifyCaller("removeFromSideStage")) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- mSplitScreenOptional.ifPresent(
- s -> s.removeFromSideStage(taskId));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
private boolean verifyCaller(String reason) {
final int callerId = Binder.getCallingUserHandle().getIdentifier();
if (callerId != mCurrentBoundedUserId) {
@@ -762,6 +500,22 @@ public class OverviewProxyService extends CurrentUserTracker implements
params.putBinder(KEY_EXTRA_SYSUI_PROXY, mSysUiProxy.asBinder());
params.putFloat(KEY_EXTRA_WINDOW_CORNER_RADIUS, mWindowCornerRadius);
params.putBoolean(KEY_EXTRA_SUPPORTS_WINDOW_CORNERS, mSupportsRoundedCornersOnWindows);
+
+ mPipOptional.ifPresent((pip) -> params.putBinder(
+ KEY_EXTRA_SHELL_PIP,
+ pip.createExternalInterface().asBinder()));
+ mSplitScreenOptional.ifPresent((splitscreen) -> params.putBinder(
+ KEY_EXTRA_SHELL_SPLIT_SCREEN,
+ splitscreen.createExternalInterface().asBinder()));
+ mOneHandedOptional.ifPresent((onehanded) -> params.putBinder(
+ KEY_EXTRA_SHELL_ONE_HANDED,
+ onehanded.createExternalInterface().asBinder()));
+ params.putBinder(KEY_EXTRA_SHELL_SHELL_TRANSITIONS,
+ mShellTransitions.createExternalInterface().asBinder());
+ mStartingSurface.ifPresent((startingwindow) -> params.putBinder(
+ KEY_EXTRA_SHELL_STARTING_WINDOW,
+ startingwindow.createExternalInterface().asBinder()));
+
try {
mOverviewProxy.onInitialize(params);
} catch (RemoteException e) {
@@ -801,42 +555,11 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final StatusBarWindowCallback mStatusBarWindowCallback = this::onStatusBarStateChanged;
private final BiConsumer<Rect, Rect> mSplitScreenBoundsChangeListener =
this::notifySplitScreenBoundsChanged;
- private final Consumer<Boolean> mPinnedStackAnimationCallback =
- this::notifyPinnedStackAnimationStarted;
-
- private final BiConsumer<Integer, Integer> mStartingWindowListener =
- this::notifyTaskLaunching;
// This is the death handler for the binder from the launcher service
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
- private ISplitScreenListener mISplitScreenListener;
- private final SplitScreen.SplitScreenListener mSplitScreenListener =
- new SplitScreen.SplitScreenListener() {
- @Override
- public void onStagePositionChanged(int stage, int position) {
- try {
- if (mISplitScreenListener != null) {
- mISplitScreenListener.onStagePositionChanged(stage, position);
- }
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "onStagePositionChanged", e);
- }
- }
-
- @Override
- public void onTaskStageChanged(int taskId, int stage, boolean visible) {
- try {
- if (mISplitScreenListener != null) {
- mISplitScreenListener.onTaskStageChanged(taskId, stage, visible);
- }
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "onTaskStageChanged", e);
- }
- }
- };
-
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyService(Context context, CommandQueue commandQueue,
@@ -849,7 +572,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
Optional<Lazy<StatusBar>> statusBarOptionalLazy,
Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher,
- RemoteTransitions shellTransitions,
+ ShellTransitions shellTransitions,
Optional<StartingSurface> startingSurface) {
super(broadcastDispatcher);
mContext = context;
@@ -966,29 +689,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
}
- private void notifyPinnedStackAnimationStarted(Boolean isAnimationStarted) {
- if (mIPinnedStackAnimationListener == null) {
- return;
- }
- try {
- mIPinnedStackAnimationListener.onPinnedStackAnimationStarted();
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call onPinnedStackAnimationStarted()", e);
- }
- }
-
- private void notifyTaskLaunching(int taskId, int supportedType) {
- if (mIStartingWindowListener == null) {
- return;
- }
-
- try {
- mIStartingWindowListener.onTaskLaunching(taskId, supportedType);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call notifyTaskLaunching()", e);
- }
- }
-
private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
boolean bouncerShowing) {
mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
@@ -1032,12 +732,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
// Clean up the minimized state if launcher dies
mLegacySplitScreenOptional.ifPresent(
splitScreen -> splitScreen.setMinimized(false));
-
- // Clean up any registered remote transitions
- for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) {
- mShellTransitions.unregisterRemote(mRemoteTransitions.valueAt(i));
- }
- mRemoteTransitions.clear();
}
public void startConnectionToCurrentUser() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 2b194ba15816..f65ae0c39331 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -337,6 +337,7 @@ public class NotificationChildrenContainer extends ViewGroup {
} else {
header.reapply(getContext(), mNotificationHeader);
}
+ mNotificationHeaderWrapper.setExpanded(mChildrenExpanded);
mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
if (mNotificationHeaderWrapper instanceof NotificationHeaderViewWrapper) {
NotificationHeaderViewWrapper headerWrapper =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index d53724159244..f1405dea1294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -675,8 +675,7 @@ public class PhoneStatusBarPolicy
mIconController.setIconVisibility(mSlotCamera, showCamera);
mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
- if (mPrivacyItemController.getAllIndicatorsAvailable()
- || mPrivacyItemController.getLocationAvailable()) {
+ if (mPrivacyItemController.getLocationAvailable()) {
mIconController.setIconVisibility(mSlotLocation, showLocation);
}
mPrivacyLogger.logStatusBarIconsVisible(showCamera, showMicrophone, showLocation);
@@ -684,8 +683,7 @@ public class PhoneStatusBarPolicy
@Override
public void onLocationActiveChanged(boolean active) {
- if (!mPrivacyItemController.getAllIndicatorsAvailable()
- && !mPrivacyItemController.getLocationAvailable()) {
+ if (!mPrivacyItemController.getLocationAvailable()) {
updateLocationFromController();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 1b6c61237e29..1d18750f1fdf 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -81,7 +81,7 @@ import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
-import com.android.wm.shell.transition.RemoteTransitions;
+import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -399,8 +399,8 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
- static RemoteTransitions provideRemoteTransitions(Transitions transitions) {
- return Transitions.asRemoteTransitions(transitions);
+ static ShellTransitions provideRemoteTransitions(Transitions transitions) {
+ return transitions.asRemoteTransitions();
}
@WMSingleton
@@ -509,27 +509,33 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
- static ShellInit provideShellInit(DisplayImeController displayImeController,
+ static ShellInit provideShellInit(ShellInitImpl impl) {
+ return impl.asShellInit();
+ }
+
+ @WMSingleton
+ @Provides
+ static ShellInitImpl provideShellInitImpl(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
- Optional<StartingSurface> startingSurface,
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
+ StartingWindowController startingWindow,
@ShellMainThread ShellExecutor mainExecutor) {
- return ShellInitImpl.create(displayImeController,
+ return new ShellInitImpl(displayImeController,
dragAndDropController,
shellTaskOrganizer,
legacySplitScreenOptional,
splitScreenOptional,
appPairsOptional,
- startingSurface,
pipTouchHandlerOptional,
fullscreenTaskListener,
transitions,
+ startingWindow,
mainExecutor);
}
@@ -539,7 +545,13 @@ public abstract class WMShellBaseModule {
*/
@WMSingleton
@Provides
- static Optional<ShellCommandHandler> provideShellCommandHandler(
+ static Optional<ShellCommandHandler> provideShellCommandHandler(ShellCommandHandlerImpl impl) {
+ return Optional.of(impl.asShellCommandHandler());
+ }
+
+ @WMSingleton
+ @Provides
+ static ShellCommandHandlerImpl provideShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
@@ -548,8 +560,8 @@ public abstract class WMShellBaseModule {
Optional<HideDisplayCutoutController> hideDisplayCutout,
Optional<AppPairsController> appPairsOptional,
@ShellMainThread ShellExecutor mainExecutor) {
- return Optional.of(ShellCommandHandlerImpl.create(shellTaskOrganizer,
+ return new ShellCommandHandlerImpl(shellTaskOrganizer,
legacySplitScreenOptional, splitScreenOptional, pipOptional, oneHandedOptional,
- hideDisplayCutout, appPairsOptional, mainExecutor));
+ hideDisplayCutout, appPairsOptional, mainExecutor);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
index 072f7b8a7756..791dd121852f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
@@ -395,9 +395,8 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
`when`(permissionManager.indicatorAppOpUsageData).thenReturn(
listOf(usage_camera, usage_location, usage_microphone)
)
- `when`(privacyItemController.micCameraAvailable).thenReturn(false)
- `when`(privacyItemController.locationAvailable).thenReturn(false)
- `when`(privacyItemController.allIndicatorsAvailable).thenReturn(true)
+ `when`(privacyItemController.micCameraAvailable).thenReturn(true)
+ `when`(privacyItemController.locationAvailable).thenReturn(true)
controller.showDialog(context)
exhaustExecutors()
@@ -422,7 +421,6 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
)
`when`(privacyItemController.micCameraAvailable).thenReturn(false)
`when`(privacyItemController.locationAvailable).thenReturn(false)
- `when`(privacyItemController.allIndicatorsAvailable).thenReturn(false)
controller.showDialog(context)
exhaustExecutors()
@@ -525,7 +523,6 @@ class PrivacyDialogControllerTest : SysuiTestCase() {
`when`(privacyItemController.locationAvailable).thenReturn(true)
`when`(privacyItemController.micCameraAvailable).thenReturn(true)
- `when`(privacyItemController.allIndicatorsAvailable).thenReturn(false)
`when`(userTracker.userProfiles).thenReturn(listOf(
UserInfo(USER_ID, "", 0),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
index 132bee0e7fdf..f991e718122e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt
@@ -37,7 +37,6 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@@ -51,8 +50,6 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
fun <T> eq(value: T): T = Mockito.eq(value) ?: value
fun <T> any(): T = Mockito.any<T>()
- private const val ALL_INDICATORS =
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
private const val LOCATION = SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
}
@@ -96,11 +93,6 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
@Test
- fun testNotListeningAllByDefault() {
- assertFalse(privacyItemController.allIndicatorsAvailable)
- }
-
- @Test
fun testMicCameraListeningByDefault() {
assertTrue(privacyItemController.micCameraAvailable)
}
@@ -111,10 +103,8 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
executor.runAllReady()
verify(callback).onFlagMicCameraChanged(false)
- verify(callback, never()).onFlagAllChanged(anyBoolean())
assertFalse(privacyItemController.micCameraAvailable)
- assertFalse(privacyItemController.allIndicatorsAvailable)
}
@Test
@@ -127,26 +117,15 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
@Test
- fun testAllChanged() {
- changeAll(true)
- executor.runAllReady()
-
- verify(callback).onFlagAllChanged(true)
- verify(callback, never()).onFlagMicCameraChanged(anyBoolean())
-
- assertTrue(privacyItemController.allIndicatorsAvailable)
- }
-
- @Test
fun testBothChanged() {
changeAll(true)
changeMicCamera(false)
executor.runAllReady()
- verify(callback, atLeastOnce()).onFlagAllChanged(true)
+ verify(callback, atLeastOnce()).onFlagLocationChanged(true)
verify(callback, atLeastOnce()).onFlagMicCameraChanged(false)
- assertTrue(privacyItemController.allIndicatorsAvailable)
+ assertTrue(privacyItemController.locationAvailable)
assertFalse(privacyItemController.micCameraAvailable)
}
@@ -186,28 +165,6 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
}
@Test
- fun testSomeListening_stillListening() {
- // Mic and camera are true by default
- changeAll(true)
- executor.runAllReady()
- changeAll(false)
- executor.runAllReady()
-
- verify(appOpsController, never()).removeCallback(any(), any())
- }
-
- @Test
- fun testAllDeleted_micCameraFalse_stopListening() {
- changeMicCamera(false)
- changeAll(true)
- executor.runAllReady()
- changeAll(null)
- executor.runAllReady()
-
- verify(appOpsController).removeCallback(any(), any())
- }
-
- @Test
fun testMicDeleted_stillListening() {
changeMicCamera(true)
executor.runAllReady()
@@ -219,7 +176,10 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() {
private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
private fun changeLocation(value: Boolean?) = changeProperty(LOCATION, value)
- private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value)
+ private fun changeAll(value: Boolean?) {
+ changeMicCamera(value)
+ changeLocation(value)
+ }
private fun changeProperty(name: String, value: Boolean?) {
deviceConfigProxy.setProperty(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 7ca468edfd9c..b87c7a6ad2d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -43,7 +43,6 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
@@ -72,8 +71,8 @@ class PrivacyItemControllerTest : SysuiTestCase() {
val TEST_UID = CURRENT_USER_ID * UserHandle.PER_USER_RANGE
const val TEST_PACKAGE_NAME = "test"
- private const val ALL_INDICATORS =
- SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED
+ private const val LOCATION_INDICATOR =
+ SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_ENABLED
private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
fun <T> eq(value: T): T = Mockito.eq(value) ?: value
@@ -119,7 +118,8 @@ class PrivacyItemControllerTest : SysuiTestCase() {
deviceConfigProxy = DeviceConfigProxyFake()
// Listen to everything by default
- changeAll(true)
+ changeMicCamera(true)
+ changeLocation(true)
`when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(CURRENT_USER_ID, "", 0)))
@@ -259,9 +259,8 @@ class PrivacyItemControllerTest : SysuiTestCase() {
}
@Test
- @Ignore // TODO(b/168209929)
fun testNotListeningWhenIndicatorsDisabled() {
- changeAll(false)
+ changeLocation(false)
changeMicCamera(false)
privacyItemController.addCallback(callback)
executor.runAllReady()
@@ -271,7 +270,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
@Test
fun testNotSendingLocationWhenOnlyMicCamera() {
- changeAll(false)
+ changeLocation(false)
changeMicCamera(true)
executor.runAllReady()
@@ -294,7 +293,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
.`when`(appOpsController).getActiveAppOpsForUser(anyInt())
privacyItemController.addCallback(callback)
- changeAll(false)
+ changeLocation(false)
changeMicCamera(true)
executor.runAllReady()
reset(callback) // Clean callback
@@ -521,7 +520,7 @@ class PrivacyItemControllerTest : SysuiTestCase() {
}
private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value)
- private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value)
+ private fun changeLocation(value: Boolean?) = changeProperty(LOCATION_INDICATOR, value)
private fun changeProperty(name: String, value: Boolean?) {
deviceConfigProxy.setProperty(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 97a845916185..4948c2b18746 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -148,7 +148,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Test
fun testIgnoredSlotsOnAttached_noIndicators() {
- setPrivacyController(false, false, false)
+ setPrivacyController(micCamera = false, location = false)
controller.init()
@@ -160,7 +160,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Test
fun testIgnoredSlotsOnAttached_onlyMicCamera() {
- setPrivacyController(false, true, false)
+ setPrivacyController(micCamera = true, location = false)
controller.init()
@@ -177,7 +177,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Test
fun testIgnoredSlotsOnAttached_onlyLocation() {
- setPrivacyController(false, false, true)
+ setPrivacyController(micCamera = false, location = true)
controller.init()
@@ -192,26 +192,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
@Test
fun testIgnoredSlotsOnAttached_locationMicCamera() {
- setPrivacyController(false, true, true)
-
- controller.init()
-
- val captor = argumentCaptor<List<String>>()
- verify(iconContainer).setIgnoredSlots(capture(captor))
-
- val cameraString = mContext.resources.getString(
- com.android.internal.R.string.status_bar_camera)
- val micString = mContext.resources.getString(
- com.android.internal.R.string.status_bar_microphone)
- val locationString = mContext.resources.getString(
- com.android.internal.R.string.status_bar_location)
-
- assertThat(captor.value).containsExactly(cameraString, micString, locationString)
- }
-
- @Test
- fun testIgnoredSlotsOnAttached_all() {
- setPrivacyController(true, false, false)
+ setPrivacyController(micCamera = true, location = true)
controller.init()
@@ -248,8 +229,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
`when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
}
- private fun setPrivacyController(all: Boolean, micCamera: Boolean, location: Boolean) {
- `when`(privacyItemController.allIndicatorsAvailable).thenReturn(all)
+ private fun setPrivacyController(micCamera: Boolean, location: Boolean) {
`when`(privacyItemController.micCameraAvailable).thenReturn(micCamera)
`when`(privacyItemController.locationAvailable).thenReturn(location)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
deleted file mode 100644
index 25104b8b1d20..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableContext;
-import android.testing.TestableLooper;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
-import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.startingsurface.StartingSurface;
-import com.android.wm.shell.transition.RemoteTransitions;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-
-import dagger.Lazy;
-
-/**
- * Unit tests for {@link com.android.systemui.recents.OverviewProxyService}
- */
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OverviewProxyServiceTest extends SysuiTestCase {
- private OverviewProxyService mSpiedOverviewProxyService;
- private TestableContext mSpiedContext;
-
- @Mock private BroadcastDispatcher mMockBroadcastDispatcher;
- @Mock private CommandQueue mMockCommandQueue;
- @Mock private Lazy<NavigationBarController> mMockNavBarControllerLazy;
- @Mock private IPinnedStackAnimationListener mMockPinnedStackAnimationListener;
- @Mock private NavigationModeController mMockNavModeController;
- @Mock private NotificationShadeWindowController mMockStatusBarWinController;
- @Mock private Optional<Pip> mMockPipOptional;
- @Mock private Optional<LegacySplitScreen> mMockLegacySplitScreenOptional;
- @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
- @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
- @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
- @Mock private PackageManager mPackageManager;
- @Mock private SysUiState mMockSysUiState;
- @Mock private RemoteTransitions mMockTransitions;
- @Mock private Optional<StartingSurface> mStartingSurface;
-
- @Before
- public void setUp() throws RemoteException {
- MockitoAnnotations.initMocks(this);
-
- mSpiedContext = spy(mContext);
-
- when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false);
- when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager);
-
- mSpiedOverviewProxyService = spy(new OverviewProxyService(mSpiedContext, mMockCommandQueue,
- mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController,
- mMockSysUiState, mMockPipOptional, mMockLegacySplitScreenOptional,
- mMockSplitScreenOptional, mMockStatusBarOptionalLazy, mMockOneHandedOptional,
- mMockBroadcastDispatcher, mMockTransitions, mStartingSurface));
- }
-
- @Test
- public void testNonPipDevice_shouldNotNotifySwipeToHomeFinished() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.notifySwipeToHomeFinished();
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-
- @Test
- public void testNonPipDevice_shouldNotSetPinnedStackAnimationListener() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.setPinnedStackAnimationListener(
- mMockPinnedStackAnimationListener);
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-
- @Test
- public void testNonPipDevice_shouldNotSetShelfHeight() throws RemoteException {
- mSpiedOverviewProxyService.mSysUiProxy.setShelfHeight(true /* visible */,
- 100 /* shelfHeight */);
-
- verify(mMockPipOptional, never()).ifPresent(any());
- }
-}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index fbfde436a16f..1e608f5c1240 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -1595,6 +1595,8 @@ public final class BatteryService extends SystemService {
if (Objects.equals(newService, oldService)) return;
Slog.i(TAG, "health: new instance registered " + mInstanceName);
+ // #init() may be called with null callback. Skip null callbacks.
+ if (mCallback == null) return;
mCallback.onRegistration(oldService, newService, mInstanceName);
} catch (NoSuchElementException | RemoteException ex) {
Slog.e(TAG, "health: Cannot get instance '" + mInstanceName
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index e12586bfdc06..c9836001da77 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -18,6 +18,7 @@ per-file ServiceWatcher.java = sooniln@google.com
per-file *Alarm* = file:/apex/jobscheduler/OWNERS
per-file *AppOp* = file:/core/java/android/permission/OWNERS
+per-file *Battery* = file:/BATTERY_STATS_OWNERS
per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a9904ba0de91..5adbdff150ea 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -318,7 +318,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private int[] mDataEnabledReason;
- private Map<Integer, Long> mAllowedNetworkTypesList;
+ private int[] mAllowedNetworkTypeReason;
+ private long[] mAllowedNetworkTypeValue;
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
@@ -383,7 +384,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private boolean isPrivilegedPhoneStatePermissionRequired(Set<Integer> events) {
return events.contains(TelephonyCallback.EVENT_SRVCC_STATE_CHANGED)
|| events.contains(TelephonyCallback.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
- || events.contains(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED);
+ || events.contains(TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
+ || events.contains(TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED);
}
private static final int MSG_USER_SWITCHED = 1;
@@ -527,6 +529,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones);
mIsDataEnabled= copyOf(mIsDataEnabled, mNumPhones);
mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones);
+ mAllowedNetworkTypeReason = copyOf(mAllowedNetworkTypeReason, mNumPhones);
+ mAllowedNetworkTypeValue = copyOf(mAllowedNetworkTypeValue, mNumPhones);
// ds -> ss switch.
if (mNumPhones < oldNumPhones) {
@@ -571,6 +575,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mIsDataEnabled[i] = false;
mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
+ mAllowedNetworkTypeReason[i] = -1;
+ mAllowedNetworkTypeValue[i] = -1;
}
}
@@ -630,9 +636,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mBarringInfo = new ArrayList<>();
mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones];
mPhysicalChannelConfigs = new ArrayList<>();
- mAllowedNetworkTypesList = new HashMap<>();
+ mAllowedNetworkTypeReason = new int[numPhones];
+ mAllowedNetworkTypeValue = new long[numPhones];
mIsDataEnabled = new boolean[numPhones];
mDataEnabledReason = new int[numPhones];
+
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -665,6 +673,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mIsDataEnabled[i] = false;
mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
+ mAllowedNetworkTypeReason[i] = -1;
+ mAllowedNetworkTypeValue[i] = -1;
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1172,14 +1182,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
- if (events.contains(
- TelephonyCallback.EVENT_ALLOWED_NETWORK_TYPE_LIST_CHANGED)) {
- try {
- r.callback.onAllowedNetworkTypesChanged(mAllowedNetworkTypesList);
- } catch (RemoteException ex) {
- remove(r.binder);
- }
- }
}
}
}
@@ -2454,18 +2456,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
*
* @param phoneId the phone id.
* @param subId the subId.
- * @param allowedNetworkTypesList Map associating all allowed network type reasons with reason's
- * allowed network type values.
+ * @param reason the allowed network type reason.
+ * @param allowedNetworkType the allowed network type value.
*/
- public void notifyAllowedNetworkTypesChanged(int phoneId, int subId,
- Map allowedNetworkTypesList) {
+ public void notifyAllowedNetworkTypesChanged(int phoneId, int subId, int reason,
+ long allowedNetworkType) {
if (!checkNotifyPermission("notifyAllowedNetworkTypesChanged()")) {
return;
}
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mAllowedNetworkTypesList = allowedNetworkTypesList;
+ mAllowedNetworkTypeReason[phoneId] = reason;
+ mAllowedNetworkTypeValue[phoneId] = allowedNetworkType;
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
@@ -2473,10 +2476,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
&& idMatch(r.subId, subId, phoneId)) {
try {
if (VDBG) {
- log("notifyAllowedNetworkTypesChanged: AllowedNetworkTypesList= "
- + mAllowedNetworkTypesList.toString());
+ log("notifyAllowedNetworkTypesChanged: reason= " + reason
+ + ", allowed network type:"
+ + TelephonyManager.convertNetworkTypeBitmaskToString(
+ allowedNetworkType));
}
- r.callback.onAllowedNetworkTypesChanged(mAllowedNetworkTypesList);
+ r.callback.onAllowedNetworkTypesChanged(reason, allowedNetworkType);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2531,6 +2536,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
pw.println("mIsDataEnabled=" + mIsDataEnabled);
pw.println("mDataEnabledReason=" + mDataEnabledReason);
+ pw.println("mAllowedNetworkTypeReason=" + mAllowedNetworkTypeReason[i]);
+ pw.println("mAllowedNetworkTypeValue=" + mAllowedNetworkTypeValue[i]);
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index cd3892da43e4..140f24f7cf8f 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -666,6 +666,10 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull IVcnUnderlyingNetworkPolicyListener listener) {
requireNonNull(listener, "listener was null");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.NETWORK_FACTORY,
+ "Must have permission NETWORK_FACTORY to unregister a policy listener");
+
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
PolicyListenerBinderDeath listenerBinderDeath =
diff --git a/services/core/java/com/android/server/app/GameManagerSettings.java b/services/core/java/com/android/server/app/GameManagerSettings.java
index 3e32380b60a9..2982545a5e6f 100644
--- a/services/core/java/com/android/server/app/GameManagerSettings.java
+++ b/services/core/java/com/android/server/app/GameManagerSettings.java
@@ -137,6 +137,11 @@ public class GameManagerSettings {
boolean readPersistentDataLocked() {
mGameModes.clear();
+ if (!mSettingsFile.exists()) {
+ Slog.v(GameManagerService.TAG, "Settings file doesn't exists, skip reading");
+ return false;
+ }
+
try {
final FileInputStream str = mSettingsFile.openRead();
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 6614e06aba8c..1122f7f4115a 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2098,26 +2098,28 @@ public class AppOpsService extends IAppOpsService.Stub {
ensureHistoricalOpRequestIsValid(uid, packageName, attributionTag, opNames, filter,
beginTimeMillis, endTimeMillis, flags);
Objects.requireNonNull(callback, "callback cannot be null");
-
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
- boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
- boolean isCallerSystem = Binder.getCallingPid() == Process.myPid();
- boolean isCallerPermissionController;
- try {
- isCallerPermissionController = pm.getPackageUid(
- mContext.getPackageManager().getPermissionControllerPackageName(), 0)
- == Binder.getCallingUid();
- } catch (PackageManager.NameNotFoundException doesNotHappen) {
- return;
- }
+ boolean isSelfRequest = (filter & FILTER_BY_UID) != 0 && uid == Binder.getCallingUid();
+ if (!isSelfRequest) {
+ boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
+ boolean isCallerSystem = Binder.getCallingPid() == Process.myPid();
+ boolean isCallerPermissionController;
+ try {
+ isCallerPermissionController = pm.getPackageUid(
+ mContext.getPackageManager().getPermissionControllerPackageName(), 0)
+ == Binder.getCallingUid();
+ } catch (PackageManager.NameNotFoundException doesNotHappen) {
+ return;
+ }
- if (!isCallerSystem && !isCallerInstrumented && !isCallerPermissionController) {
- mHandler.post(() -> callback.sendResult(new Bundle()));
- return;
- }
+ if (!isCallerSystem && !isCallerInstrumented && !isCallerPermissionController) {
+ mHandler.post(() -> callback.sendResult(new Bundle()));
+ return;
+ }
- mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
- Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
+ mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
+ }
final String[] opNamesArray = (opNames != null)
? opNames.toArray(new String[opNames.size()]) : null;
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index ed62abc7d773..2b0157c88136 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -49,8 +49,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
-import libcore.util.EmptyArray;
-
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -85,6 +83,8 @@ final class DiscreteRegistry {
private static final String TAG = DiscreteRegistry.class.getSimpleName();
private static final long TIMELINE_HISTORY_CUTOFF = Duration.ofHours(24).toMillis();
+ private static final long TIMELINE_QUANTIZATION = Duration.ofMinutes(1).toMillis();
+
private static final String TAG_HISTORY = "h";
private static final String ATTR_VERSION = "v";
private static final int CURRENT_VERSION = 1;
@@ -107,6 +107,8 @@ final class DiscreteRegistry {
private static final String ATTR_UID_STATE = "us";
private static final String ATTR_FLAGS = "f";
+ private static final int OP_FLAGS_DISCRETE = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED;
+
// Lock for read/write access to on disk state
private final Object mOnDiskLock = new Object();
@@ -119,6 +121,9 @@ final class DiscreteRegistry {
@GuardedBy("mInMemoryLock")
private DiscreteOps mDiscreteOps;
+ @GuardedBy("mOnDiskLock")
+ private DiscreteOps mCachedOps = null;
+
DiscreteRegistry(Object inMemoryLock) {
mInMemoryLock = inMemoryLock;
mDiscreteAccessDir = new File(new File(Environment.getDataSystemDirectory(), "appops"),
@@ -173,23 +178,25 @@ final class DiscreteRegistry {
}
}
}
- }
- DiscreteOps discreteOps;
- synchronized (mInMemoryLock) {
- discreteOps = mDiscreteOps;
- mDiscreteOps = new DiscreteOps();
- }
- if (discreteOps.isEmpty()) {
- return;
- }
- long currentTimeStamp = Instant.now().toEpochMilli();
- try {
- final File file = new File(mDiscreteAccessDir, currentTimeStamp + TIMELINE_FILE_SUFFIX);
- discreteOps.writeToFile(file);
- } catch (Throwable t) {
- Slog.e(TAG,
- "Error writing timeline state: " + t.getMessage() + " "
- + Arrays.toString(t.getStackTrace()));
+ DiscreteOps discreteOps;
+ synchronized (mInMemoryLock) {
+ discreteOps = mDiscreteOps;
+ mDiscreteOps = new DiscreteOps();
+ mCachedOps = null;
+ }
+ if (discreteOps.isEmpty()) {
+ return;
+ }
+ long currentTimeStamp = Instant.now().toEpochMilli();
+ try {
+ final File file = new File(mDiscreteAccessDir,
+ currentTimeStamp + TIMELINE_FILE_SUFFIX);
+ discreteOps.writeToFile(file);
+ } catch (Throwable t) {
+ Slog.e(TAG,
+ "Error writing timeline state: " + t.getMessage() + " "
+ + Arrays.toString(t.getStackTrace()));
+ }
}
}
@@ -197,25 +204,33 @@ final class DiscreteRegistry {
long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter, int uidFilter,
@Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
- writeAndClearAccessHistory();
- DiscreteOps discreteOps = new DiscreteOps();
- readDiscreteOpsFromDisk(discreteOps, beginTimeMillis, endTimeMillis, filter, uidFilter,
- packageNameFilter, opNamesFilter, attributionTagFilter, flagsFilter);
+ DiscreteOps discreteOps = getAndCacheDiscreteOps();
+ discreteOps.filter(beginTimeMillis, endTimeMillis, filter, uidFilter, packageNameFilter,
+ opNamesFilter, attributionTagFilter, flagsFilter);
discreteOps.applyToHistoricalOps(result);
return;
}
- private void readDiscreteOpsFromDisk(DiscreteOps discreteOps, long beginTimeMillis,
- long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter, int uidFilter,
- @Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
- @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
+ private DiscreteOps getAndCacheDiscreteOps() {
+ DiscreteOps discreteOps = new DiscreteOps();
+
synchronized (mOnDiskLock) {
- long historyBeginTimeMillis = Instant.now().minus(TIMELINE_HISTORY_CUTOFF,
- ChronoUnit.MILLIS).toEpochMilli();
- if (historyBeginTimeMillis > endTimeMillis) {
- return;
+ synchronized (mInMemoryLock) {
+ discreteOps.merge(mDiscreteOps);
+ }
+ if (mCachedOps == null) {
+ mCachedOps = new DiscreteOps();
+ readDiscreteOpsFromDisk(mCachedOps);
}
- beginTimeMillis = max(beginTimeMillis, historyBeginTimeMillis);
+ discreteOps.merge(mCachedOps);
+ }
+ return discreteOps;
+ }
+
+ private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) {
+ synchronized (mOnDiskLock) {
+ long beginTimeMillis = Instant.now().minus(TIMELINE_HISTORY_CUTOFF,
+ ChronoUnit.MILLIS).toEpochMilli();
final File[] files = mDiscreteAccessDir.listFiles();
if (files != null && files.length > 0) {
@@ -229,8 +244,7 @@ final class DiscreteRegistry {
if (timestamp < beginTimeMillis) {
continue;
}
- discreteOps.readFromFile(f, beginTimeMillis, endTimeMillis, filter, uidFilter,
- packageNameFilter, opNamesFilter, attributionTagFilter, flagsFilter);
+ discreteOps.readFromFile(f, beginTimeMillis);
}
}
}
@@ -251,15 +265,11 @@ final class DiscreteRegistry {
@AppOpsManager.HistoricalOpsRequestFilter int filter, int dumpOp,
@NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix,
int nDiscreteOps) {
- DiscreteOps discreteOps = new DiscreteOps();
- synchronized (mOnDiskLock) {
- writeAndClearAccessHistory();
- String[] opNamesFilter = dumpOp == OP_NONE ? EmptyArray.STRING
- : new String[]{AppOpsManager.opToPublicName(dumpOp)};
- readDiscreteOpsFromDisk(discreteOps, 0, Instant.now().toEpochMilli(), filter,
- uidFilter, packageNameFilter, opNamesFilter, attributionTagFilter,
- OP_FLAGS_ALL);
- }
+ DiscreteOps discreteOps = getAndCacheDiscreteOps();
+ String[] opNamesFilter = dumpOp == OP_NONE ? null
+ : new String[]{AppOpsManager.opToPublicName(dumpOp)};
+ discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter,
+ opNamesFilter, attributionTagFilter, OP_FLAGS_ALL);
discreteOps.dump(pw, sdf, date, prefix, nDiscreteOps);
}
@@ -270,7 +280,7 @@ final class DiscreteRegistry {
if (!isDiscreteUid(uid)) {
return false;
}
- if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) == 0) {
+ if ((flags & (OP_FLAGS_DISCRETE)) == 0) {
return false;
}
return true;
@@ -298,6 +308,19 @@ final class DiscreteRegistry {
mUids = new ArrayMap<>();
}
+ boolean isEmpty() {
+ return mUids.isEmpty();
+ }
+
+ void merge(DiscreteOps other) {
+ int nUids = other.mUids.size();
+ for (int i = 0; i < nUids; i++) {
+ int uid = other.mUids.keyAt(i);
+ DiscreteUidOps uidOps = other.mUids.valueAt(i);
+ getOrCreateDiscreteUidOps(uid).merge(uidOps);
+ }
+ }
+
void addDiscreteAccess(int op, int uid, @NonNull String packageName,
@Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
@AppOpsManager.UidState int uidState, long accessTime, long accessDuration) {
@@ -305,6 +328,25 @@ final class DiscreteRegistry {
uidState, accessTime, accessDuration);
}
+ private void filter(long beginTimeMillis, long endTimeMillis,
+ @AppOpsManager.HistoricalOpsRequestFilter int filter, int uidFilter,
+ @Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
+ @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
+ if ((filter & FILTER_BY_UID) != 0) {
+ ArrayMap<Integer, DiscreteUidOps> uids = new ArrayMap<>();
+ uids.put(uidFilter, getOrCreateDiscreteUidOps(uidFilter));
+ mUids = uids;
+ }
+ int nUids = mUids.size();
+ for (int i = nUids - 1; i >= 0; i--) {
+ mUids.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter, packageNameFilter,
+ opNamesFilter, attributionTagFilter, flagsFilter);
+ if (mUids.valueAt(i).isEmpty()) {
+ mUids.removeAt(i);
+ }
+ }
+ }
+
private void applyToHistoricalOps(AppOpsManager.HistoricalOps result) {
int nUids = mUids.size();
for (int i = 0; i < nUids; i++) {
@@ -353,14 +395,7 @@ final class DiscreteRegistry {
return result;
}
- boolean isEmpty() {
- return mUids.isEmpty();
- }
-
- private void readFromFile(File f, long beginTimeMillis, long endTimeMillis,
- @AppOpsManager.HistoricalOpsRequestFilter int filter,
- int uidFilter, @Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
- @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
+ private void readFromFile(File f, long beginTimeMillis) {
try {
FileInputStream stream = new FileInputStream(f);
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
@@ -377,12 +412,7 @@ final class DiscreteRegistry {
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_UID.equals(parser.getName())) {
int uid = parser.getAttributeInt(null, ATTR_UID, -1);
- if ((filter & FILTER_BY_UID) != 0 && uid != uidFilter) {
- continue;
- }
- getOrCreateDiscreteUidOps(uid).deserialize(parser, beginTimeMillis,
- endTimeMillis, filter, packageNameFilter, opNamesFilter,
- attributionTagFilter, flagsFilter);
+ getOrCreateDiscreteUidOps(uid).deserialize(parser, beginTimeMillis);
}
}
} catch (Throwable t) {
@@ -400,6 +430,38 @@ final class DiscreteRegistry {
mPackages = new ArrayMap<>();
}
+ boolean isEmpty() {
+ return mPackages.isEmpty();
+ }
+
+ void merge(DiscreteUidOps other) {
+ int nPackages = other.mPackages.size();
+ for (int i = 0; i < nPackages; i++) {
+ String packageName = other.mPackages.keyAt(i);
+ DiscretePackageOps p = other.mPackages.valueAt(i);
+ getOrCreateDiscretePackageOps(packageName).merge(p);
+ }
+ }
+
+ private void filter(long beginTimeMillis, long endTimeMillis,
+ @AppOpsManager.HistoricalOpsRequestFilter int filter,
+ @Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
+ @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
+ if ((filter & FILTER_BY_PACKAGE_NAME) != 0) {
+ ArrayMap<String, DiscretePackageOps> packages = new ArrayMap<>();
+ packages.put(packageNameFilter, getOrCreateDiscretePackageOps(packageNameFilter));
+ mPackages = packages;
+ }
+ int nPackages = mPackages.size();
+ for (int i = nPackages - 1; i >= 0; i--) {
+ mPackages.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter, opNamesFilter,
+ attributionTagFilter, flagsFilter);
+ if (mPackages.valueAt(i).isEmpty()) {
+ mPackages.removeAt(i);
+ }
+ }
+ }
+
void addDiscreteAccess(int op, @NonNull String packageName, @Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
long accessTime, long accessDuration) {
@@ -445,22 +507,12 @@ final class DiscreteRegistry {
}
}
- void deserialize(TypedXmlPullParser parser, long beginTimeMillis,
- long endTimeMillis, @AppOpsManager.HistoricalOpsRequestFilter int filter,
- @Nullable String packageNameFilter,
- @Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
- @AppOpsManager.OpFlags int flagsFilter) throws Exception {
+ void deserialize(TypedXmlPullParser parser, long beginTimeMillis) throws Exception {
int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_PACKAGE.equals(parser.getName())) {
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
- if ((filter & FILTER_BY_PACKAGE_NAME) != 0
- && !packageName.equals(packageNameFilter)) {
- continue;
- }
- getOrCreateDiscretePackageOps(packageName).deserialize(parser, beginTimeMillis,
- endTimeMillis, filter, opNamesFilter, attributionTagFilter,
- flagsFilter);
+ getOrCreateDiscretePackageOps(packageName).deserialize(parser, beginTimeMillis);
}
}
}
@@ -473,6 +525,10 @@ final class DiscreteRegistry {
mPackageOps = new ArrayMap<>();
}
+ boolean isEmpty() {
+ return mPackageOps.isEmpty();
+ }
+
void addDiscreteAccess(int op, @Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
long accessTime, long accessDuration) {
@@ -480,6 +536,35 @@ final class DiscreteRegistry {
accessDuration);
}
+ void merge(DiscretePackageOps other) {
+ int nOps = other.mPackageOps.size();
+ for (int i = 0; i < nOps; i++) {
+ int opId = other.mPackageOps.keyAt(i);
+ DiscreteOp op = other.mPackageOps.valueAt(i);
+ getOrCreateDiscreteOp(opId).merge(op);
+ }
+ }
+
+ private void filter(long beginTimeMillis, long endTimeMillis,
+ @AppOpsManager.HistoricalOpsRequestFilter int filter,
+ @Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
+ @AppOpsManager.OpFlags int flagsFilter) {
+ int nOps = mPackageOps.size();
+ for (int i = nOps - 1; i >= 0; i--) {
+ int opId = mPackageOps.keyAt(i);
+ if ((filter & FILTER_BY_OP_NAMES) != 0 && !ArrayUtils.contains(opNamesFilter,
+ AppOpsManager.opToPublicName(opId))) {
+ mPackageOps.removeAt(i);
+ continue;
+ }
+ mPackageOps.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter,
+ attributionTagFilter, flagsFilter);
+ if (mPackageOps.valueAt(i).isEmpty()) {
+ mPackageOps.removeAt(i);
+ }
+ }
+ }
+
private DiscreteOp getOrCreateDiscreteOp(int op) {
DiscreteOp result = mPackageOps.get(op);
if (result == null) {
@@ -519,20 +604,12 @@ final class DiscreteRegistry {
}
}
- void deserialize(TypedXmlPullParser parser, long beginTimeMillis, long endTimeMillis,
- @AppOpsManager.HistoricalOpsRequestFilter int filter,
- @Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
- @AppOpsManager.OpFlags int flagsFilter) throws Exception {
+ void deserialize(TypedXmlPullParser parser, long beginTimeMillis) throws Exception {
int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_OP.equals(parser.getName())) {
int op = parser.getAttributeInt(null, ATTR_OP_ID);
- if ((filter & FILTER_BY_OP_NAMES) != 0 && !ArrayUtils.contains(opNamesFilter,
- AppOpsManager.opToPublicName(op))) {
- continue;
- }
- getOrCreateDiscreteOp(op).deserialize(parser, beginTimeMillis, endTimeMillis,
- filter, attributionTagFilter, flagsFilter);
+ getOrCreateDiscreteOp(op).deserialize(parser, beginTimeMillis);
}
}
}
@@ -545,31 +622,66 @@ final class DiscreteRegistry {
mAttributedOps = new ArrayMap<>();
}
+ boolean isEmpty() {
+ return mAttributedOps.isEmpty();
+ }
+
+ void merge(DiscreteOp other) {
+ int nTags = other.mAttributedOps.size();
+ for (int i = 0; i < nTags; i++) {
+ String tag = other.mAttributedOps.keyAt(i);
+ List<DiscreteOpEvent> otherEvents = other.mAttributedOps.valueAt(i);
+ List<DiscreteOpEvent> events = getOrCreateDiscreteOpEventsList(tag);
+ mAttributedOps.put(tag, stableListMerge(events, otherEvents));
+ }
+ }
+
+ private void filter(long beginTimeMillis, long endTimeMillis,
+ @AppOpsManager.HistoricalOpsRequestFilter int filter,
+ @Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
+ if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0) {
+ ArrayMap<String, List<DiscreteOpEvent>> attributedOps = new ArrayMap<>();
+ attributedOps.put(attributionTagFilter,
+ getOrCreateDiscreteOpEventsList(attributionTagFilter));
+ mAttributedOps = attributedOps;
+ }
+
+ int nTags = mAttributedOps.size();
+ for (int i = nTags - 1; i >= 0; i--) {
+ String tag = mAttributedOps.keyAt(i);
+ List<DiscreteOpEvent> list = mAttributedOps.valueAt(i);
+ list = filterEventsList(list, beginTimeMillis, endTimeMillis, flagsFilter);
+ mAttributedOps.put(tag, list);
+ if (list.size() == 0) {
+ mAttributedOps.removeAt(i);
+ }
+ }
+ }
+
void addDiscreteAccess(@Nullable String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.UidState int uidState,
long accessTime, long accessDuration) {
List<DiscreteOpEvent> attributedOps = getOrCreateDiscreteOpEventsList(
attributionTag);
- accessTime = Instant.ofEpochMilli(accessTime).truncatedTo(
- ChronoUnit.MINUTES).toEpochMilli();
+ accessTime = accessTime / TIMELINE_QUANTIZATION * TIMELINE_QUANTIZATION;
int nAttributedOps = attributedOps.size();
- for (int i = nAttributedOps - 1; i >= 0; i--) {
- DiscreteOpEvent previousOp = attributedOps.get(i);
- if (i == nAttributedOps - 1 && previousOp.mNoteTime == accessTime
- && accessDuration > -1) {
- // existing event with updated duration
- attributedOps.remove(i);
- break;
- }
+ int i = nAttributedOps;
+ for (; i > 0; i--) {
+ DiscreteOpEvent previousOp = attributedOps.get(i - 1);
if (previousOp.mNoteTime < accessTime) {
break;
}
if (previousOp.mOpFlag == flags && previousOp.mUidState == uidState) {
- return;
+ if (accessDuration != previousOp.mNoteDuration
+ && accessDuration > TIMELINE_QUANTIZATION) {
+ break;
+ } else {
+ return;
+ }
}
}
- attributedOps.add(new DiscreteOpEvent(accessTime, accessDuration, uidState, flags));
+ attributedOps.add(i, new DiscreteOpEvent(accessTime, accessDuration, uidState, flags));
}
private List<DiscreteOpEvent> getOrCreateDiscreteOpEventsList(String attributionTag) {
@@ -633,18 +745,11 @@ final class DiscreteRegistry {
}
}
- void deserialize(TypedXmlPullParser parser, long beginTimeMillis, long endTimeMillis,
- @AppOpsManager.HistoricalOpsRequestFilter int filter,
- @Nullable String attributionTagFilter,
- @AppOpsManager.OpFlags int flagsFilter) throws Exception {
+ void deserialize(TypedXmlPullParser parser, long beginTimeMillis) throws Exception {
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (TAG_TAG.equals(parser.getName())) {
String attributionTag = parser.getAttributeValue(null, ATTR_TAG);
- if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !attributionTag.equals(
- attributionTagFilter)) {
- continue;
- }
List<DiscreteOpEvent> events = getOrCreateDiscreteOpEventsList(
attributionTag);
int innerDepth = parser.getDepth();
@@ -655,11 +760,7 @@ final class DiscreteRegistry {
-1);
int uidState = parser.getAttributeInt(null, ATTR_UID_STATE);
int opFlags = parser.getAttributeInt(null, ATTR_FLAGS);
- if ((flagsFilter & opFlags) == 0) {
- continue;
- }
- if ((noteTime + noteDuration < beginTimeMillis
- && noteTime > endTimeMillis)) {
+ if (noteTime + noteDuration < beginTimeMillis) {
continue;
}
DiscreteOpEvent event = new DiscreteOpEvent(noteTime, noteDuration,
@@ -715,5 +816,41 @@ final class DiscreteRegistry {
out.attributeInt(null, ATTR_FLAGS, mOpFlag);
}
}
+
+ private static List<DiscreteOpEvent> stableListMerge(List<DiscreteOpEvent> a,
+ List<DiscreteOpEvent> b) {
+ int nA = a.size();
+ int nB = b.size();
+ int i = 0;
+ int k = 0;
+ List<DiscreteOpEvent> result = new ArrayList<>(nA + nB);
+ while (i < nA || k < nB) {
+ if (i == nA) {
+ result.add(b.get(k++));
+ } else if (k == nB) {
+ result.add(a.get(i++));
+ } else if (a.get(i).mNoteTime < b.get(k).mNoteTime) {
+ result.add(a.get(i++));
+ } else {
+ result.add(b.get(k++));
+ }
+ }
+ return result;
+ }
+
+ private static List<DiscreteOpEvent> filterEventsList(List<DiscreteOpEvent> list,
+ long beginTimeMillis, long endTimeMillis, @AppOpsManager.OpFlags int flagsFilter) {
+ int n = list.size();
+ List<DiscreteOpEvent> result = new ArrayList<>(n);
+ for (int i = 0; i < n; i++) {
+ DiscreteOpEvent event = list.get(i);
+ if ((event.mOpFlag & flagsFilter) != 0
+ && event.mNoteTime + event.mNoteDuration > beginTimeMillis
+ && event.mNoteTime < endTimeMillis) {
+ result.add(event);
+ }
+ }
+ return result;
+ }
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 22d628b8e789..4435c4795730 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -532,7 +532,7 @@ final class HistoricalRegistry {
System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName,
attributionTag, uidState, flags, increment);
mDiscreteRegistry.recordDiscreteAccess(uid, packageName, op, attributionTag,
- flags, uidState, increment, eventStartTime);
+ flags, uidState, eventStartTime, increment);
}
}
}
@@ -795,7 +795,7 @@ final class HistoricalRegistry {
private static boolean isApiEnabled() {
return Binder.getCallingUid() == Process.myUid()
|| DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_ENABLED, false);
+ PROPERTY_PERMISSIONS_HUB_ENABLED, true);
}
private static final class Persistence {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 672ed3d00344..6ab4a69eaf65 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2621,9 +2621,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
// Dispatch display id for InputMethodService to update context display.
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(
- MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken,
- mMethodMap.get(mCurMethodId).getConfigChanges()));
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+ MSG_INITIALIZE_IME, mCurTokenDisplayId, mCurMethod, mCurToken));
scheduleNotifyImeUidToAudioService(mCurMethodUid);
if (mCurClient != null) {
clearClientSessionLocked(mCurClient);
@@ -4479,8 +4478,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
final IBinder token = (IBinder) args.arg2;
((IInputMethod) args.arg1).initializeInternal(token, msg.arg1,
- new InputMethodPrivilegedOperationsImpl(this, token),
- (int) args.arg3);
+ new InputMethodPrivilegedOperationsImpl(this, token));
} catch (RemoteException e) {
}
args.recycle();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0cc9f9e150c6..d5a9e3c0d4f8 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7376,15 +7376,7 @@ public class NotificationManagerService extends SystemService {
// so need to check the notification still valide for vibrate.
synchronized (mNotificationLock) {
if (mNotificationsByKey.get(record.getKey()) != null) {
- // Vibrator checks the appops for the op package, not the caller,
- // so we need to add the bypass dnd flag to be heard. it's ok to
- // always add this flag here because we've already checked that we can
- // bypass dnd
- AudioAttributes.Builder aab =
- new AudioAttributes.Builder(record.getAudioAttributes())
- .setFlags(FLAG_BYPASS_INTERRUPTION_POLICY);
- mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getOpPkg(),
- effect, "Notification (delayed)", aab.build());
+ vibrate(record, effect, true);
} else {
Slog.e(TAG, "No vibration for canceled notification : "
+ record.getKey());
@@ -7392,8 +7384,7 @@ public class NotificationManagerService extends SystemService {
}
}).start();
} else {
- mVibrator.vibrate(record.getSbn().getUid(), record.getSbn().getPackageName(),
- effect, "Notification", record.getAudioAttributes());
+ vibrate(record, effect, false);
}
return true;
} finally{
@@ -7401,6 +7392,16 @@ public class NotificationManagerService extends SystemService {
}
}
+ private void vibrate(NotificationRecord record, VibrationEffect effect, boolean delayed) {
+ // We need to vibrate as "android" so we can breakthrough DND. VibratorManagerService
+ // doesn't have a concept of vibrating on an app's behalf, so add the app information
+ // to the reason so we can still debug from bugreports
+ String reason = "Notification (" + record.getSbn().getOpPkg() + " "
+ + record.getSbn().getUid() + ") " + (delayed ? "(Delayed)" : "");
+ mVibrator.vibrate(Process.SYSTEM_UID, PackageManagerService.PLATFORM_PACKAGE_NAME,
+ effect, reason, record.getAudioAttributes());
+ }
+
private boolean isNotificationForCurrentUser(NotificationRecord record) {
final int currentUser;
final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 1acbabda9e19..ca8202f5f94b 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -105,6 +105,12 @@ public class AppsFilter implements Watchable, Snappable {
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
/**
+ * A mapping from the set of App IDs that query other App IDs via library name to the
+ * list of packages that they can see.
+ */
+ private final SparseSetArray<Integer> mQueryableViaUsesLibrary = new SparseSetArray<>();
+
+ /**
* Executor for running reasonably short background tasks such as building the initial
* visibility cache.
*/
@@ -239,6 +245,7 @@ public class AppsFilter implements Watchable, Snappable {
Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
+ Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
mForceQueryable.addAll(orig.mForceQueryable);
mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
@@ -508,6 +515,22 @@ public class AppsFilter implements Watchable, Snappable {
return false;
}
+ private static boolean canQueryViaUsesLibrary(AndroidPackage querying,
+ AndroidPackage potentialTarget) {
+ if (potentialTarget.getLibraryNames().isEmpty()) {
+ return false;
+ }
+ final List<String> libNames = potentialTarget.getLibraryNames();
+ for (int i = 0, size = libNames.size(); i < size; i++) {
+ final String libName = libNames.get(i);
+ if (querying.getUsesLibraries().contains(libName)
+ || querying.getUsesOptionalLibraries().contains(libName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static boolean matchesProviders(
Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
@@ -707,6 +730,9 @@ public class AppsFilter implements Watchable, Snappable {
|| canQueryAsInstaller(existingSetting, newPkg)) {
mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
}
+ if (canQueryViaUsesLibrary(existingPkg, newPkg)) {
+ mQueryableViaUsesLibrary.add(existingSetting.appId, newPkgSetting.appId);
+ }
}
// now we'll evaluate our new package's ability to see existing packages
if (!mForceQueryable.contains(existingSetting.appId)) {
@@ -718,6 +744,9 @@ public class AppsFilter implements Watchable, Snappable {
|| canQueryAsInstaller(newPkgSetting, existingPkg)) {
mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
}
+ if (canQueryViaUsesLibrary(newPkg, existingPkg)) {
+ mQueryableViaUsesLibrary.add(newPkgSetting.appId, existingSetting.appId);
+ }
}
// if either package instruments the other, mark both as visible to one another
if (newPkgSetting.pkg != null && existingSetting.pkg != null
@@ -1035,6 +1064,10 @@ public class AppsFilter implements Watchable, Snappable {
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
}
+ mQueryableViaUsesLibrary.remove(setting.appId);
+ for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
+ mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), setting.appId);
+ }
mForceQueryable.remove(setting.appId);
@@ -1315,6 +1348,18 @@ public class AppsFilter implements Watchable, Snappable {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
+ if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) {
+ if (DEBUG_LOGGING) {
+ log(callingSetting, targetPkgSetting, "queryable for library users");
+ }
+ return false;
+ }
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+
return true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -1394,6 +1439,8 @@ public class AppsFilter implements Watchable, Snappable {
filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
mImplicitlyQueryable, " ", expandPackages);
}
+ pw.println(" queryable via uses-library:");
+ dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", expandPackages);
}
private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index b34611b9cd6f..29322e2553e9 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -180,6 +180,8 @@ public class DataLoaderManagerService extends SystemService {
mId = id;
mListener = listener;
mDataLoader = null;
+
+ callListener(IDataLoaderStatusListener.DATA_LOADER_BINDING);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 82b12aac0a11..bafe987cb546 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1011,8 +1011,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
"DataLoader installation of APEX modules is not allowed.");
}
- if (this.params.dataLoaderParams.getComponentName().getPackageName()
- == SYSTEM_DATA_LOADER_PACKAGE && mContext.checkCallingOrSelfPermission(
+ boolean systemDataLoader = SYSTEM_DATA_LOADER_PACKAGE.equals(
+ this.params.dataLoaderParams.getComponentName().getPackageName());
+ if (systemDataLoader && mContext.checkCallingOrSelfPermission(
Manifest.permission.USE_SYSTEM_DATA_LOADERS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("You need the "
@@ -3653,6 +3654,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public void onStatusChanged(int dataLoaderId, int status) {
switch (status) {
+ case IDataLoaderStatusListener.DATA_LOADER_BINDING:
case IDataLoaderStatusListener.DATA_LOADER_STOPPED:
case IDataLoaderStatusListener.DATA_LOADER_DESTROYED:
return;
@@ -3763,8 +3765,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
healthCheckParams.unhealthyTimeoutMs = INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS;
healthCheckParams.unhealthyMonitoringMs = INCREMENTAL_STORAGE_UNHEALTHY_MONITORING_MS;
- final boolean systemDataLoader =
- params.getComponentName().getPackageName() == SYSTEM_DATA_LOADER_PACKAGE;
+ final boolean systemDataLoader = SYSTEM_DATA_LOADER_PACKAGE.equals(
+ params.getComponentName().getPackageName());
final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
@Override
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 0c2b4c547dae..b4bcde726173 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -80,14 +80,14 @@ public interface DomainVerificationManagerInternal {
* been preserved for migration purposes, but is otherwise ignored. Corresponds to
* {@link PackageManager#INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS}.
*/
- int APPROVAL_LEVEL_LEGACY_ALWAYS = 1;
+ int APPROVAL_LEVEL_LEGACY_ALWAYS = 2;
/**
* The app has been chosen by the user through
* {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set, boolean)},
* indicating an explicit choice to use this app to open an unverified domain.
*/
- int APPROVAL_LEVEL_SELECTION = 2;
+ int APPROVAL_LEVEL_SELECTION = 3;
/**
* The app is approved through the digital asset link statement being hosted at the domain
@@ -95,7 +95,7 @@ public interface DomainVerificationManagerInternal {
* {@link DomainVerificationManager#setDomainVerificationStatus(UUID, Set, int)} by
* the domain verification agent on device.
*/
- int APPROVAL_LEVEL_VERIFIED = 3;
+ int APPROVAL_LEVEL_VERIFIED = 4;
/**
* The app has been installed as an instant app, which grants it total authority on the domains
@@ -105,7 +105,7 @@ public interface DomainVerificationManagerInternal {
* The user is still able to disable instant app link handling through
* {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String, boolean)}.
*/
- int APPROVAL_LEVEL_INSTANT_APP = 4;
+ int APPROVAL_LEVEL_INSTANT_APP = 5;
/**
* Defines the possible values for {@link #approvalLevelForDomain(PackageSetting, Intent, int)}
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index eaba083c551c..e3dc70b41c0d 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -54,50 +54,6 @@ final class VibratorController {
void onComplete(int vibratorId, long vibrationId);
}
- /**
- * Initializes the native part of this controller, creating a global reference to given
- * {@link OnVibrationCompleteListener} and returns a newly allocated native pointer. This
- * wrapper is responsible for deleting this pointer by calling the method pointed
- * by {@link #vibratorGetFinalizer()}.
- *
- * <p><b>Note:</b> Make sure the given implementation of {@link OnVibrationCompleteListener}
- * do not hold any strong reference to the instance responsible for deleting the returned
- * pointer, to avoid creating a cyclic GC root reference.
- */
- static native long vibratorInit(int vibratorId, OnVibrationCompleteListener listener);
-
- /**
- * Returns pointer to native function responsible for cleaning up the native pointer allocated
- * and returned by {@link #vibratorInit(int, OnVibrationCompleteListener)}.
- */
- static native long vibratorGetFinalizer();
-
- static native boolean vibratorIsAvailable(long nativePtr);
-
- static native void vibratorOn(long nativePtr, long milliseconds, long vibrationId);
-
- static native void vibratorOff(long nativePtr);
-
- static native void vibratorSetAmplitude(long nativePtr, int amplitude);
-
- static native int[] vibratorGetSupportedEffects(long nativePtr);
-
- static native int[] vibratorGetSupportedPrimitives(long nativePtr);
-
- static native long vibratorPerformEffect(
- long nativePtr, long effect, long strength, long vibrationId);
-
- static native long vibratorPerformComposedEffect(
- long nativePtr, VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId);
-
- static native void vibratorSetExternalControl(long nativePtr, boolean enabled);
-
- static native long vibratorGetCapabilities(long nativePtr);
-
- static native void vibratorAlwaysOnEnable(long nativePtr, long id, long effect, long strength);
-
- static native void vibratorAlwaysOnDisable(long nativePtr, long id);
-
VibratorController(int vibratorId, OnVibrationCompleteListener listener) {
this(vibratorId, listener, new NativeWrapper());
}
@@ -109,7 +65,8 @@ final class VibratorController {
mNativeWrapper.init(vibratorId, listener);
mVibratorInfo = new VibratorInfo(vibratorId, nativeWrapper.getCapabilities(),
- nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives());
+ nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives(),
+ nativeWrapper.getResonantFrequency(), nativeWrapper.getQFactor());
}
/** Register state listener for this vibrator. */
@@ -336,13 +293,47 @@ final class VibratorController {
/** Wrapper around the static-native methods of {@link VibratorController} for tests. */
@VisibleForTesting
public static class NativeWrapper {
+ /**
+ * Initializes the native part of this controller, creating a global reference to given
+ * {@link OnVibrationCompleteListener} and returns a newly allocated native pointer. This
+ * wrapper is responsible for deleting this pointer by calling the method pointed
+ * by {@link #getNativeFinalizer()}.
+ *
+ * <p><b>Note:</b> Make sure the given implementation of {@link OnVibrationCompleteListener}
+ * do not hold any strong reference to the instance responsible for deleting the returned
+ * pointer, to avoid creating a cyclic GC root reference.
+ */
+ private static native long nativeInit(int vibratorId, OnVibrationCompleteListener listener);
+
+ /**
+ * Returns pointer to native function responsible for cleaning up the native pointer
+ * allocated and returned by {@link #nativeInit(int, OnVibrationCompleteListener)}.
+ */
+ private static native long getNativeFinalizer();
+ private static native boolean isAvailable(long nativePtr);
+ private static native void on(long nativePtr, long milliseconds, long vibrationId);
+ private static native void off(long nativePtr);
+ private static native void setAmplitude(long nativePtr, int amplitude);
+ private static native int[] getSupportedEffects(long nativePtr);
+ private static native int[] getSupportedPrimitives(long nativePtr);
+ private static native long performEffect(
+ long nativePtr, long effect, long strength, long vibrationId);
+ private static native long performComposedEffect(long nativePtr,
+ VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId);
+ private static native void setExternalControl(long nativePtr, boolean enabled);
+ private static native long getCapabilities(long nativePtr);
+ private static native void alwaysOnEnable(long nativePtr, long id, long effect,
+ long strength);
+ private static native void alwaysOnDisable(long nativePtr, long id);
+ private static native float getResonantFrequency(long nativePtr);
+ private static native float getQFactor(long nativePtr);
private long mNativePtr = 0;
/** Initializes native controller and allocation registry to destroy native instances. */
public void init(int vibratorId, OnVibrationCompleteListener listener) {
- mNativePtr = VibratorController.vibratorInit(vibratorId, listener);
- long finalizerPtr = VibratorController.vibratorGetFinalizer();
+ mNativePtr = nativeInit(vibratorId, listener);
+ long finalizerPtr = getNativeFinalizer();
if (finalizerPtr != 0) {
NativeAllocationRegistry registry =
@@ -354,65 +345,73 @@ final class VibratorController {
/** Check if the vibrator is currently available. */
public boolean isAvailable() {
- return VibratorController.vibratorIsAvailable(mNativePtr);
+ return isAvailable(mNativePtr);
}
/** Turns vibrator on for given time. */
public void on(long milliseconds, long vibrationId) {
- VibratorController.vibratorOn(mNativePtr, milliseconds, vibrationId);
+ on(mNativePtr, milliseconds, vibrationId);
}
/** Turns vibrator off. */
public void off() {
- VibratorController.vibratorOff(mNativePtr);
+ off(mNativePtr);
}
/** Sets the amplitude for the vibrator to run. */
public void setAmplitude(int amplitude) {
- VibratorController.vibratorSetAmplitude(mNativePtr, amplitude);
+ setAmplitude(mNativePtr, amplitude);
}
/** Returns all predefined effects supported by the device vibrator. */
public int[] getSupportedEffects() {
- return VibratorController.vibratorGetSupportedEffects(mNativePtr);
+ return getSupportedEffects(mNativePtr);
}
/** Returns all compose primitives supported by the device vibrator. */
public int[] getSupportedPrimitives() {
- return VibratorController.vibratorGetSupportedPrimitives(mNativePtr);
+ return getSupportedPrimitives(mNativePtr);
}
/** Turns vibrator on to perform one of the supported effects. */
public long perform(long effect, long strength, long vibrationId) {
- return VibratorController.vibratorPerformEffect(
- mNativePtr, effect, strength, vibrationId);
+ return performEffect(mNativePtr, effect, strength, vibrationId);
}
/** Turns vibrator on to perform one of the supported composed effects. */
public long compose(
VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId) {
- return VibratorController.vibratorPerformComposedEffect(mNativePtr, effect,
- vibrationId);
+ return performComposedEffect(mNativePtr, effect, vibrationId);
}
/** Enabled the device vibrator to be controlled by another service. */
public void setExternalControl(boolean enabled) {
- VibratorController.vibratorSetExternalControl(mNativePtr, enabled);
+ setExternalControl(mNativePtr, enabled);
}
/** Returns all capabilities of the device vibrator. */
public long getCapabilities() {
- return VibratorController.vibratorGetCapabilities(mNativePtr);
+ return getCapabilities(mNativePtr);
}
/** Enable always-on vibration with given id and effect. */
public void alwaysOnEnable(long id, long effect, long strength) {
- VibratorController.vibratorAlwaysOnEnable(mNativePtr, id, effect, strength);
+ alwaysOnEnable(mNativePtr, id, effect, strength);
}
/** Disable always-on vibration for given id. */
public void alwaysOnDisable(long id) {
- VibratorController.vibratorAlwaysOnDisable(mNativePtr, id);
+ alwaysOnDisable(mNativePtr, id);
+ }
+
+ /** Gets the vibrator's resonant frequency (F0) */
+ public float getResonantFrequency() {
+ return getResonantFrequency(mNativePtr);
+ }
+
+ /** Gets the vibrator's Q factor */
+ public float getQFactor() {
+ return getQFactor(mNativePtr);
}
}
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 385dc79567fa..5d22f8fde057 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -884,6 +884,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
mPendingTaskEvents.remove(pending);
}
mPendingTaskEvents.add(pending);
+ mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
return true;
}
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index ef2d0baff031..f60b35499013 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -32,8 +32,6 @@
#include "com_android_server_vibrator_VibratorManagerService.h"
namespace V1_0 = android::hardware::vibrator::V1_0;
-namespace V1_1 = android::hardware::vibrator::V1_1;
-namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;
namespace aidl = android::hardware::vibrator;
@@ -85,10 +83,11 @@ static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId)
class VibratorControllerWrapper {
public:
VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener)
- : mHal(std::move(findVibrator(vibratorId))),
+ : mHal(findVibrator(vibratorId)),
mVibratorId(vibratorId),
mCallbackListener(env->NewGlobalRef(callbackListener)) {
- LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator hal");
+ LOG_ALWAYS_FATAL_IF(mHal == nullptr,
+ "Failed to connect to vibrator HAL, or vibratorId is invalid");
LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
"Unable to create global reference to vibration callback handler");
}
@@ -130,15 +129,15 @@ static void destroyNativeWrapper(void* ptr) {
}
}
-static jlong vibratorInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
- jobject callbackListener) {
+static jlong vibratorNativeInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
+ jobject callbackListener) {
std::unique_ptr<VibratorControllerWrapper> wrapper =
std::make_unique<VibratorControllerWrapper>(env, vibratorId, callbackListener);
wrapper->hal()->init();
return reinterpret_cast<jlong>(wrapper.release());
}
-static jlong vibratorGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
+static jlong vibratorGetNativeFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeWrapper));
}
@@ -286,25 +285,46 @@ static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr,
wrapper->hal()->alwaysOnDisable(static_cast<int32_t>(id));
}
+static float vibratorGetResonantFrequency(JNIEnv* env, jclass /* clazz */, jlong ptr) {
+ VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
+ if (wrapper == nullptr) {
+ ALOGE("vibratorGetResonantFrequency failed because native wrapper was not initialized");
+ return NAN;
+ }
+ auto result = wrapper->hal()->getResonantFrequency();
+ return result.isOk() ? static_cast<jfloat>(result.value()) : NAN;
+}
+
+static float vibratorGetQFactor(JNIEnv* env, jclass /* clazz */, jlong ptr) {
+ VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
+ if (wrapper == nullptr) {
+ ALOGE("vibratorGetQFactor failed because native wrapper was not initialized");
+ return NAN;
+ }
+ auto result = wrapper->hal()->getQFactor();
+ return result.isOk() ? static_cast<jfloat>(result.value()) : NAN;
+}
+
static const JNINativeMethod method_table[] = {
- {"vibratorInit",
+ {"nativeInit",
"(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)J",
- (void*)vibratorInit},
- {"vibratorGetFinalizer", "()J", (void*)vibratorGetFinalizer},
- {"vibratorIsAvailable", "(J)Z", (void*)vibratorIsAvailable},
- {"vibratorOn", "(JJJ)V", (void*)vibratorOn},
- {"vibratorOff", "(J)V", (void*)vibratorOff},
- {"vibratorSetAmplitude", "(JI)V", (void*)vibratorSetAmplitude},
- {"vibratorPerformEffect", "(JJJJ)J", (void*)vibratorPerformEffect},
- {"vibratorPerformComposedEffect",
- "(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;J)J",
+ (void*)vibratorNativeInit},
+ {"getNativeFinalizer", "()J", (void*)vibratorGetNativeFinalizer},
+ {"isAvailable", "(J)Z", (void*)vibratorIsAvailable},
+ {"on", "(JJJ)V", (void*)vibratorOn},
+ {"off", "(J)V", (void*)vibratorOff},
+ {"setAmplitude", "(JI)V", (void*)vibratorSetAmplitude},
+ {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect},
+ {"performComposedEffect", "(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;J)J",
(void*)vibratorPerformComposedEffect},
- {"vibratorGetSupportedEffects", "(J)[I", (void*)vibratorGetSupportedEffects},
- {"vibratorGetSupportedPrimitives", "(J)[I", (void*)vibratorGetSupportedPrimitives},
- {"vibratorSetExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
- {"vibratorGetCapabilities", "(J)J", (void*)vibratorGetCapabilities},
- {"vibratorAlwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
- {"vibratorAlwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
+ {"getSupportedEffects", "(J)[I", (void*)vibratorGetSupportedEffects},
+ {"getSupportedPrimitives", "(J)[I", (void*)vibratorGetSupportedPrimitives},
+ {"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
+ {"getCapabilities", "(J)J", (void*)vibratorGetCapabilities},
+ {"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
+ {"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
+ {"getResonantFrequency", "(J)F", (void*)vibratorGetResonantFrequency},
+ {"getQFactor", "(J)F", (void*)vibratorGetQFactor},
};
int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
@@ -320,7 +340,8 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env
sPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "scale", "F");
sPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "delay", "I");
- return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorController",
+ return jniRegisterNativeMethods(env,
+ "com/android/server/vibrator/VibratorController$NativeWrapper",
method_table, NELEM(method_table));
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 48ae8d672fb1..aed13b263a7f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -19,6 +19,8 @@ package com.android.server.devicepolicy;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;
+
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.TEXT;
@@ -38,7 +40,6 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
-import android.util.Log;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
@@ -455,8 +456,7 @@ class ActiveAdmin {
try {
trustAgentInfo.options.saveToXml(out);
} catch (XmlPullParserException e) {
- Log.e(DevicePolicyManagerService.LOG_TAG,
- "Failed to save TrustAgent options", e);
+ Slog.e(LOG_TAG, e, "Failed to save TrustAgent options");
}
out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
}
@@ -629,8 +629,7 @@ class ActiveAdmin {
String tag = parser.getName();
if (TAG_POLICIES.equals(tag)) {
if (shouldOverridePolicies) {
- Log.d(DevicePolicyManagerService.LOG_TAG,
- "Overriding device admin policies from XML.");
+ Slog.d(LOG_TAG, "Overriding device admin policies from XML.");
info.readPoliciesFromXml(parser);
}
} else if (TAG_PASSWORD_QUALITY.equals(tag)) {
@@ -726,16 +725,14 @@ class ActiveAdmin {
if (type == TypedXmlPullParser.TEXT) {
shortSupportMessage = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing text when loading short support message");
+ Slog.w(LOG_TAG, "Missing text when loading short support message");
}
} else if (TAG_LONG_SUPPORT_MESSAGE.equals(tag)) {
type = parser.next();
if (type == TypedXmlPullParser.TEXT) {
longSupportMessage = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing text when loading long support message");
+ Slog.w(LOG_TAG, "Missing text when loading long support message");
}
} else if (TAG_PARENT_ADMIN.equals(tag)) {
Preconditions.checkState(!isParent);
@@ -748,8 +745,7 @@ class ActiveAdmin {
if (type == TypedXmlPullParser.TEXT) {
organizationName = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing text when loading organization name");
+ Slog.w(LOG_TAG, "Missing text when loading organization name");
}
} else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
isLogoutEnabled = parser.getAttributeBoolean(null, ATTR_VALUE, false);
@@ -758,16 +754,14 @@ class ActiveAdmin {
if (type == TypedXmlPullParser.TEXT) {
startUserSessionMessage = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing text when loading start session message");
+ Slog.w(LOG_TAG, "Missing text when loading start session message");
}
} else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
type = parser.next();
if (type == TypedXmlPullParser.TEXT) {
endUserSessionMessage = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing text when loading end session message");
+ Slog.w(LOG_TAG, "Missing text when loading end session message");
}
} else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
mCrossProfileCalendarPackages = readPackageList(parser, tag);
@@ -802,16 +796,14 @@ class ActiveAdmin {
if (type == TypedXmlPullParser.TEXT) {
mOrganizationId = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing Organization ID.");
+ Slog.w(LOG_TAG, "Missing Organization ID.");
}
} else if (TAG_ENROLLMENT_SPECIFIC_ID.equals(tag)) {
type = parser.next();
if (type == TypedXmlPullParser.TEXT) {
mEnrollmentSpecificId = parser.getText();
} else {
- Log.w(DevicePolicyManagerService.LOG_TAG,
- "Missing Enrollment-specific ID.");
+ Slog.w(LOG_TAG, "Missing Enrollment-specific ID.");
}
} else if (TAG_ADMIN_CAN_GRANT_SENSORS_PERMISSIONS.equals(tag)) {
mAdminCanGrantSensorsPermissions = parser.getAttributeBoolean(null, ATTR_VALUE,
@@ -820,7 +812,7 @@ class ActiveAdmin {
mUsbDataSignalingEnabled = parser.getAttributeBoolean(null, ATTR_VALUE,
USB_DATA_SIGNALING_ENABLED_DEFAULT);
} else {
- Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
+ Slog.w(LOG_TAG, "Unknown admin tag: %s", tag);
XmlUtils.skipCurrentTag(parser);
}
}
@@ -842,12 +834,10 @@ class ActiveAdmin {
if (packageName != null) {
result.add(packageName);
} else {
- Slog.w(DevicePolicyManagerService.LOG_TAG,
- "Package name missing under " + outerTag);
+ Slog.w(LOG_TAG, "Package name missing under %s", outerTag);
}
} else {
- Slog.w(DevicePolicyManagerService.LOG_TAG,
- "Unknown tag under " + tag + ": " + outerTag);
+ Slog.w(LOG_TAG, "Unknown tag under %s: ", tag, outerTag);
}
}
return result;
@@ -868,8 +858,7 @@ class ActiveAdmin {
if (tag.equals(tagDAM)) {
result.add(parser.getAttributeValue(null, ATTR_VALUE));
} else {
- Slog.e(DevicePolicyManagerService.LOG_TAG,
- "Expected tag " + tag + " but found " + tagDAM);
+ Slog.e(LOG_TAG, "Expected tag %s but found %s", tag, tagDAM);
}
}
}
@@ -891,8 +880,7 @@ class ActiveAdmin {
final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
result.put(component, trustAgentInfo);
} else {
- Slog.w(DevicePolicyManagerService.LOG_TAG,
- "Unknown tag under " + tag + ": " + tagDAM);
+ Slog.w(LOG_TAG, "Unknown tag under %s: %s", tag, tagDAM);
}
}
return result;
@@ -912,8 +900,7 @@ class ActiveAdmin {
if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
result.options = PersistableBundle.restoreFromXml(parser);
} else {
- Slog.w(DevicePolicyManagerService.LOG_TAG,
- "Unknown tag under " + tag + ": " + tagDAM);
+ Slog.w(LOG_TAG, "Unknown tag under %s: %s", tag, tagDAM);
}
}
return result;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
index d812b8f7fadb..e0c5e328f8c7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/CertificateMonitor.java
@@ -16,6 +16,8 @@
package com.android.server.devicepolicy;
+import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;
+
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -33,7 +35,7 @@ import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
-import android.util.Log;
+import android.util.Slog;
import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -47,7 +49,6 @@ import java.security.cert.X509Certificate;
import java.util.List;
public class CertificateMonitor {
- protected static final String LOG_TAG = DevicePolicyManagerService.LOG_TAG;
protected static final int MONITORING_CERT_NOTIFICATION_ID = SystemMessage.NOTE_SSL_CERT_INFO;
private final DevicePolicyManagerService mService;
@@ -78,16 +79,16 @@ public class CertificateMonitor {
X509Certificate cert = parseCert(certBuffer);
pemCert = Credentials.convertToPem(cert);
} catch (CertificateException | IOException ce) {
- Log.e(LOG_TAG, "Problem converting cert", ce);
+ Slog.e(LOG_TAG, ce, "Problem converting cert");
return null;
}
try (KeyChainConnection keyChainConnection = mInjector.keyChainBindAsUser(userHandle)) {
return keyChainConnection.getService().installCaCertificate(pemCert);
} catch (RemoteException e) {
- Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e);
+ Slog.e(LOG_TAG, e, "installCaCertsToKeyChain(): ");
} catch (InterruptedException e1) {
- Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1);
+ Slog.w(LOG_TAG, e1, "installCaCertsToKeyChain(): ");
Thread.currentThread().interrupt();
}
return null;
@@ -99,9 +100,9 @@ public class CertificateMonitor {
keyChainConnection.getService().deleteCaCertificate(aliases[i]);
}
} catch (RemoteException e) {
- Log.e(LOG_TAG, "from CaCertUninstaller: ", e);
+ Slog.e(LOG_TAG, e, "from CaCertUninstaller: ");
} catch (InterruptedException ie) {
- Log.w(LOG_TAG, "CaCertUninstaller: ", ie);
+ Slog.w(LOG_TAG, ie, "CaCertUninstaller: ");
Thread.currentThread().interrupt();
}
}
@@ -137,7 +138,8 @@ public class CertificateMonitor {
};
private void updateInstalledCertificates(final UserHandle userHandle) {
- if (!mInjector.getUserManager().isUserUnlocked(userHandle.getIdentifier())) {
+ final int userId = userHandle.getIdentifier();
+ if (!mInjector.getUserManager().isUserUnlocked(userId)) {
return;
}
@@ -145,7 +147,8 @@ public class CertificateMonitor {
try {
installedCerts = getInstalledCaCertificates(userHandle);
} catch (RemoteException | RuntimeException e) {
- Log.e(LOG_TAG, "Could not retrieve certificates from KeyChain service", e);
+ Slog.e(LOG_TAG, e, "Could not retrieve certificates from KeyChain service for user %d",
+ userId);
return;
}
mService.onInstalledCertificatesChanged(userHandle, installedCerts);
@@ -167,7 +170,7 @@ public class CertificateMonitor {
try {
userContext = mInjector.createContextAsUser(userHandle);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Create context as " + userHandle + " failed", e);
+ Slog.e(LOG_TAG, e, "Create context as %s failed", userHandle);
return null;
}
@@ -183,7 +186,6 @@ public class CertificateMonitor {
smallIconId = R.drawable.stat_sys_certificate_info;
parentUserId = mService.getProfileParentId(userHandle.getIdentifier());
} else if (mService.getDeviceOwnerUserId() == userHandle.getIdentifier()) {
- final String ownerName = mService.getDeviceOwnerName();
contentText = resources.getString(R.string.ssl_ca_cert_noti_managed,
mService.getDeviceOwnerName());
smallIconId = R.drawable.stat_sys_certificate_info;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
index 3067d4507162..00e0292d404f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceAdminServiceController.java
@@ -46,19 +46,11 @@ public class DeviceAdminServiceController {
final Object mLock = new Object();
final Context mContext;
- private final DevicePolicyManagerService mService;
private final DevicePolicyManagerService.Injector mInjector;
private final DevicePolicyConstants mConstants;
private final Handler mHandler; // needed?
- static void debug(String format, Object... args) {
- if (!DEBUG) {
- return;
- }
- Slog.d(TAG, String.format(format, args));
- }
-
private class DevicePolicyServiceConnection
extends PersistentConnection<IDeviceAdminService> {
public DevicePolicyServiceConnection(int userId, @NonNull ComponentName componentName) {
@@ -88,7 +80,6 @@ public class DeviceAdminServiceController {
public DeviceAdminServiceController(DevicePolicyManagerService service,
DevicePolicyConstants constants) {
- mService = service;
mInjector = service.mInjector;
mContext = mInjector.mContext;
mHandler = new Handler(BackgroundThread.get().getLooper());
@@ -122,8 +113,9 @@ public class DeviceAdminServiceController {
synchronized (mLock) {
final ServiceInfo service = findService(packageName, userId);
if (service == null) {
- debug("Owner package %s on u%d has no service.",
- packageName, userId);
+ if (DEBUG) {
+ Slog.d(TAG, "Owner package %s on u%d has no service.", packageName, userId);
+ }
disconnectServiceOnUserLocked(userId, actionForLog);
return;
}
@@ -134,14 +126,17 @@ public class DeviceAdminServiceController {
// Note even when we're already connected to the same service, the binding
// would have died at this point due to a package update. So we disconnect
// anyway and re-connect.
- debug("Disconnecting from existing service connection.",
- packageName, userId);
+ if (DEBUG) {
+ Slog.d("Disconnecting from existing service connection.", packageName,
+ userId);
+ }
disconnectServiceOnUserLocked(userId, actionForLog);
}
- debug("Owner package %s on u%d has service %s for %s",
- packageName, userId,
+ if (DEBUG) {
+ Slog.d("Owner package %s on u%d has service %s for %s", packageName, userId,
service.getComponentName().flattenToShortString(), actionForLog);
+ }
final DevicePolicyServiceConnection conn =
new DevicePolicyServiceConnection(
@@ -172,8 +167,10 @@ public class DeviceAdminServiceController {
private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
final DevicePolicyServiceConnection conn = mConnections.get(userId);
if (conn != null) {
- debug("Stopping service for u%d if already running for %s.",
- userId, actionForLog);
+ if (DEBUG) {
+ Slog.d(TAG, "Stopping service for u%d if already running for %s.", userId,
+ actionForLog);
+ }
conn.unbind();
mConnections.remove(userId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyConstants.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyConstants.java
index 464d6f5ea835..84e6da0d9851 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyConstants.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyConstants.java
@@ -88,7 +88,7 @@ public class DevicePolicyConstants {
} catch (IllegalArgumentException e) {
// Failed to parse the settings string, log this and move on
// with defaults.
- Slog.e(TAG, "Bad device policy settings: " + settings);
+ Slog.e(TAG, "Bad device policy settings: %s", settings);
}
long dasDiedServiceReconnectBackoffSec = parser.getLong(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index c0b2ed4cc955..52cdce6ee7b3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -179,11 +179,11 @@ class DevicePolicyData {
*/
static boolean store(DevicePolicyData policyData, JournaledFile file, boolean isFdeDevice) {
FileOutputStream stream = null;
+ File chooseForWrite = null;
try {
- File chooseForWrite = file.chooseForWrite();
+ chooseForWrite = file.chooseForWrite();
if (VERBOSE_LOG) {
- Slog.v(TAG, "Storing data for user " + policyData.mUserId + " on "
- + chooseForWrite);
+ Slog.v(TAG, "Storing data for user %d on %s ", policyData.mUserId, chooseForWrite);
}
stream = new FileOutputStream(chooseForWrite, false);
TypedXmlSerializer out = Xml.resolveSerializer(stream);
@@ -195,7 +195,7 @@ class DevicePolicyData {
policyData.mRestrictionsProvider.flattenToString());
}
if (policyData.mUserSetupComplete) {
- if (VERBOSE_LOG) Slog.v(TAG, "setting " + ATTR_SETUP_COMPLETE + " to true");
+ if (VERBOSE_LOG) Slog.v(TAG, "setting %s to true", ATTR_SETUP_COMPLETE);
out.attributeBoolean(null, ATTR_SETUP_COMPLETE, true);
}
if (policyData.mPaired) {
@@ -216,8 +216,8 @@ class DevicePolicyData {
if (policyData.mFactoryResetFlags != 0) {
if (VERBOSE_LOG) {
- Slog.v(TAG, "Storing factory reset flags for user " + policyData.mUserId + ": "
- + factoryResetFlagsToString(policyData.mFactoryResetFlags));
+ Slog.v(TAG, "Storing factory reset flags for user %d: %s", policyData.mUserId,
+ factoryResetFlagsToString(policyData.mFactoryResetFlags));
}
out.attributeInt(null, ATTR_FACTORY_RESET_FLAGS, policyData.mFactoryResetFlags);
}
@@ -382,7 +382,7 @@ class DevicePolicyData {
file.commit();
return true;
} catch (XmlPullParserException | IOException e) {
- Slog.w(TAG, "failed writing file", e);
+ Slog.w(TAG, e, "failed writing file %s", chooseForWrite);
try {
if (stream != null) {
stream.close();
@@ -404,10 +404,8 @@ class DevicePolicyData {
ComponentName ownerComponent) {
FileInputStream stream = null;
File file = journaledFile.chooseForRead();
- if (VERBOSE_LOG) {
- Slog.v(TAG, "Loading data for user " + policy.mUserId + " from " + file);
- }
-
+ if (VERBOSE_LOG) Slog.v(TAG, "Loading data for user %d from %s", policy.mUserId, file);
+ boolean needsRewrite = false;
try {
stream = new FileInputStream(file);
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
@@ -454,8 +452,8 @@ class DevicePolicyData {
policy.mFactoryResetFlags = parser.getAttributeInt(null, ATTR_FACTORY_RESET_FLAGS, 0);
if (VERBOSE_LOG) {
- Slog.v(TAG, "Restored factory reset flags for user " + policy.mUserId + ": "
- + factoryResetFlagsToString(policy.mFactoryResetFlags));
+ Slog.v(TAG, "Restored factory reset flags for user %d: %s", policy.mUserId,
+ factoryResetFlagsToString(policy.mFactoryResetFlags));
}
policy.mFactoryResetReason = parser.getAttributeValue(null, ATTR_FACTORY_RESET_REASON);
@@ -488,7 +486,7 @@ class DevicePolicyData {
policy.mAdminMap.put(ap.info.getComponent(), ap);
}
} catch (RuntimeException e) {
- Slog.w(TAG, "Failed loading admin " + name, e);
+ Slog.w(TAG, e, "Failed loading admin %s", name);
}
} else if ("delegation".equals(tag)) {
// Parse delegation info.
@@ -560,7 +558,7 @@ class DevicePolicyData {
policy.mAppsSuspended =
parser.getAttributeBoolean(null, ATTR_VALUE, false);
} else {
- Slog.w(TAG, "Unknown tag: " + tag);
+ Slog.w(TAG, "Unknown tag: %s", tag);
XmlUtils.skipCurrentTag(parser);
}
}
@@ -568,7 +566,7 @@ class DevicePolicyData {
// Don't be noisy, this is normal if we haven't defined any policies.
} catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
| IndexOutOfBoundsException e) {
- Slog.w(TAG, "failed parsing " + file, e);
+ Slog.w(TAG, e, "failed parsing %s", file);
}
try {
if (stream != null) {
@@ -592,8 +590,8 @@ class DevicePolicyData {
}
}
if (!haveOwner) {
- Slog.w(TAG, "Previous password owner " + mPasswordOwner
- + " no longer active; disabling");
+ Slog.w(TAG, "Previous password owner %s no longer active; disabling",
+ mPasswordOwner);
mPasswordOwner = -1;
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2855c70368b1..577f3f5a1cb4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1106,7 +1106,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* Used by {@code setDevicePolicySafetyChecker()} above and {@link OneTimeSafetyChecker}.
*/
void setDevicePolicySafetyCheckerUnchecked(DevicePolicySafetyChecker safetyChecker) {
- Slog.i(LOG_TAG, String.format("Setting DevicePolicySafetyChecker as %s", safetyChecker));
+ Slog.i(LOG_TAG, "Setting DevicePolicySafetyChecker as %s", safetyChecker);
mSafetyChecker = safetyChecker;
mInjector.setDevicePolicySafetyChecker(safetyChecker);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
index 457255bd9a73..28a6987bb846 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
@@ -68,17 +68,16 @@ public final class FactoryResetter {
IResultReceiver receiver = new IResultReceiver.Stub() {
@Override
public void send(int resultCode, Bundle resultData) throws RemoteException {
- Slog.i(TAG, String.format("Factory reset confirmed by %s, proceeding",
- mSafetyChecker));
+ Slog.i(TAG, "Factory reset confirmed by %s, proceeding", mSafetyChecker);
try {
factoryResetInternalUnchecked();
} catch (IOException e) {
// Shouldn't happen
- Slog.wtf(TAG, "IOException calling underlying systems", e);
+ Slog.wtf(TAG, e, "IOException calling underlying systems");
}
}
};
- Slog.i(TAG, String.format("Delaying factory reset until %s confirms", mSafetyChecker));
+ Slog.i(TAG, "Delaying factory reset until %s confirms", mSafetyChecker);
mSafetyChecker.onFactoryReset(receiver);
return false;
}
@@ -113,9 +112,9 @@ public final class FactoryResetter {
}
private void factoryResetInternalUnchecked() throws IOException {
- Slog.i(TAG, String.format("factoryReset(): reason=%s, shutdown=%b, force=%b, wipeEuicc=%b, "
+ Slog.i(TAG, "factoryReset(): reason=%s, shutdown=%b, force=%b, wipeEuicc=%b, "
+ "wipeAdoptableStorage=%b, wipeFRP=%b", mReason, mShutdown, mForce, mWipeEuicc,
- mWipeAdoptableStorage, mWipeFactoryResetProtection));
+ mWipeAdoptableStorage, mWipeFactoryResetProtection);
UserManager um = mContext.getSystemService(UserManager.class);
if (!mForce && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
index 37dbfc170aff..0b9ece466df4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
@@ -18,6 +18,8 @@ package com.android.server.devicepolicy;
import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
+import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;
+
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -36,6 +38,7 @@ import android.provider.Telephony;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
+import android.util.Log;
import android.util.Slog;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
@@ -105,7 +108,9 @@ public final class PersonalAppsSuspensionHelper {
result.remove(pkg);
}
- Slog.i(LOG_TAG, "Packages subject to suspension: " + String.join(",", result));
+ if (Log.isLoggable(LOG_TAG, Log.INFO)) {
+ Slog.i(LOG_TAG, "Packages subject to suspension: %s", String.join(",", result));
+ }
return result.toArray(new String[0]);
}
@@ -118,7 +123,7 @@ public final class PersonalAppsSuspensionHelper {
for (final ResolveInfo resolveInfo : matchingActivities) {
if (resolveInfo.activityInfo == null
|| TextUtils.isEmpty(resolveInfo.activityInfo.packageName)) {
- Slog.wtf(LOG_TAG, "Could not find package name for launcher app" + resolveInfo);
+ Slog.wtf(LOG_TAG, "Could not find package name for launcher app %s", resolveInfo);
continue;
}
final String packageName = resolveInfo.activityInfo.packageName;
@@ -129,7 +134,8 @@ public final class PersonalAppsSuspensionHelper {
result.add(packageName);
}
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(LOG_TAG, "Could not find application info for launcher app: " + packageName);
+ Slog.e(LOG_TAG, "Could not find application info for launcher app: %s",
+ packageName);
}
}
return result;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index 543f3815454e..2959c10d5508 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -25,6 +25,8 @@ import static android.app.admin.DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEP
import static android.app.admin.DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED;
import static android.app.admin.DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED;
+import static com.android.server.devicepolicy.DevicePolicyManagerService.LOG_TAG;
+
import android.annotation.IntDef;
import android.app.Notification;
import android.app.PendingIntent;
@@ -58,7 +60,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Class managing bugreport collection upon device owner's request.
*/
public class RemoteBugreportManager {
- private static final String LOG_TAG = DevicePolicyManagerService.LOG_TAG;
static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
@@ -206,7 +207,7 @@ public class RemoteBugreportManager {
return true;
} catch (RemoteException re) {
// should never happen
- Slog.e(LOG_TAG, "Failed to make remote calls to start bugreportremote service", re);
+ Slog.e(LOG_TAG, re, "Failed to make remote calls to start bugreportremote service");
return false;
} finally {
mInjector.binderRestoreCallingIdentity(callingIdentity);
@@ -220,7 +221,7 @@ public class RemoteBugreportManager {
mContext.registerReceiver(mRemoteBugreportFinishedReceiver, filterFinished);
} catch (IntentFilter.MalformedMimeTypeException e) {
// should never happen, as setting a constant
- Slog.w(LOG_TAG, "Failed to set type " + BUGREPORT_MIMETYPE, e);
+ Slog.w(LOG_TAG, e, "Failed to set type %s", BUGREPORT_MIMETYPE);
}
final IntentFilter filterConsent = new IntentFilter();
filterConsent.addAction(ACTION_BUGREPORT_SHARING_DECLINED);
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 1fcc2843bd43..c38d0b3cc7db 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -74,6 +74,13 @@ struct Constants {
// If DL was up and not crashing for 10mins, we consider it healthy and reset all delays.
static constexpr auto healthyDataLoaderUptime = 10min;
+
+ // For healthy DLs, we'll retry every ~5secs for ~10min
+ static constexpr auto bindRetryInterval = 5s;
+ static constexpr auto bindGracePeriod = 10min;
+
+ static constexpr auto bindingTimeout = 1min;
+
// 10s, 100s (~2min), 1000s (~15min), 10000s (~3hrs)
static constexpr auto minBindDelay = 10s;
static constexpr auto maxBindDelay = 10000s;
@@ -293,6 +300,7 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v
mTimedQueue(sm.getTimedQueue()),
mProgressUpdateJobQueue(sm.getProgressUpdateJobQueue()),
mFs(sm.getFs()),
+ mClock(sm.getClock()),
mIncrementalDir(rootDir) {
CHECK(mVold) << "Vold service is unavailable";
CHECK(mDataLoaderManager) << "DataLoaderManagerService is unavailable";
@@ -302,6 +310,7 @@ IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_v
CHECK(mTimedQueue) << "TimedQueue is unavailable";
CHECK(mProgressUpdateJobQueue) << "mProgressUpdateJobQueue is unavailable";
CHECK(mFs) << "Fs is unavailable";
+ CHECK(mClock) << "Clock is unavailable";
mJobQueue.reserve(16);
mJobProcessor = std::thread([this]() {
@@ -2241,17 +2250,44 @@ void IncrementalService::DataLoaderStub::setTargetStatusLocked(int status) {
<< status << " (current " << mCurrentStatus << ")";
}
-Milliseconds IncrementalService::DataLoaderStub::updateBindDelay() {
+std::optional<Milliseconds> IncrementalService::DataLoaderStub::needToBind() {
std::unique_lock lock(mMutex);
+
+ const auto now = mService.mClock->now();
+ const bool healthy = (mPreviousBindDelay == 0ms);
+
+ if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_BINDING &&
+ now - mCurrentStatusTs <= Constants::bindingTimeout) {
+ LOG(INFO) << "Binding still in progress. "
+ << (healthy ? "The DL is healthy/freshly bound, ok to retry for a few times."
+ : "Already unhealthy, don't do anything.");
+ // Binding still in progress.
+ if (!healthy) {
+ // Already unhealthy, don't do anything.
+ return {};
+ }
+ // The DL is healthy/freshly bound, ok to retry for a few times.
+ if (now - mPreviousBindTs <= Constants::bindGracePeriod) {
+ // Still within grace period.
+ if (now - mCurrentStatusTs >= Constants::bindRetryInterval) {
+ // Retry interval passed, retrying.
+ mCurrentStatusTs = now;
+ mPreviousBindDelay = 0ms;
+ return 0ms;
+ }
+ return {};
+ }
+ // fallthrough, mark as unhealthy, and retry with delay
+ }
+
const auto previousBindTs = mPreviousBindTs;
- const auto now = Clock::now();
mPreviousBindTs = now;
const auto nonCrashingInterval = std::max(castToMs(now - previousBindTs), 100ms);
if (previousBindTs.time_since_epoch() == Clock::duration::zero() ||
nonCrashingInterval > Constants::healthyDataLoaderUptime) {
mPreviousBindDelay = 0ms;
- return mPreviousBindDelay;
+ return 0ms;
}
constexpr auto minBindDelayMs = castToMs(Constants::minBindDelay);
@@ -2264,12 +2300,16 @@ Milliseconds IncrementalService::DataLoaderStub::updateBindDelay() {
const auto bindDelayJitterRangeMs = bindDelayMs / Constants::bindDelayJitterDivider;
const auto bindDelayJitterMs = rand() % (bindDelayJitterRangeMs * 2) - bindDelayJitterRangeMs;
mPreviousBindDelay = std::chrono::milliseconds(bindDelayMs + bindDelayJitterMs);
-
return mPreviousBindDelay;
}
bool IncrementalService::DataLoaderStub::bind() {
- const auto bindDelay = updateBindDelay();
+ const auto maybeBindDelay = needToBind();
+ if (!maybeBindDelay) {
+ LOG(DEBUG) << "Skipping bind to " << mParams.packageName << " because of pending bind.";
+ return true;
+ }
+ const auto bindDelay = *maybeBindDelay;
if (bindDelay > 1s) {
LOG(INFO) << "Delaying bind to " << mParams.packageName << " by "
<< bindDelay.count() / 1000 << "s";
@@ -2279,7 +2319,21 @@ bool IncrementalService::DataLoaderStub::bind() {
auto status = mService.mDataLoaderManager->bindToDataLoader(id(), mParams, bindDelay.count(),
this, &result);
if (!status.isOk() || !result) {
- LOG(ERROR) << "Failed to bind a data loader for mount " << id();
+ const bool healthy = (bindDelay == 0ms);
+ LOG(ERROR) << "Failed to bind a data loader for mount " << id()
+ << (healthy ? ", retrying." : "");
+
+ // Internal error, retry for healthy/new DLs.
+ // Let needToBind migrate it to unhealthy after too many retries.
+ if (healthy) {
+ if (mService.addTimedJob(*mService.mTimedQueue, id(), Constants::bindRetryInterval,
+ [this]() { fsmStep(); })) {
+ // Mark as binding so that we know it's not the DL's fault.
+ setCurrentStatus(IDataLoaderStatusListener::DATA_LOADER_BINDING);
+ return true;
+ }
+ }
+
return false;
}
return true;
@@ -2339,7 +2393,14 @@ bool IncrementalService::DataLoaderStub::fsmStep() {
// Do nothing, this is a reset state.
break;
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
- return destroy();
+ switch (currentStatus) {
+ case IDataLoaderStatusListener::DATA_LOADER_BINDING:
+ setCurrentStatus(IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
+ return true;
+ default:
+ return destroy();
+ }
+ break;
}
case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
switch (currentStatus) {
@@ -2353,6 +2414,7 @@ bool IncrementalService::DataLoaderStub::fsmStep() {
switch (currentStatus) {
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED:
case IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE:
+ case IDataLoaderStatusListener::DATA_LOADER_BINDING:
return bind();
case IDataLoaderStatusListener::DATA_LOADER_BOUND:
return create();
@@ -2372,7 +2434,8 @@ binder::Status IncrementalService::DataLoaderStub::onStatusChanged(MountId mount
fromServiceSpecificError(-EINVAL, "onStatusChange came to invalid DataLoaderStub");
}
if (id() != mountId) {
- LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
+ LOG(ERROR) << "onStatusChanged: mount ID mismatch: expected " << id()
+ << ", but got: " << mountId;
return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
}
if (newStatus == IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE) {
@@ -2396,11 +2459,13 @@ void IncrementalService::DataLoaderStub::setCurrentStatus(int newStatus) {
}
oldStatus = mCurrentStatus;
- mCurrentStatus = newStatus;
targetStatus = mTargetStatus;
-
listener = mStatusListener;
+ // Change the status.
+ mCurrentStatus = newStatus;
+ mCurrentStatusTs = mService.mClock->now();
+
if (mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNAVAILABLE ||
mCurrentStatus == IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE) {
// For unavailable, unbind from DataLoader to ensure proper re-commit.
@@ -2428,7 +2493,8 @@ binder::Status IncrementalService::DataLoaderStub::reportStreamHealth(MountId mo
"reportStreamHealth came to invalid DataLoaderStub");
}
if (id() != mountId) {
- LOG(ERROR) << "Mount ID mismatch: expected " << id() << ", but got: " << mountId;
+ LOG(ERROR) << "reportStreamHealth: mount ID mismatch: expected " << id()
+ << ", but got: " << mountId;
return binder::Status::fromServiceSpecificError(-EPERM, "Mount ID mismatch.");
}
{
@@ -2694,6 +2760,8 @@ static std::string toHexString(const RawMetadata& metadata) {
void IncrementalService::DataLoaderStub::onDump(int fd) {
dprintf(fd, " dataLoader: {\n");
dprintf(fd, " currentStatus: %d\n", mCurrentStatus);
+ dprintf(fd, " currentStatusTs: %lldmcs\n",
+ (long long)(elapsedMcs(mCurrentStatusTs, Clock::now())));
dprintf(fd, " targetStatus: %d\n", mTargetStatus);
dprintf(fd, " targetStatusTs: %lldmcs\n",
(long long)(elapsedMcs(mTargetStatusTs, Clock::now())));
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 14e5a7734172..4eb513808342 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -267,7 +267,10 @@ private:
BootClockTsUs getOldestTsFromLastPendingReads();
Milliseconds elapsedMsSinceKernelTs(TimePoint now, BootClockTsUs kernelTsUs);
- Milliseconds updateBindDelay();
+ // If the stub has to bind to the DL.
+ // Returns {} if bind operation is already in progress.
+ // Or bind delay in ms.
+ std::optional<Milliseconds> needToBind();
void registerForPendingReads();
void unregisterFromPendingReads();
@@ -283,6 +286,7 @@ private:
std::condition_variable mStatusCondition;
int mCurrentStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
+ TimePoint mCurrentStatusTs = {};
int mTargetStatus = content::pm::IDataLoaderStatusListener::DATA_LOADER_DESTROYED;
TimePoint mTargetStatusTs = {};
@@ -443,6 +447,7 @@ private:
const std::unique_ptr<TimedQueueWrapper> mTimedQueue;
const std::unique_ptr<TimedQueueWrapper> mProgressUpdateJobQueue;
const std::unique_ptr<FsWrapper> mFs;
+ const std::unique_ptr<ClockWrapper> mClock;
const std::string mIncrementalDir;
mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index d61328942e5c..80f409ff1c61 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -329,6 +329,14 @@ public:
}
};
+class RealClockWrapper final : public ClockWrapper {
+public:
+ RealClockWrapper() = default;
+ ~RealClockWrapper() = default;
+
+ TimePoint now() const final { return Clock::now(); }
+};
+
RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager, JNIEnv* env)
: mServiceManager(std::move(serviceManager)), mJvm(RealJniWrapper::getJvm(env)) {}
@@ -388,6 +396,10 @@ std::unique_ptr<FsWrapper> RealServiceManager::getFs() {
return std::make_unique<RealFsWrapper>();
}
+std::unique_ptr<ClockWrapper> RealServiceManager::getClock() {
+ return std::make_unique<RealClockWrapper>();
+}
+
static JavaVM* getJavaVm(JNIEnv* env) {
CHECK(env);
JavaVM* jvm = nullptr;
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 245bb3105be5..d113f992de71 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -158,6 +158,12 @@ public:
virtual void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const = 0;
};
+class ClockWrapper {
+public:
+ virtual ~ClockWrapper() = default;
+ virtual TimePoint now() const = 0;
+};
+
class ServiceManagerWrapper {
public:
virtual ~ServiceManagerWrapper() = default;
@@ -170,6 +176,7 @@ public:
virtual std::unique_ptr<TimedQueueWrapper> getTimedQueue() = 0;
virtual std::unique_ptr<TimedQueueWrapper> getProgressUpdateJobQueue() = 0;
virtual std::unique_ptr<FsWrapper> getFs() = 0;
+ virtual std::unique_ptr<ClockWrapper> getClock() = 0;
};
// --- Real stuff ---
@@ -187,6 +194,7 @@ public:
std::unique_ptr<TimedQueueWrapper> getTimedQueue() final;
std::unique_ptr<TimedQueueWrapper> getProgressUpdateJobQueue() final;
std::unique_ptr<FsWrapper> getFs() final;
+ std::unique_ptr<ClockWrapper> getClock() final;
private:
template <class INTERFACE>
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 5236983c83ff..25b34b5669b8 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -248,6 +248,27 @@ public:
}
return binder::Status::ok();
}
+ binder::Status bindToDataLoaderNotOkWithNoDelay(int32_t mountId,
+ const DataLoaderParamsParcel& params,
+ int bindDelayMs,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) {
+ CHECK(bindDelayMs == 0) << bindDelayMs;
+ *_aidl_return = false;
+ return binder::Status::ok();
+ }
+ binder::Status bindToDataLoaderBindingWithNoDelay(int32_t mountId,
+ const DataLoaderParamsParcel& params,
+ int bindDelayMs,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) {
+ CHECK(bindDelayMs == 0) << bindDelayMs;
+ *_aidl_return = true;
+ if (listener) {
+ listener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_BINDING);
+ }
+ return binder::Status::ok();
+ }
binder::Status bindToDataLoaderOkWith10sDelay(int32_t mountId,
const DataLoaderParamsParcel& params,
int bindDelayMs,
@@ -557,6 +578,21 @@ public:
}
};
+class MockClockWrapper : public ClockWrapper {
+public:
+ MOCK_CONST_METHOD0(now, TimePoint());
+
+ void start() { ON_CALL(*this, now()).WillByDefault(Invoke(this, &MockClockWrapper::getClock)); }
+ template <class Delta>
+ void advance(Delta delta) {
+ mClock += delta;
+ }
+
+ TimePoint getClock() const { return mClock; }
+
+ TimePoint mClock = Clock::now();
+};
+
class MockStorageHealthListener : public os::incremental::BnStorageHealthListener {
public:
MOCK_METHOD2(onHealthStatus, binder::Status(int32_t storageId, int32_t status));
@@ -594,7 +630,7 @@ public:
std::unique_ptr<MockLooperWrapper> looper,
std::unique_ptr<MockTimedQueueWrapper> timedQueue,
std::unique_ptr<MockTimedQueueWrapper> progressUpdateJobQueue,
- std::unique_ptr<MockFsWrapper> fs)
+ std::unique_ptr<MockFsWrapper> fs, std::unique_ptr<MockClockWrapper> clock)
: mVold(std::move(vold)),
mDataLoaderManager(std::move(dataLoaderManager)),
mIncFs(std::move(incfs)),
@@ -603,7 +639,8 @@ public:
mLooper(std::move(looper)),
mTimedQueue(std::move(timedQueue)),
mProgressUpdateJobQueue(std::move(progressUpdateJobQueue)),
- mFs(std::move(fs)) {}
+ mFs(std::move(fs)),
+ mClock(std::move(clock)) {}
std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
std::unique_ptr<DataLoaderManagerWrapper> getDataLoaderManager() final {
return std::move(mDataLoaderManager);
@@ -619,6 +656,7 @@ public:
return std::move(mProgressUpdateJobQueue);
}
std::unique_ptr<FsWrapper> getFs() final { return std::move(mFs); }
+ std::unique_ptr<ClockWrapper> getClock() final { return std::move(mClock); }
private:
std::unique_ptr<MockVoldService> mVold;
@@ -630,6 +668,7 @@ private:
std::unique_ptr<MockTimedQueueWrapper> mTimedQueue;
std::unique_ptr<MockTimedQueueWrapper> mProgressUpdateJobQueue;
std::unique_ptr<MockFsWrapper> mFs;
+ std::unique_ptr<MockClockWrapper> mClock;
};
// --- IncrementalServiceTest ---
@@ -657,6 +696,8 @@ public:
mProgressUpdateJobQueue = progressUpdateJobQueue.get();
auto fs = std::make_unique<NiceMock<MockFsWrapper>>();
mFs = fs.get();
+ auto clock = std::make_unique<NiceMock<MockClockWrapper>>();
+ mClock = clock.get();
mIncrementalService = std::make_unique<
IncrementalService>(MockServiceManager(std::move(vold),
std::move(dataloaderManager),
@@ -664,12 +705,13 @@ public:
std::move(jni), std::move(looper),
std::move(timedQueue),
std::move(progressUpdateJobQueue),
- std::move(fs)),
+ std::move(fs), std::move(clock)),
mRootDir.path);
mDataLoaderParcel.packageName = "com.test";
mDataLoaderParcel.arguments = "uri";
mDataLoaderManager->unbindFromDataLoaderSuccess();
mIncrementalService->onSystemReady();
+ mClock->start();
setupSuccess();
}
@@ -724,6 +766,7 @@ protected:
NiceMock<MockTimedQueueWrapper>* mTimedQueue = nullptr;
NiceMock<MockTimedQueueWrapper>* mProgressUpdateJobQueue = nullptr;
NiceMock<MockFsWrapper>* mFs = nullptr;
+ NiceMock<MockClockWrapper>* mClock = nullptr;
NiceMock<MockDataLoader>* mDataLoader = nullptr;
std::unique_ptr<IncrementalService> mIncrementalService;
TemporaryDir mRootDir;
@@ -853,6 +896,119 @@ TEST_F(IncrementalServiceTest, testDataLoaderDestroyedAndDelayed) {
mDataLoaderManager->setDataLoaderStatusDestroyed();
}
+TEST_F(IncrementalServiceTest, testDataLoaderOnRestart) {
+ mIncFs->waitForPendingReadsSuccess();
+ mIncFs->openMountSuccess();
+
+ constexpr auto bindRetryInterval = 5s;
+
+ EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(10);
+ EXPECT_CALL(*mDataLoaderManager, unbindFromDataLoader(_)).Times(1);
+ EXPECT_CALL(*mDataLoader, create(_, _, _, _)).Times(6);
+ EXPECT_CALL(*mDataLoader, start(_)).Times(6);
+ EXPECT_CALL(*mDataLoader, destroy(_)).Times(1);
+ EXPECT_CALL(*mVold, unmountIncFs(_)).Times(2);
+ EXPECT_CALL(*mTimedQueue, addJob(_, _, _)).Times(2);
+ TemporaryDir tempDir;
+ int storageId =
+ mIncrementalService->createStorage(tempDir.path, mDataLoaderParcel,
+ IncrementalService::CreateOptions::CreateNew);
+ ASSERT_GE(storageId, 0);
+
+ // First binds to DataLoader fails... because it's restart.
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderNotOkWithNoDelay));
+
+ // Request DL start.
+ mIncrementalService->startLoading(storageId, std::move(mDataLoaderParcel), {}, {}, {}, {});
+
+ // Retry callback present.
+ ASSERT_EQ(storageId, mTimedQueue->mId);
+ ASSERT_EQ(mTimedQueue->mAfter, bindRetryInterval);
+ auto retryCallback = mTimedQueue->mWhat;
+ mTimedQueue->clearJob(storageId);
+
+ // Expecting the same bindToDataLoaderNotOkWithNoDelay call.
+ mClock->advance(5s);
+
+ retryCallback();
+ // Retry callback present.
+ ASSERT_EQ(storageId, mTimedQueue->mId);
+ ASSERT_EQ(mTimedQueue->mAfter, bindRetryInterval);
+ retryCallback = mTimedQueue->mWhat;
+ mTimedQueue->clearJob(storageId);
+
+ // Returning "binding" so that we can retry.
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderBindingWithNoDelay));
+
+ // Expecting bindToDataLoaderBindingWithNoDelay call.
+ mClock->advance(5s);
+
+ retryCallback();
+ // No retry callback.
+ ASSERT_EQ(mTimedQueue->mAfter, 0ms);
+ ASSERT_EQ(mTimedQueue->mWhat, nullptr);
+
+ // Should not change the bindToDataLoader call count
+ ASSERT_NE(nullptr, mLooper->mCallback);
+ ASSERT_NE(nullptr, mLooper->mCallbackData);
+ auto looperCb = mLooper->mCallback;
+ auto looperCbData = mLooper->mCallbackData;
+ looperCb(-1, -1, looperCbData);
+
+ // Expecting the same bindToDataLoaderBindingWithNoDelay call.
+ mClock->advance(5s);
+
+ // Use pending reads callback to trigger binding.
+ looperCb(-1, -1, looperCbData);
+
+ // No retry callback.
+ ASSERT_EQ(mTimedQueue->mAfter, 0ms);
+ ASSERT_EQ(mTimedQueue->mWhat, nullptr);
+
+ // Now we are out of 10m "retry" budget, let's finally bind.
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager, &MockDataLoaderManager::bindToDataLoaderOk));
+ mClock->advance(11min);
+
+ // Use pending reads callback to trigger binding.
+ looperCb(-1, -1, looperCbData);
+
+ // No retry callback.
+ ASSERT_EQ(mTimedQueue->mAfter, 0ms);
+ ASSERT_EQ(mTimedQueue->mWhat, nullptr);
+
+ // And test the rest of the backoff.
+ // Simulated crash/other connection breakage.
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderOkWith10sDelay));
+ mDataLoaderManager->setDataLoaderStatusDestroyed();
+
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderOkWith100sDelay));
+ mDataLoaderManager->setDataLoaderStatusDestroyed();
+
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderOkWith1000sDelay));
+ mDataLoaderManager->setDataLoaderStatusDestroyed();
+
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderOkWith10000sDelay));
+ mDataLoaderManager->setDataLoaderStatusDestroyed();
+
+ ON_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _))
+ .WillByDefault(Invoke(mDataLoaderManager,
+ &MockDataLoaderManager::bindToDataLoaderOkWith10000sDelay));
+ mDataLoaderManager->setDataLoaderStatusDestroyed();
+}
+
TEST_F(IncrementalServiceTest, testStartDataLoaderCreate) {
mDataLoader->initializeCreateOkNoStatus();
EXPECT_CALL(*mDataLoaderManager, bindToDataLoader(_, _, _, _, _)).Times(1);
diff --git a/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java
index 169b85eb7e06..b07fe19393b2 100644
--- a/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java
+++ b/services/smartspace/java/com/android/server/smartspace/SmartspaceManagerService.java
@@ -19,6 +19,7 @@ package com.android.server.smartspace;
import static android.Manifest.permission.MANAGE_SMARTSPACE;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.content.Context.SMARTSPACE_SERVICE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -161,11 +162,13 @@ public class SmartspaceManagerService extends
Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
}
- if (!(mServiceNameResolver.isTemporary(userId)
+ Context ctx = getContext();
+ if (!(ctx.checkCallingPermission(MANAGE_SMARTSPACE) == PERMISSION_GRANTED
+ || mServiceNameResolver.isTemporary(userId)
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
- String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid();
+ String msg = "Permission Denial: Cannot call " + func + " from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 9a52643b57f2..9f428c7cbded 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.parsing.ParsingPackage;
@@ -141,6 +142,10 @@ public class AppsFilterTest {
return pkg(packageName).addReceiver(receiver);
}
+ private static ParsingPackage pkgWithSharedLibrary(String packageName, String libName) {
+ return pkg(packageName).addLibraryName(libName);
+ }
+
private static ParsedActivity createActivity(String packageName, IntentFilter[] filters) {
ParsedActivity activity = new ParsedActivity();
activity.setPackageName(packageName);
@@ -413,6 +418,118 @@ public class AppsFilterTest {
}
@Test
+ public void testNoUsesLibrary_Filters() throws Exception {
+ final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
+ mMockExecutor);
+
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ final Signature mockSignature = Mockito.mock(Signature.class);
+ final SigningDetails mockSigningDetails = new SigningDetails(
+ new Signature[]{mockSignature},
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
+
+ final PackageSetting target = simulateAddPackage(appsFilter,
+ pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
+ DUMMY_TARGET_APPID,
+ setting -> setting.setSigningDetails(mockSigningDetails)
+ .setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+ final PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
+
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ }
+
+ @Test
+ public void testUsesLibrary_DoesntFilter() throws Exception {
+ final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
+ mMockExecutor);
+
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ final Signature mockSignature = Mockito.mock(Signature.class);
+ final SigningDetails mockSigningDetails = new SigningDetails(
+ new Signature[]{mockSignature},
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
+
+ final PackageSetting target = simulateAddPackage(appsFilter,
+ pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
+ DUMMY_TARGET_APPID,
+ setting -> setting.setSigningDetails(mockSigningDetails)
+ .setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+ final PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package").addUsesLibrary("com.some.shared_library"),
+ DUMMY_CALLING_APPID);
+
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ }
+
+ @Test
+ public void testUsesOptionalLibrary_DoesntFilter() throws Exception {
+ final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
+ mMockExecutor);
+
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ final Signature mockSignature = Mockito.mock(Signature.class);
+ final SigningDetails mockSigningDetails = new SigningDetails(
+ new Signature[]{mockSignature},
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
+
+ final PackageSetting target = simulateAddPackage(appsFilter,
+ pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
+ DUMMY_TARGET_APPID,
+ setting -> setting.setSigningDetails(mockSigningDetails)
+ .setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+ final PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package").addUsesOptionalLibrary("com.some.shared_library"),
+ DUMMY_CALLING_APPID);
+
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ }
+
+ @Test
+ public void testUsesLibrary_ShareUid_DoesntFilter() throws Exception {
+ final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
+ new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
+ mMockExecutor);
+
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ final Signature mockSignature = Mockito.mock(Signature.class);
+ final SigningDetails mockSigningDetails = new SigningDetails(
+ new Signature[]{mockSignature},
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
+
+ final PackageSetting target = simulateAddPackage(appsFilter,
+ pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
+ DUMMY_TARGET_APPID,
+ setting -> setting.setSigningDetails(mockSigningDetails)
+ .setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
+ final PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package_a").setSharedUserId("com.some.uid"),
+ DUMMY_CALLING_APPID);
+ simulateAddPackage(appsFilter, pkg("com.some.other.package_b")
+ .setSharedUserId("com.some.uid").addUsesLibrary("com.some.shared_library"),
+ DUMMY_CALLING_APPID);
+
+ // Although package_a doesn't use library, it should be granted visibility. It's because
+ // package_a shares userId with package_b, and package_b uses that shared library.
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ }
+
+ @Test
public void testForceQueryable_SystemDoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
index 2a3c2c46ce4e..b54b6969e7df 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
@@ -49,6 +49,8 @@ final class FakeVibratorControllerProvider {
private int mCapabilities;
private int[] mSupportedEffects;
private int[] mSupportedPrimitives;
+ private float mResonantFrequency;
+ private float mQFactor;
private final class FakeNativeWrapper extends VibratorController.NativeWrapper {
public int vibratorId;
@@ -89,6 +91,14 @@ final class FakeVibratorControllerProvider {
return mSupportedPrimitives;
}
+ public float getResonantFrequency() {
+ return mResonantFrequency;
+ }
+
+ public float getQFactor() {
+ return mQFactor;
+ }
+
public long perform(long effect, long strength, long vibrationId) {
if (mSupportedEffects == null
|| Arrays.binarySearch(mSupportedEffects, (int) effect) < 0) {
@@ -198,6 +208,16 @@ final class FakeVibratorControllerProvider {
mSupportedPrimitives = primitives;
}
+ /** Set the resonant frequency of the fake vibrator hardware. */
+ public void setResonantFrequency(float resonantFrequency) {
+ mResonantFrequency = resonantFrequency;
+ }
+
+ /** Set the Q factor of the fake vibrator hardware. */
+ public void setQFactor(float qFactor) {
+ mQFactor = qFactor;
+ }
+
/**
* Return the amplitudes set by this controller, including zeroes for each time the vibrator was
* turned off.
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index a28d18fb74d3..ce6639c6b4aa 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -266,6 +266,8 @@ public class VibratorManagerServiceTest {
vibrator.setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS, IVibrator.CAP_AMPLITUDE_CONTROL);
vibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
vibrator.setSupportedPrimitives(VibrationEffect.Composition.PRIMITIVE_CLICK);
+ vibrator.setResonantFrequency(123.f);
+ vibrator.setQFactor(Float.NaN);
VibratorInfo info = createSystemReadyService().getVibratorInfo(1);
assertNotNull(info);
@@ -279,6 +281,8 @@ public class VibratorManagerServiceTest {
info.isEffectSupported(VibrationEffect.EFFECT_TICK));
assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK));
assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK));
+ assertEquals(123.f, info.getResonantFrequency(), 0.01 /*tolerance*/);
+ assertTrue(Float.isNaN(info.getQFactor()));
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index e510b4fbfdd5..5462f47e3a4c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -61,6 +61,7 @@ import android.media.AudioAttributes;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Handler;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.VibrationEffect;
@@ -81,10 +82,12 @@ import com.android.internal.logging.InstanceIdSequenceFake;
import com.android.internal.util.IntPair;
import com.android.server.UiServiceTestCase;
import com.android.server.lights.LogicalLight;
+import com.android.server.pm.PackageManagerService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -412,12 +415,16 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
}
private void verifyVibrate() {
+ ArgumentCaptor<AudioAttributes> captor = ArgumentCaptor.forClass(AudioAttributes.class);
verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), argThat(mVibrateOnceMatcher),
- anyString(), any(AudioAttributes.class));
+ anyString(), captor.capture());
+ assertEquals(0, (captor.getValue().getAllFlags()
+ & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
}
private void verifyVibrate(int times) {
- verify(mVibrator, times(times)).vibrate(anyInt(), anyString(), any(), anyString(),
+ verify(mVibrator, times(times)).vibrate(eq(Process.SYSTEM_UID),
+ eq(PackageManagerService.PLATFORM_PACKAGE_NAME), any(), anyString(),
any(AudioAttributes.class));
}
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index 201c5db74e16..809f2bc1bb7d 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -19,9 +19,12 @@ package android.telecom;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -30,6 +33,7 @@ import com.android.internal.telecom.ICallDiagnosticService;
import com.android.internal.telecom.ICallDiagnosticServiceAdapter;
import java.util.Map;
+import java.util.concurrent.Executor;
/**
* The platform supports a single OEM provided {@link CallDiagnosticService}, as defined by the
@@ -51,6 +55,11 @@ import java.util.Map;
* </service>
* }
* </pre>
+ * <p>
+ * <h2>Threading Model</h2>
+ * By default, all incoming IPC from Telecom in this service and in the {@link DiagnosticCall}
+ * instances will take place on the main thread. You can override {@link #getExecutor()} in your
+ * implementation to provide your own {@link Executor}.
* @hide
*/
@SystemApi
@@ -83,7 +92,7 @@ public abstract class CallDiagnosticService extends Service {
@Override
public void updateCallAudioState(CallAudioState callAudioState) throws RemoteException {
- onCallAudioStateChanged(callAudioState);
+ getExecutor().execute(() -> onCallAudioStateChanged(callAudioState));
}
@Override
@@ -133,8 +142,18 @@ public abstract class CallDiagnosticService extends Service {
*/
private final Map<String, Call.Details> mCallByTelecomCallId = new ArrayMap<>();
private final Map<String, DiagnosticCall> mDiagnosticCallByTelecomCallId = new ArrayMap<>();
+ private final Object mLock = new Object();
private ICallDiagnosticServiceAdapter mAdapter;
+ /**
+ * Handles binding to the {@link CallDiagnosticService}.
+ *
+ * @param intent The Intent that was used to bind to this service,
+ * as given to {@link android.content.Context#bindService
+ * Context.bindService}. Note that any extras that were included with
+ * the Intent at that point will <em>not</em> be seen here.
+ * @return
+ */
@Nullable
@Override
public IBinder onBind(@NonNull Intent intent) {
@@ -143,11 +162,29 @@ public abstract class CallDiagnosticService extends Service {
}
/**
+ * Returns the {@link Executor} to use for incoming IPS from Telecom into your service
+ * implementation.
+ * <p>
+ * Override this method in your {@link CallDiagnosticService} implementation to provide the
+ * executor you want to use for incoming IPC.
+ *
+ * @return the {@link Executor} to use for incoming IPC from Telecom to
+ * {@link CallDiagnosticService} and {@link DiagnosticCall}.
+ */
+ @SuppressLint("OnNameExpected")
+ @NonNull public Executor getExecutor() {
+ return new HandlerExecutor(Handler.createAsync(getMainLooper()));
+ }
+
+ /**
* Telecom calls this method on the {@link CallDiagnosticService} with details about a new call
* which was added to Telecom.
* <p>
* The {@link CallDiagnosticService} returns an implementation of {@link DiagnosticCall} to be
* used for the lifespan of this call.
+ * <p>
+ * Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
+ * {@link CallDiagnosticService#getExecutor()} for more information.
*
* @param call The details of the new call.
* @return An instance of {@link DiagnosticCall} which the {@link CallDiagnosticService}
@@ -160,6 +197,10 @@ public abstract class CallDiagnosticService extends Service {
/**
* Telecom calls this method when a previous created {@link DiagnosticCall} is no longer needed.
* This happens when Telecom is no longer tracking the call in question.
+ * <p>
+ * Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
+ * {@link CallDiagnosticService#getExecutor()} for more information.
+ *
* @param call The diagnostic call which is no longer tracked by Telecom.
*/
public abstract void onRemoveDiagnosticCall(@NonNull DiagnosticCall call);
@@ -169,6 +210,9 @@ public abstract class CallDiagnosticService extends Service {
* changes.
* <p>
* Audio state is common to all calls.
+ * <p>
+ * Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
+ * {@link CallDiagnosticService#getExecutor()} for more information.
*
* @param audioState The new audio state.
*/
@@ -178,6 +222,10 @@ public abstract class CallDiagnosticService extends Service {
/**
* Telecom calls this method when a {@link BluetoothCallQualityReport} is received from the
* bluetooth stack.
+ * <p>
+ * Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
+ * {@link CallDiagnosticService#getExecutor()} for more information.
+ *
* @param qualityReport the {@link BluetoothCallQualityReport}.
*/
public abstract void onBluetoothCallQualityReportReceived(
@@ -199,15 +247,22 @@ public abstract class CallDiagnosticService extends Service {
String telecomCallId = parcelableCall.getId();
Log.i(this, "handleCallAdded: callId=%s - added", telecomCallId);
Call.Details newCallDetails = Call.Details.createFromParcelableCall(parcelableCall);
- mCallByTelecomCallId.put(telecomCallId, newCallDetails);
-
- DiagnosticCall diagnosticCall = onInitializeDiagnosticCall(newCallDetails);
- if (diagnosticCall == null) {
- throw new IllegalArgumentException("A valid DiagnosticCall instance was not provided.");
+ synchronized (mLock) {
+ mCallByTelecomCallId.put(telecomCallId, newCallDetails);
}
- diagnosticCall.setListener(mDiagnosticCallListener);
- diagnosticCall.setCallId(telecomCallId);
- mDiagnosticCallByTelecomCallId.put(telecomCallId, diagnosticCall);
+
+ getExecutor().execute(() -> {
+ DiagnosticCall diagnosticCall = onInitializeDiagnosticCall(newCallDetails);
+ if (diagnosticCall == null) {
+ throw new IllegalArgumentException(
+ "A valid DiagnosticCall instance was not provided.");
+ }
+ synchronized (mLock) {
+ diagnosticCall.setListener(mDiagnosticCallListener);
+ diagnosticCall.setCallId(telecomCallId);
+ mDiagnosticCallByTelecomCallId.put(telecomCallId, diagnosticCall);
+ }
+ });
}
/**
@@ -220,10 +275,12 @@ public abstract class CallDiagnosticService extends Service {
String telecomCallId = parcelableCall.getId();
Log.i(this, "handleCallUpdated: callId=%s - updated", telecomCallId);
Call.Details newCallDetails = Call.Details.createFromParcelableCall(parcelableCall);
-
- DiagnosticCall diagnosticCall = mDiagnosticCallByTelecomCallId.get(telecomCallId);
- mCallByTelecomCallId.put(telecomCallId, newCallDetails);
- diagnosticCall.handleCallUpdated(newCallDetails);
+ DiagnosticCall diagnosticCall;
+ synchronized (mLock) {
+ diagnosticCall = mDiagnosticCallByTelecomCallId.get(telecomCallId);
+ mCallByTelecomCallId.put(telecomCallId, newCallDetails);
+ }
+ getExecutor().execute(() -> diagnosticCall.handleCallUpdated(newCallDetails));
}
/**
@@ -236,10 +293,19 @@ public abstract class CallDiagnosticService extends Service {
if (mCallByTelecomCallId.containsKey(telecomCallId)) {
mCallByTelecomCallId.remove(telecomCallId);
}
- if (mDiagnosticCallByTelecomCallId.containsKey(telecomCallId)) {
- DiagnosticCall call = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
- // Inform the service of the removed call.
- onRemoveDiagnosticCall(call);
+
+ DiagnosticCall diagnosticCall;
+ synchronized (mLock) {
+ if (mDiagnosticCallByTelecomCallId.containsKey(telecomCallId)) {
+ diagnosticCall = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
+ } else {
+ diagnosticCall = null;
+ }
+ }
+
+ // Inform the service of the removed call.
+ if (diagnosticCall != null) {
+ getExecutor().execute(() -> onRemoveDiagnosticCall(diagnosticCall));
}
}
@@ -252,8 +318,14 @@ public abstract class CallDiagnosticService extends Service {
*/
private void handleReceivedD2DMessage(@NonNull String callId, int message, int value) {
Log.i(this, "handleReceivedD2DMessage: callId=%s, msg=%d/%d", callId, message, value);
- DiagnosticCall diagnosticCall = mDiagnosticCallByTelecomCallId.get(callId);
- diagnosticCall.onReceiveDeviceToDeviceMessage(message, value);
+ DiagnosticCall diagnosticCall;
+ synchronized (mLock) {
+ diagnosticCall = mDiagnosticCallByTelecomCallId.get(callId);
+ }
+ if (diagnosticCall != null) {
+ getExecutor().execute(
+ () -> diagnosticCall.onReceiveDeviceToDeviceMessage(message, value));
+ }
}
/**
@@ -265,7 +337,7 @@ public abstract class CallDiagnosticService extends Service {
private void handleBluetoothCallQualityReport(@NonNull BluetoothCallQualityReport
qualityReport) {
Log.i(this, "handleBluetoothCallQualityReport; report=%s", qualityReport);
- onBluetoothCallQualityReportReceived(qualityReport);
+ getExecutor().execute(() -> onBluetoothCallQualityReportReceived(qualityReport));
}
/**
diff --git a/telecomm/java/android/telecom/DiagnosticCall.java b/telecomm/java/android/telecom/DiagnosticCall.java
index a4952899eb46..af46b7759fb5 100644
--- a/telecomm/java/android/telecom/DiagnosticCall.java
+++ b/telecomm/java/android/telecom/DiagnosticCall.java
@@ -26,15 +26,27 @@ import android.telephony.ims.ImsReasonInfo;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* A {@link DiagnosticCall} provides a way for a {@link CallDiagnosticService} to receive diagnostic
- * information about a mobile call on the device. The {@link CallDiagnosticService} can generate
- * mid-call diagnostic messages using the {@link #displayDiagnosticMessage(int, CharSequence)} API
- * which provides the user with valuable information about conditions impacting their call and
- * corrective actions. For example, if the {@link CallDiagnosticService} determines that conditions
- * on the call are degrading, it can inform the user that the call may soon drop and that they
- * can try using a different calling method (e.g. VOIP or WIFI).
+ * information about a mobile call on the device. A {@link DiagnosticCall} is similar to a
+ * {@link Call}, however it does not expose call control capabilities and exposes extra diagnostic
+ * and messaging capabilities not present on a {@link Call}. The {@link CallDiagnosticService}
+ * creates a {@link DiagnosticCall} for each {@link Call} on the device. This means that for each
+ * in progress call on the device, the {@link CallDiagnosticService} will create an instance of
+ * {@link DiagnosticCall}.
+ * <p>
+ * The {@link CallDiagnosticService} can generate mid-call diagnostic messages using the
+ * {@link #displayDiagnosticMessage(int, CharSequence)} API which provides the user with valuable
+ * information about conditions impacting their call and corrective actions. For example, if the
+ * {@link CallDiagnosticService} determines that conditions on the call are degrading, it can inform
+ * the user that the call may soon drop and that they can try using a different calling method
+ * (e.g. VOIP or WIFI).
+ * <h2>Threading Model</h2>
+ * All incoming IPC from Telecom in this class will use the same {@link Executor} as the
+ * {@link CallDiagnosticService}. See {@link CallDiagnosticService#setExecutor(Executor)} for more
+ * information.
* @hide
*/
@SystemApi
@@ -53,15 +65,19 @@ public abstract class DiagnosticCall {
/**
* Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
* {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the radio access type
- * used for the current call. Based loosely on the
- * {@link android.telephony.TelephonyManager#getNetworkType(int)} for the call, provides a
- * high level summary of the call radio access type.
+ * used for the current call. The call network type communicated here is an intentional
+ * simplification of the {@link android.telephony.TelephonyManager#getNetworkType(int)} which
+ * removes some of the resolution inherent in those values; the
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE_CA} value, for example is
+ * collapsed into the {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE} value for
+ * efficiency of transport. For a discussion on the necessity of this simplification, see
+ * {@link #sendDeviceToDeviceMessage(int, int)}.
* <p>
- * Valid values:
+ * Valid values are below:
* <UL>
- * <LI>{@link #NETWORK_TYPE_LTE}</LI>
- * <LI>{@link #NETWORK_TYPE_IWLAN}</LI>
- * <LI>{@link #NETWORK_TYPE_NR}</LI>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}</LI>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_IWLAN}</LI>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_NR}</LI>
* </UL>
*/
public static final int MESSAGE_CALL_NETWORK_TYPE = 1;
@@ -69,14 +85,21 @@ public abstract class DiagnosticCall {
/**
* Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
* {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the call audio codec
- * used for the current call. Based loosely on the {@link Connection#EXTRA_AUDIO_CODEC} for a
- * call.
+ * used for the current call.
+ * <p>
+ * The audio codec communicated here is an intentional simplification of the
+ * {@link Connection#EXTRA_AUDIO_CODEC} for a call and focuses on communicating the most common
+ * variants of these audio codecs. Other variants of these codecs are reported as the next
+ * closest variant. For example, the {@link Connection#AUDIO_CODEC_EVS_FB} full band codec
+ * is reported via device to device communication as {@link Connection#AUDIO_CODEC_EVS_WB}.
+ * For a discussion on the necessity of this simplification, see
+ * {@link #sendDeviceToDeviceMessage(int, int)}.
* <p>
* Valid values:
* <UL>
- * <LI>{@link #AUDIO_CODEC_EVS}</LI>
- * <LI>{@link #AUDIO_CODEC_AMR_WB}</LI>
- * <LI>{@link #AUDIO_CODEC_AMR_NB}</LI>
+ * <LI>{@link Connection#AUDIO_CODEC_EVS_WB}</LI>
+ * <LI>{@link Connection#AUDIO_CODEC_AMR_WB}</LI>
+ * <LI>{@link Connection#AUDIO_CODEC_AMR}</LI>
* </UL>
*/
public static final int MESSAGE_CALL_AUDIO_CODEC = 2;
@@ -122,41 +145,6 @@ public abstract class DiagnosticCall {
public @interface MessageType {}
/**
- * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate an LTE network is being used for the
- * call.
- */
- public static final int NETWORK_TYPE_LTE = 1;
-
- /**
- * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate WIFI calling is in use for the call.
- */
- public static final int NETWORK_TYPE_IWLAN = 2;
-
- /**
- * Used with {@link #MESSAGE_CALL_NETWORK_TYPE} to indicate a 5G NR (new radio) network is in
- * used for the call.
- */
- public static final int NETWORK_TYPE_NR = 3;
-
- /**
- * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the
- * Enhanced Voice Services (EVS) codec for the call.
- */
- public static final int AUDIO_CODEC_EVS = 1;
-
- /**
- * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the AMR
- * (adaptive multi-rate) WB (wide band) audio codec.
- */
- public static final int AUDIO_CODEC_AMR_WB = 2;
-
- /**
- * Used with {@link #MESSAGE_CALL_AUDIO_CODEC} to indicate call audio is using the AMR
- * (adaptive multi-rate) NB (narrow band) audio codec.
- */
- public static final int AUDIO_CODEC_AMR_NB = 3;
-
- /**
* Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is low.
*/
public static final int BATTERY_STATE_LOW = 1;
@@ -183,7 +171,6 @@ public abstract class DiagnosticCall {
private Listener mListener;
private String mCallId;
- private Call.Details mCallDetails;
/**
* @hide
@@ -210,16 +197,10 @@ public abstract class DiagnosticCall {
}
/**
- * Returns the latest {@link Call.Details} associated with this {@link DiagnosticCall} as
- * reported by {@link #onCallDetailsChanged(Call.Details)}.
- * @return The latest {@link Call.Details}.
- */
- public @NonNull Call.Details getCallDetails() {
- return mCallDetails;
- }
-
- /**
* Telecom calls this method when the details of a call changes.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
*/
public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details details);
@@ -234,6 +215,9 @@ public abstract class DiagnosticCall {
* devices communicating are using a different version of the protocol, messages the recipient
* are not aware of are silently discarded. This means an older client talking to a new client
* will not receive newer messages and values sent by the new client.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
*/
public abstract void onReceiveDeviceToDeviceMessage(
@MessageType int message,
@@ -253,39 +237,19 @@ public abstract class DiagnosticCall {
* platform due to the extreme bandwidth constraints inherent with underlying device to device
* communication transports used by the telephony framework. Device to device communication is
* either accomplished by adding RFC8285 compliant RTP header extensions to the audio packets
- * for a call, or using the DTMF digits A-D as a communication pathway. Signalling requirements
- * for DTMF digits place a significant limitation on the amount of information which can be
- * communicated during a call.
+ * for a call, or using the DTMF digits A-D as a communication pathway. RTP header extension
+ * packets ride alongside a the audio for a call, and are thus limited to roughly a byte for
+ * a message. Signalling requirements for DTMF digits place even more significant limitations
+ * on the amount of information which can be communicated during a call, offering only a few
+ * bits of potential information per message. The messages and values are constrained in order
+ * to meet the limited bandwidth inherent with DTMF signalling.
* <p>
- * Allowed message types and values are:
+ * Allowed message types are:
* <ul>
- * <li>{@link #MESSAGE_CALL_NETWORK_TYPE}
- * <ul>
- * <li>{@link #NETWORK_TYPE_LTE}</li>
- * <li>{@link #NETWORK_TYPE_IWLAN}</li>
- * <li>{@link #NETWORK_TYPE_NR}</li>
- * </ul>
- * </li>
- * <li>{@link #MESSAGE_CALL_AUDIO_CODEC}
- * <ul>
- * <li>{@link #AUDIO_CODEC_EVS}</li>
- * <li>{@link #AUDIO_CODEC_AMR_WB}</li>
- * <li>{@link #AUDIO_CODEC_AMR_NB}</li>
- * </ul>
- * </li>
- * <li>{@link #MESSAGE_DEVICE_BATTERY_STATE}
- * <ul>
- * <li>{@link #BATTERY_STATE_LOW}</li>
- * <li>{@link #BATTERY_STATE_GOOD}</li>
- * <li>{@link #BATTERY_STATE_CHARGING}</li>
- * </ul>
- * </li>
- * <li>{@link #MESSAGE_DEVICE_NETWORK_COVERAGE}
- * <ul>
- * <li>{@link #COVERAGE_POOR}</li>
- * <li>{@link #COVERAGE_GOOD}</li>
- * </ul>
- * </li>
+ * <li>{@link #MESSAGE_CALL_NETWORK_TYPE}</LI>
+ * <li>{@link #MESSAGE_CALL_AUDIO_CODEC}</LI>
+ * <li>{@link #MESSAGE_DEVICE_BATTERY_STATE}</LI>
+ * <li>{@link #MESSAGE_DEVICE_NETWORK_COVERAGE}</LI>
* </ul>
* @param message The message type to send.
* @param value The message value corresponding to the type.
@@ -307,6 +271,9 @@ public abstract class DiagnosticCall {
* @param preciseDisconnectCause the precise disconnect cause for the call.
* @return the disconnect message to use in place of the default Telephony message, or
* {@code null} if the default message will not be overridden.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
*/
// TODO: Wire in Telephony support for this.
public abstract @Nullable CharSequence onCallDisconnected(
@@ -323,6 +290,9 @@ public abstract class DiagnosticCall {
* @param disconnectReason The {@link ImsReasonInfo} associated with the call disconnection.
* @return A user-readable call disconnect message to use in place of the platform-generated
* disconnect message, or {@code null} if the disconnect message should not be overridden.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
*/
// TODO: Wire in Telephony support for this.
public abstract @Nullable CharSequence onCallDisconnected(
@@ -332,6 +302,9 @@ public abstract class DiagnosticCall {
* Telecom calls this method when a {@link CallQuality} report is received from the telephony
* stack for a call.
* @param callQuality The call quality report for this call.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
*/
public abstract void onCallQualityReceived(@NonNull CallQuality callQuality);
@@ -375,7 +348,6 @@ public abstract class DiagnosticCall {
* @hide
*/
public void handleCallUpdated(@NonNull Call.Details newDetails) {
- mCallDetails = newDetails;
onCallDetailsChanged(newDetails);
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 2d5f5fb58306..f7580d77186d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -602,6 +602,43 @@ public class SubscriptionManager {
public @interface SimDisplayNameSource {}
/**
+ * Device status is not shared to a remote party.
+ */
+ public static final int D2D_SHARING_DISABLED = 0;
+
+ /**
+ * Device status is shared with all numbers in the user's contacts.
+ */
+ public static final int D2D_SHARING_ALL_CONTACTS = 1;
+
+ /**
+ * Device status is shared with all starred contacts.
+ */
+ public static final int D2D_SHARING_STARRED_CONTACTS = 2;
+
+ /**
+ * Device status is shared whenever possible.
+ */
+ public static final int D2D_SHARING_ALL = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"D2D_SHARING_"},
+ value = {
+ D2D_SHARING_DISABLED,
+ D2D_SHARING_ALL_CONTACTS,
+ D2D_SHARING_STARRED_CONTACTS,
+ D2D_SHARING_ALL
+ })
+ public @interface DeviceToDeviceStatusSharing {}
+
+ /**
+ * TelephonyProvider column name for device to device sharing status.
+ * <P>Type: INTEGER (int)</P>
+ */
+ public static final String D2D_STATUS_SHARING = SimInfo.COLUMN_D2D_STATUS_SHARING;
+
+ /**
* TelephonyProvider column name for the color of a SIM.
* <P>Type: INTEGER (int)</P>
*/
@@ -3374,6 +3411,36 @@ public class SubscriptionManager {
}
/**
+ * Set the device to device status sharing user preference for a subscription ID. The setting
+ * app uses this method to indicate with whom they wish to share device to device status
+ * information.
+ * @param sharing the status sharing preference
+ * @param subId the unique Subscription ID in database
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setDeviceToDeviceStatusSharing(@DeviceToDeviceStatusSharing int sharing,
+ int subId) {
+ if (VDBG) {
+ logd("[setDeviceToDeviceStatusSharing] + sharing: " + sharing + " subId: " + subId);
+ }
+ setSubscriptionPropertyHelper(subId, "setDeviceToDeviceSharingStatus",
+ (iSub)->iSub.setDeviceToDeviceStatusSharing(sharing, subId));
+ }
+
+ /**
+ * Returns the user-chosen device to device status sharing preference
+ * @param subId Subscription id of subscription
+ * @return The device to device status sharing preference
+ */
+ public @DeviceToDeviceStatusSharing int getDeviceToDeviceStatusSharing(int subId) {
+ if (VDBG) {
+ logd("[getDeviceToDeviceStatusSharing] + subId: " + subId);
+ }
+ return getIntegerSubscriptionProperty(subId, D2D_STATUS_SHARING, D2D_SHARING_DISABLED,
+ mContext);
+ }
+
+ /**
* DO NOT USE.
* This API is designed for features that are not finished at this point. Do not call this API.
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2546bbe5f5f6..4dc6c7ce35cf 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -139,6 +139,8 @@ import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* Provides access to information about the telephony services on
@@ -3147,6 +3149,10 @@ public class TelephonyManager {
return NETWORK_TYPE_BITMASK_LTE_CA;
case NETWORK_TYPE_NR:
return NETWORK_TYPE_BITMASK_NR;
+ case NETWORK_TYPE_IWLAN:
+ return NETWORK_TYPE_BITMASK_IWLAN;
+ case NETWORK_TYPE_IDEN:
+ return (1 << (NETWORK_TYPE_IDEN - 1));
default:
return NETWORK_TYPE_BITMASK_UNKNOWN;
}
@@ -8642,8 +8648,8 @@ public class TelephonyManager {
public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3;
/**
- * Set the allowed network types of the device and
- * provide the reason triggering the allowed network change.
+ * Set the allowed network types of the device and provide the reason triggering the allowed
+ * network change.
* This can be called for following reasons
* <ol>
* <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER}
@@ -8655,10 +8661,15 @@ public class TelephonyManager {
* </ol>
* This API will result in allowing an intersection of allowed network types for all reasons,
* including the configuration done through other reasons.
+ *
+ * The functionality of this API with the parameter
+ * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API
+ * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of
+ * {@link TelephonyManager#setAllowedNetworkTypes}.
* <p>
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
* ({@link TelephonyManager#CAPABILITY_ALLOWED_NETWORK_TYPES_USED}) returns true, then
- * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
+ * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
* @param reason the reason the allowed network type change is taking place
@@ -8698,21 +8709,17 @@ public class TelephonyManager {
* {@link #getAllowedNetworkTypesForReason} returns allowed network type for a
* specific reason.
*
- * <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
- * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
- *
* @param reason the reason the allowed network type change is taking place
* @return the allowed network type bitmask
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED)
+ @SystemApi
public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
@AllowedNetworkTypesReason int reason) {
if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -8757,6 +8764,25 @@ public class TelephonyManager {
}
/**
+ * Returns a string representation of the allowed network types{@link NetworkTypeBitMask}.
+ *
+ * @param networkTypeBitmask The bitmask of allowed network types.
+ * @return the name of the allowed network types
+ * @hide
+ */
+ public static String convertNetworkTypeBitmaskToString(
+ @NetworkTypeBitMask long networkTypeBitmask) {
+ String networkTypeName = IntStream.rangeClosed(NETWORK_TYPE_GPRS, NETWORK_TYPE_NR)
+ .filter(x -> {
+ return (networkTypeBitmask & getBitMaskForNetworkType(x))
+ == getBitMaskForNetworkType(x);
+ })
+ .mapToObj(x -> getNetworkTypeName(x))
+ .collect(Collectors.joining("|"));
+ return TextUtils.isEmpty(networkTypeName) ? "UNKNOWN" : networkTypeName;
+ }
+
+ /**
* Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
*
* <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -12577,6 +12603,7 @@ public class TelephonyManager {
NETWORK_TYPE_BITMASK_LTE,
NETWORK_TYPE_BITMASK_LTE_CA,
NETWORK_TYPE_BITMASK_NR,
+ NETWORK_TYPE_BITMASK_IWLAN
})
public @interface NetworkTypeBitMask {}
@@ -15216,13 +15243,17 @@ public class TelephonyManager {
* </ul>
* @param appType icc application type, like {@link #APPTYPE_USIM} or {@link
* #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN}
- * @param nafId Network Application Function(NAF) fully qualified domain name and
- * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first
- * part is the constant string "3GPP-bootstrapping" (GBA_ME),
- * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest),
- * and the latter part shall be the FQDN of the NAF (e.g.
- * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com",
- * or "3GPP-bootstrapping-digest@naf1.operator.com").
+ * @param nafId A URI to specify Network Application Function(NAF) fully qualified domain
+ * name (FQDN) and the selected GBA mode. The authority of the URI must contain two parts
+ * delimited by "@" sign. The first part is the constant string "3GPP-bootstrapping" (GBA_ME),
+ * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest).
+ * The second part shall be the FQDN of the NAF. The scheme of the URI is not actually used
+ * for the authentication, which may be set the same as the resource that the application is
+ * going to access. For example, the nafId can be
+ * "https://3GPP-bootstrapping@naf1.operator.com",
+ * "https://3GPP-bootstrapping-uicc@naf1.operator.com",
+ * "https://3GPP-bootstrapping-digest@naf1.operator.com",
+ * "ftps://3GPP-bootstrapping-digest@naf1.operator.com".
* @param securityProtocol Security protocol identifier between UE and NAF.  See
* 3GPP TS 33.220 Annex H. Application can use
   * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId},
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index a76422977cb6..ffe5399e406b 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -18,6 +18,7 @@
package android.telephony.data;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -29,6 +30,7 @@ import android.telephony.DataFailCause;
import android.telephony.data.ApnSetting.ProtocolType;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -812,11 +814,19 @@ public final class DataCallResponse implements Parcelable {
/**
* Set pdu session id.
+ * <p/>
+ * The id must be between 1 and 15 when linked to a pdu session. If no pdu session
+ * exists for the current data call, the id must be set to {@link PDU_SESSION_ID_NOT_SET}.
*
* @param pduSessionId Pdu Session Id of the data call.
* @return The same instance of the builder.
*/
- public @NonNull Builder setPduSessionId(int pduSessionId) {
+ public @NonNull Builder setPduSessionId(
+ @IntRange(from = PDU_SESSION_ID_NOT_SET, to = 15) int pduSessionId) {
+ Preconditions.checkArgument(pduSessionId >= PDU_SESSION_ID_NOT_SET,
+ "pduSessionId must be greater than or equal to" + PDU_SESSION_ID_NOT_SET);
+ Preconditions.checkArgument(pduSessionId <= 15,
+ "pduSessionId must be less than or equal to 15.");
mPduSessionId = pduSessionId;
return this;
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index f5f29c65b7cd..048b3297a1b4 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -41,6 +41,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Base class of data service. Services that extend DataService must register the service in
@@ -284,11 +285,11 @@ public abstract class DataService extends Service {
*
* Any resources being transferred cannot be released while a
* handover is underway.
- *
+ * <p/>
* If a handover was unsuccessful, then the framework calls
* {@link DataService#cancelHandover}. The target transport retains ownership over any of
* the resources being transferred.
- *
+ * <p/>
* If a handover was successful, the framework calls {@link DataService#deactivateDataCall}
* with reason {@link DataService.REQUEST_REASON_HANDOVER}. The target transport now owns
* the transferred resources and is responsible for releasing them.
@@ -299,21 +300,27 @@ public abstract class DataService extends Service {
* @hide
*/
public void startHandover(int cid, @NonNull DataServiceCallback callback) {
+ Objects.requireNonNull(callback, "callback cannot be null");
// The default implementation is to return unsupported.
- if (callback != null) {
- Log.d(TAG, "startHandover: " + cid);
- callback.onHandoverStarted(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
- } else {
- Log.e(TAG, "startHandover: " + cid + ", callback is null");
- }
+ Log.d(TAG, "startHandover: " + cid);
+ callback.onHandoverStarted(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
/**
* Indicates that a handover was cancelled after a call to
* {@link DataService#startHandover}. This is called on the source transport.
- *
+ * <p/>
* Since the handover was unsuccessful, the source transport retains ownership over any of
* the resources being transferred and is still responsible for releasing them.
+ * <p/>
+ * The handover can be cancelled up until either:
+ * <ul><li>
+ * The handover was successful after receiving a successful response from
+ * {@link DataService#setupDataCall} on the target transport.
+ * </li><li>
+ * The data call on the source transport was lost.
+ * </li>
+ * </ul>
*
* @param cid The identifier of the data call which is provided in {@link DataCallResponse}
* @param callback The result callback for this request.
@@ -321,13 +328,10 @@ public abstract class DataService extends Service {
* @hide
*/
public void cancelHandover(int cid, @NonNull DataServiceCallback callback) {
+ Objects.requireNonNull(callback, "callback cannot be null");
// The default implementation is to return unsupported.
- if (callback != null) {
- Log.d(TAG, "cancelHandover: " + cid);
- callback.onHandoverCancelled(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
- } else {
- Log.e(TAG, "cancelHandover: " + cid + ", callback is null");
- }
+ Log.d(TAG, "cancelHandover: " + cid);
+ callback.onHandoverCancelled(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
}
/**
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 85cd81bb4eb5..abc5606e6743 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -1010,6 +1010,16 @@ public class ProvisioningManager {
}
}
+ @Override
+ public void onPreProvisioningReceived(byte[] configXml) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onPreProvisioningReceived(configXml));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private void setExecutor(Executor executor) {
mExecutor = executor;
}
@@ -1022,7 +1032,7 @@ public class ProvisioningManager {
* due to various triggers defined in GSMA RCC.14 for ACS(auto configuration
* server) or other operator defined triggers. If RCS provisioning is already
* completed at the time of callback registration, then this method shall be
- * invoked with the current configuration
+ * invoked with the current configuration.
* @param configXml The RCS configuration XML received by OTA. It is defined
* by GSMA RCC.07.
*/
@@ -1055,6 +1065,20 @@ public class ProvisioningManager {
*/
public void onRemoved() {}
+ /**
+ * Some carriers using ACS (auto configuration server) may send a carrier-specific
+ * pre-provisioning configuration XML if the user has not been provisioned for RCS
+ * services yet. When this provisioning XML is received, the framework will move
+ * into a "not provisioned" state for RCS. In order for provisioning to proceed,
+ * the application must parse this configuration XML and perform the carrier specific
+ * opt-in flow for RCS services. If the user accepts, {@link #triggerRcsReconfiguration}
+ * must be called in order for the device to move out of this state and try to fetch
+ * the RCS provisioning information.
+ *
+ * @param configXml the pre-provisioning config in carrier specified format.
+ */
+ public void onPreProvisioningReceived(@NonNull byte[] configXml) {}
+
/**@hide*/
public final IRcsConfigCallback getBinder() {
return mBinder;
diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
index cedf48b0b8e1..9c28c36521f5 100644
--- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
+++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
@@ -25,7 +25,6 @@ import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -389,22 +388,6 @@ public final class RcsContactPresenceTuple implements Parcelable {
* The optional timestamp indicating the data and time of the status change of this tuple.
* Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format
* string per RFC3339.
- * @hide
- */
- public @NonNull Builder setTimestamp(@NonNull String timestamp) {
- try {
- mPresenceTuple.mTimestamp =
- DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp, Instant::from);
- } catch (DateTimeParseException e) {
- Log.d(LOG_TAG, "Parse timestamp failed " + e);
- }
- return this;
- }
-
- /**
- * The optional timestamp indicating the data and time of the status change of this tuple.
- * Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format
- * string per RFC3339.
*/
public @NonNull Builder setTime(@NonNull Instant timestamp) {
mPresenceTuple.mTimestamp = timestamp;
@@ -534,14 +517,6 @@ public final class RcsContactPresenceTuple implements Parcelable {
return mContactUri;
}
- /**
- * @return the timestamp element contained in the tuple if it exists
- * @hide
- */
- public @Nullable String getTimestamp() {
- return (mTimestamp == null) ? null : mTimestamp.toString();
- }
-
/** @return the timestamp element contained in the tuple if it exists */
public @Nullable Instant getTime() {
return mTimestamp;
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 815c08d120c2..dd9102699529 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -439,8 +439,7 @@ public class RcsUceAdapter {
/**
* The pending request has resulted in an error and may need to be retried, depending on the
- * error code. The callback {@link #onCapabilitiesReceived(List)}
- * for each contacts is required to be called before {@link #onError} is called.
+ * error code.
* @param errorCode The reason for the framework being unable to process the request.
* @param retryIntervalMillis The time in milliseconds the requesting application should
* wait before retrying, if non-zero.
@@ -487,93 +486,6 @@ public class RcsUceAdapter {
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
- @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
- Manifest.permission.READ_CONTACTS})
- public void requestCapabilities(@NonNull List<Uri> contactNumbers,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull CapabilitiesCallback c) throws ImsException {
- if (c == null) {
- throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
- }
- if (executor == null) {
- throw new IllegalArgumentException("Must include a non-null Executor.");
- }
- if (contactNumbers == null) {
- throw new IllegalArgumentException("Must include non-null contact number list.");
- }
-
- IImsRcsController imsRcsController = getIImsRcsController();
- if (imsRcsController == null) {
- Log.e(TAG, "requestCapabilities: IImsRcsController is null");
- throw new ImsException("Can not find remote IMS service",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
- }
-
- IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
- @Override
- public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
- } finally {
- restoreCallingIdentity(callingIdentity);
- }
- }
- @Override
- public void onComplete() {
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> c.onComplete());
- } finally {
- restoreCallingIdentity(callingIdentity);
- }
- }
- @Override
- public void onError(int errorCode, long retryAfterMilliseconds) {
- final long callingIdentity = Binder.clearCallingIdentity();
- try {
- executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds));
- } finally {
- restoreCallingIdentity(callingIdentity);
- }
- }
- };
-
- try {
- imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(),
- mContext.getAttributionTag(), contactNumbers, internalCallback);
- } catch (ServiceSpecificException e) {
- throw new ImsException(e.toString(), e.errorCode);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e);
- throw new ImsException("Remote IMS Service is not available",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
- }
- }
-
- /**
- * Request the User Capability Exchange capabilities for one or more contacts.
- * <p>
- * This will return the cached capabilities of the contact and will not perform a capability
- * poll on the network unless there are contacts being queried with stale information.
- * <p>
- * Be sure to check the availability of this feature using
- * {@link ImsRcsManager#isAvailable(int, int)} and ensuring
- * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
- * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is enabled or else
- * this operation will fail with {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
- *
- * @param contactNumbers A list of numbers that the capabilities are being requested for.
- * @param executor The executor that will be used when the request is completed and the
- * {@link CapabilitiesCallback} is called.
- * @param c A one-time callback for when the request for capabilities completes or there is an
- * error processing the request.
- * @throws ImsException if the subscription associated with this instance of
- * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
- * available. This can happen if the ImsService has crashed, for example, or if the subscription
- * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
- * @hide
- */
@SystemApi
@RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
Manifest.permission.READ_CONTACTS})
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
index 5a8973e37bce..d0853d1846ac 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
@@ -25,5 +25,6 @@ oneway interface IRcsConfigCallback {
void onAutoConfigurationErrorReceived(int errorCode, String errorString);
void onConfigurationReset();
void onRemoved();
+ void onPreProvisioningReceived(in byte[] config);
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 21aeb64bb417..d75da9035124 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -552,11 +552,34 @@ public class ImsConfigImplBase {
}
mRcsCallbacks.broadcastAction(c -> {
try {
- //TODO compressed by default?
c.onAutoConfigurationErrorReceived(errorCode, errorString);
} catch (RemoteException e) {
Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
}
});
}
+
+ /**
+ * Notifies application that pre-provisioning config is received.
+ *
+ * <p>Some carriers using ACS (auto configuration server) may send a carrier-specific
+ * pre-provisioning configuration XML if the user has not been provisioned for RCS
+ * services yet. When such provisioning XML is received, ACS client must call this
+ * method to notify the application with the XML.
+ *
+ * @param configXml the pre-provisioning config in carrier specified format.
+ */
+ public final void notifyPreProvisioningReceived(@NonNull byte[] configXml) {
+ // can be null in testing
+ if (mRcsCallbacks == null) {
+ return;
+ }
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onPreProvisioningReceived(configXml);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping.");
+ }
+ });
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index 00c91681d9ea..03e17fbc2c0d 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -386,41 +386,6 @@ public class RcsCapabilityExchangeImplBase {
* {@link SubscribeResponseCallback#onTerminated(String, long)} must be called for the
* framework to finish listening for NOTIFY responses.
*
- * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
- * capabilities for.
- * @param cb The callback of the subscribe request.
- * @hide
- */
- // executor used is defined in the constructor.
- @SuppressLint("ExecutorRegistration")
- public void subscribeForCapabilities(@NonNull List<Uri> uris,
- @NonNull SubscribeResponseCallback cb) {
- // Stub - to be implemented by service
- Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation.");
- try {
- cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
- } catch (ImsException e) {
- // Do not do anything, this is a stub implementation.
- }
- }
-
- /**
- * The user capabilities of one or multiple contacts have been requested by the framework.
- * <p>
- * The implementer must follow up this call with an
- * {@link SubscribeResponseCallback#onCommandError} call to indicate this operation has failed.
- * The response from the network to the SUBSCRIBE request must be sent back to the framework
- * using {@link SubscribeResponseCallback#onNetworkResponse(int, String)}.
- * As NOTIFY requests come in from the network, the requested contact’s capabilities should be
- * sent back to the framework using
- * {@link SubscribeResponseCallback#onNotifyCapabilitiesUpdate(List<String>}) and
- * {@link SubscribeResponseCallback#onResourceTerminated(List<Pair<Uri, String>>)}
- * should be called with the presence information for the contacts specified.
- * <p>
- * Once the subscription is terminated,
- * {@link SubscribeResponseCallback#onTerminated(String, long)} must be called for the
- * framework to finish listening for NOTIFY responses.
- *
* @param uris A {@link Collection} of the {@link Uri}s that the framework is requesting the
* UCE capabilities for.
* @param cb The callback of the subscribe request.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 571efcee0e15..9493c76d9a57 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -300,4 +300,6 @@ interface ISub {
boolean canDisablePhysicalSubscription();
int setUiccApplicationsEnabled(boolean enabled, int subscriptionId);
+
+ int setDeviceToDeviceStatusSharing(int sharing, int subId);
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index 17aa1d14a447..47eaddfa1f3a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -17,6 +17,7 @@
package com.android.server.wm.flicker.ime
import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -88,40 +89,40 @@ class CloseImeAutoOpenWindowToAppTest(private val testSpec: FlickerTestParameter
}
}
- @Presubmit
+ @Postsubmit
@Test
fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
- @Presubmit
+ @Postsubmit
@Test
fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
- @Presubmit
+ @Postsubmit
@Test
fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
testSpec.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE))
- @Presubmit
+ @Postsubmit
@Test
fun imeAppWindowIsAlwaysVisible() = testSpec.imeAppWindowIsAlwaysVisible(testApp)
- @Presubmit
+ @Postsubmit
@Test
fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
- @Presubmit
+ @Postsubmit
@Test
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
- @Presubmit
+ @Postsubmit
@Test
fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation)
- @Presubmit
+ @Postsubmit
@Test
fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
- @Presubmit
+ @Postsubmit
@Test
fun imeAppLayerIsAlwaysVisible() = testSpec.imeAppLayerIsAlwaysVisible(testApp)
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 335c8d0127eb..eacf5b287a2e 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -9,14 +9,17 @@ package {
android_test {
name: "InputTests",
- srcs: ["src/**/*.kt"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
platform_apis: true,
certificate: "platform",
static_libs: [
- "androidx.test.ext.junit",
- "androidx.test.rules",
- "truth-prebuilt",
- "ub-uiautomator",
- ],
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "truth-prebuilt",
+ "ub-uiautomator",
+ ],
test_suites: ["device-tests"],
}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
new file mode 100644
index 000000000000..63500774816a
--- /dev/null
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputDeviceTest {
+ private static final float DELTA = 0.01f;
+ private static final int DEVICE_ID = 1000;
+
+ private void assertMotionRangeEquals(InputDevice.MotionRange range,
+ InputDevice.MotionRange outRange) {
+ assertEquals(range.getAxis(), outRange.getAxis());
+ assertEquals(range.getSource(), outRange.getSource());
+ assertEquals(range.getMin(), outRange.getMin(), DELTA);
+ assertEquals(range.getMax(), outRange.getMax(), DELTA);
+ assertEquals(range.getFlat(), outRange.getFlat(), DELTA);
+ assertEquals(range.getFuzz(), outRange.getFuzz(), DELTA);
+ assertEquals(range.getResolution(), outRange.getResolution(), DELTA);
+ }
+
+ private void assertDeviceEquals(InputDevice device, InputDevice outDevice) {
+ assertEquals(device.getId(), outDevice.getId());
+ assertEquals(device.getGeneration(), outDevice.getGeneration());
+ assertEquals(device.getControllerNumber(), outDevice.getControllerNumber());
+ assertEquals(device.getName(), outDevice.getName());
+ assertEquals(device.getVendorId(), outDevice.getVendorId());
+ assertEquals(device.getProductId(), outDevice.getProductId());
+ assertEquals(device.getDescriptor(), outDevice.getDescriptor());
+ assertEquals(device.isExternal(), outDevice.isExternal());
+ assertEquals(device.getSources(), outDevice.getSources());
+ assertEquals(device.getKeyboardType(), outDevice.getKeyboardType());
+ assertEquals(device.getMotionRanges().size(), outDevice.getMotionRanges().size());
+
+ KeyCharacterMap keyCharacterMap = device.getKeyCharacterMap();
+ KeyCharacterMap outKeyCharacterMap = outDevice.getKeyCharacterMap();
+ assertTrue("keyCharacterMap not equal", keyCharacterMap.equals(outKeyCharacterMap));
+
+ for (int j = 0; j < device.getMotionRanges().size(); j++) {
+ assertMotionRangeEquals(device.getMotionRanges().get(j),
+ outDevice.getMotionRanges().get(j));
+ }
+ }
+
+ private void assertInputDeviceParcelUnparcel(KeyCharacterMap keyCharacterMap) {
+ final InputDevice device =
+ new InputDevice(DEVICE_ID, 0 /* generation */, 0 /* controllerNumber */, "name",
+ 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+ 0 /* sources */, 0 /* keyboardType */, keyCharacterMap,
+ false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
+ true /* hasSensor */, false /* hasBattery */);
+
+ Parcel parcel = Parcel.obtain();
+ device.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ InputDevice outDevice = InputDevice.CREATOR.createFromParcel(parcel);
+ assertDeviceEquals(device, outDevice);
+ }
+
+ @Test
+ public void testParcelUnparcelInputDevice_VirtualCharacterMap() {
+ final KeyCharacterMap keyCharacterMap =
+ KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
+ assertInputDeviceParcelUnparcel(keyCharacterMap);
+ }
+
+ @Test
+ public void testParcelUnparcelInputDevice_EmptyCharacterMap() {
+ final KeyCharacterMap keyCharacterMap = KeyCharacterMap.obtainEmptyMap(DEVICE_ID);
+ assertInputDeviceParcelUnparcel(keyCharacterMap);
+ }
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 11498dec8165..a02002752c38 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -593,6 +593,16 @@ public class VcnManagementServiceTest {
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
}
+ @Test(expected = SecurityException.class)
+ public void testRemoveVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
+ doThrow(new SecurityException())
+ .when(mMockContext)
+ .enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.NETWORK_FACTORY), any());
+
+ mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
+ }
+
@Test
public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() {
mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);