summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java2
-rw-r--r--api/current.txt3
-rwxr-xr-xapi/system-current.txt3
-rw-r--r--api/test-current.txt3
-rw-r--r--core/java/android/app/ActivityThread.java12
-rw-r--r--core/java/android/app/ApplicationPackageManager.java3
-rw-r--r--core/java/android/app/ContextImpl.java58
-rw-r--r--core/java/android/app/LoadedApk.java5
-rw-r--r--core/java/android/app/ResourcesManager.java434
-rw-r--r--core/java/android/app/WindowTokenClient.java3
-rw-r--r--core/java/android/content/pm/PackageParser.java3
-rw-r--r--core/java/android/content/res/ResourcesKey.java21
-rw-r--r--core/java/android/telephony/PhoneStateListener.java46
-rw-r--r--core/java/com/android/internal/os/TEST_MAPPING15
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl2
-rw-r--r--core/res/res/values-ar/strings.xml6
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-mk/strings.xml2
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java49
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesManagerTest.java111
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java30
-rw-r--r--libs/WindowManager/Shell/tests/README.md15
-rw-r--r--libs/WindowManager/Shell/tests/flicker/Android.bp34
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml43
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidTest.xml40
-rw-r--r--libs/WindowManager/Shell/tests/flicker/README.md10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt153
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt130
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt36
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt31
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt45
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt121
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt (renamed from libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java)27
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp0
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp20
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml37
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml26
-rw-r--r--libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java45
-rw-r--r--libs/WindowManager/Shell/tests/unittest/Android.bp (renamed from libs/WindowManager/Shell/tests/Android.bp)2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml (renamed from libs/WindowManager/Shell/tests/AndroidManifest.xml)0
-rw-r--r--libs/WindowManager/Shell/tests/unittest/AndroidTest.xml (renamed from libs/WindowManager/Shell/tests/AndroidTest.xml)4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/res/values/config.xml (renamed from libs/WindowManager/Shell/tests/res/values/config.xml)0
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java (renamed from libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java)0
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java (renamed from libs/WindowManager/Shell/tests/src/com/android/wm/shell/common/DisplayLayoutTest.java)0
-rw-r--r--media/jni/android_media_tv_Tuner.cpp4
-rw-r--r--non-updatable-api/current.txt1
-rw-r--r--non-updatable-api/system-current.txt3
-rw-r--r--packages/CarSystemUI/res/values/config.xml1
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java14
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java2
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java31
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java4
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java4
-rw-r--r--packages/PrintSpooler/res/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/README.md9
-rw-r--r--packages/SystemUI/res/values-television/config.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java157
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java (renamed from packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java)61
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java112
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java6
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java15
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java2
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java20
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java2
-rw-r--r--services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java4
-rw-r--r--services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java14
-rw-r--r--services/core/java/com/android/server/pm/Settings.java1
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java2
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java17
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java33
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java75
-rw-r--r--services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java26
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java2
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java4
-rw-r--r--tests/StagedInstallTest/Android.bp1
-rw-r--r--tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java4
-rw-r--r--wifi/api/current.txt2
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java50
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java35
129 files changed, 2085 insertions, 1031 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 6bc95bf8bc75..c033138d5f20 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -2131,7 +2131,7 @@ public class AppStandbyController implements AppStandbyInternal {
}
public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) {
- final int uid = mPackageManagerInternal.getPackageUidInternal(pkg, 0, userId);
+ final int uid = mPackageManagerInternal.getPackageUid(pkg, /* flags= */ 0, userId);
final AndroidPackage aPkg = mPackageManagerInternal.getPackage(uid);
if (uid < 0
|| aPkg == null
diff --git a/api/current.txt b/api/current.txt
index 36c67f275768..c6af6beca60b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -31624,6 +31624,7 @@ package android.net.wifi {
method @Nullable public String getPassphrase();
method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfig();
method @IntRange(from=0) public int getPriority();
+ method public int getPriorityGroup();
method @Nullable public String getSsid();
method public boolean isAppInteractionRequired();
method public boolean isCredentialSharedWithUser();
@@ -31650,6 +31651,7 @@ package android.net.wifi {
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriorityGroup(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setUntrusted(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
@@ -47842,6 +47844,7 @@ package android.telephony {
method public void onDataConnectionStateChanged(int);
method public void onDataConnectionStateChanged(int, int);
method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
+ method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
diff --git a/api/system-current.txt b/api/system-current.txt
index 28c1eafca815..41e859363581 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10817,7 +10817,8 @@ package android.telephony {
public class PhoneStateListener {
method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
method public void onRadioPowerStateChanged(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index a97a9e88a368..529dcf71ef6e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4076,7 +4076,8 @@ package android.telephony {
}
public class PhoneStateListener {
- method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d67b98620f37..f6b045349219 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2242,9 +2242,9 @@ public final class ActivityThread extends ClientTransactionHandler {
* Resources if one has already been created.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
- String[] libDirs, int displayId, LoadedApk pkgInfo) {
+ String[] libDirs, LoadedApk pkgInfo) {
return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
- displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null);
+ null, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader(), null);
}
@UnsupportedAppUsage
@@ -5692,8 +5692,7 @@ public final class ActivityThread extends ClientTransactionHandler {
// many places.
final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull(
amOverrideConfig, contextThemeWrapperOverrideConfig);
- mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig,
- displayId, movedToDifferentDisplay);
+ mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig, displayId);
activity.mConfigChangeFlags = 0;
activity.mCurrentConfig = new Configuration(newConfig);
@@ -6014,6 +6013,11 @@ public final class ActivityThread extends ClientTransactionHandler {
r.mPendingOverrideConfig = null;
}
+ if (displayId == INVALID_DISPLAY) {
+ // If INVALID_DISPLAY is passed assume that the activity should keep its current
+ // display.
+ displayId = r.activity.getDisplayId();
+ }
final boolean movedToDifferentDisplay = isDifferentDisplay(r.activity, displayId);
if (r.overrideConfig != null && !r.overrideConfig.isOtherSeqNewer(overrideConfig)
&& !movedToDifferentDisplay) {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 676c6c01d349..340d5a12f92e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -96,7 +96,6 @@ import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.LauncherIcons;
import android.util.Log;
-import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.Immutable;
@@ -1748,7 +1747,7 @@ public class ApplicationPackageManager extends PackageManager {
final Resources r = mContext.mMainThread.getTopLevelResources(
sameUid ? app.sourceDir : app.publicSourceDir,
sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
- app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+ app.resourceDirs, app.sharedLibraryFiles,
mContext.mPackageInfo);
if (r != null) {
return r;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1b3e865945d1..cee607fd7428 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -237,6 +237,15 @@ class ContextImpl extends Context {
private @NonNull Resources mResources;
private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet.
+ /**
+ * If set to {@code true} the resources for this context will be configured for mDisplay which
+ * will override the display configuration inherited from {@link #mToken} (or the global
+ * configuration if mToken is null). Typically set for display contexts and contexts derived
+ * from display contexts where changes to the activity display and the global configuration
+ * display should not impact their resources.
+ */
+ private boolean mForceDisplayOverrideInResources;
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final int mFlags;
@@ -2259,8 +2268,8 @@ class ContextImpl extends Context {
}
private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName,
- int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo,
- List<ResourcesLoader> resourcesLoader) {
+ @Nullable Integer overrideDisplayId, Configuration overrideConfig,
+ CompatibilityInfo compatInfo, List<ResourcesLoader> resourcesLoader) {
final String[] splitResDirs;
final ClassLoader classLoader;
try {
@@ -2274,7 +2283,7 @@ class ContextImpl extends Context {
splitResDirs,
pi.getOverlayDirs(),
pi.getApplicationInfo().sharedLibraryFiles,
- displayId,
+ overrideDisplayId,
overrideConfig,
compatInfo,
classLoader,
@@ -2291,8 +2300,10 @@ class ContextImpl extends Context {
new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
final int displayId = getDisplayId();
+ final Integer overrideDisplayId = mForceDisplayOverrideInResources
+ ? displayId : null;
- c.setResources(createResources(mToken, pi, null, displayId, null,
+ c.setResources(createResources(mToken, pi, null, overrideDisplayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo(), null));
if (c.mResources != null) {
return c;
@@ -2326,8 +2337,10 @@ class ContextImpl extends Context {
mToken, user, flags, null, null);
final int displayId = getDisplayId();
+ final Integer overrideDisplayId = mForceDisplayOverrideInResources
+ ? displayId : null;
- c.setResources(createResources(mToken, pi, null, displayId, null,
+ c.setResources(createResources(mToken, pi, null, overrideDisplayId, null,
getDisplayAdjustments(displayId).getCompatibilityInfo(), null));
if (c.mResources != null) {
return c;
@@ -2361,15 +2374,13 @@ class ContextImpl extends Context {
final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
mAttributionTag, splitName, mToken, mUser, mFlags, classLoader, null);
- final int displayId = getDisplayId();
-
context.setResources(ResourcesManager.getInstance().getResources(
mToken,
mPackageInfo.getResDir(),
paths,
mPackageInfo.getOverlayDirs(),
mPackageInfo.getApplicationInfo().sharedLibraryFiles,
- displayId,
+ mForceDisplayOverrideInResources ? getDisplayId() : null,
null,
mPackageInfo.getCompatibilityInfo(),
classLoader,
@@ -2383,12 +2394,23 @@ class ContextImpl extends Context {
throw new IllegalArgumentException("overrideConfiguration must not be null");
}
+ if (mForceDisplayOverrideInResources) {
+ // Ensure the resources display metrics are adjusted to match the display this context
+ // is based on.
+ Configuration displayAdjustedConfig = new Configuration();
+ displayAdjustedConfig.setTo(mDisplay.getDisplayAdjustments().getConfiguration(),
+ ActivityInfo.CONFIG_WINDOW_CONFIGURATION, 1);
+ displayAdjustedConfig.updateFrom(overrideConfiguration);
+ overrideConfiguration = displayAdjustedConfig;
+ }
+
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, mToken, mUser, mFlags, mClassLoader, null);
final int displayId = getDisplayId();
-
- context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
+ final Integer overrideDisplayId = mForceDisplayOverrideInResources
+ ? displayId : null;
+ context.setResources(createResources(mToken, mPackageInfo, mSplitName, overrideDisplayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
context.mIsUiContext = isUiContext() || isOuterUiContext();
@@ -2406,11 +2428,20 @@ class ContextImpl extends Context {
final int displayId = display.getDisplayId();
+ // Ensure the resources display metrics are adjusted to match the provided display.
+ Configuration overrideConfig = new Configuration();
+ overrideConfig.setTo(display.getDisplayAdjustments().getConfiguration(),
+ ActivityInfo.CONFIG_WINDOW_CONFIGURATION, 1);
+
context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
- null, getDisplayAdjustments(displayId).getCompatibilityInfo(),
+ overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
mResources.getLoaders()));
context.mDisplay = display;
context.mIsAssociatedWithDisplay = true;
+ // Display contexts and any context derived from a display context should always override
+ // the display that would otherwise be inherited from mToken (or the global configuration if
+ // mToken is null).
+ context.mForceDisplayOverrideInResources = true;
return context;
}
@@ -2428,8 +2459,10 @@ class ContextImpl extends Context {
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, token, mUser, mFlags, mClassLoader, null);
context.mIsUiContext = true;
-
context.mIsAssociatedWithDisplay = true;
+ // Window contexts receive configurations directly from the server and as such do not
+ // need to override their display in ResourcesManager.
+ context.mForceDisplayOverrideInResources = false;
return context;
}
@@ -2772,6 +2805,7 @@ class ContextImpl extends Context {
mDisplay = container.mDisplay;
mIsAssociatedWithDisplay = container.mIsAssociatedWithDisplay;
mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext;
+ mForceDisplayOverrideInResources = container.mForceDisplayOverrideInResources;
} else {
mBasePackageName = packageInfo.mPackageName;
ApplicationInfo ainfo = packageInfo.getApplicationInfo();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index aa6a08b6d2e4..202b6152d2ea 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -56,7 +56,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.Display;
import android.view.DisplayAdjustments;
import com.android.internal.util.ArrayUtils;
@@ -367,7 +366,7 @@ public final class LoadedApk {
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
+ null, null, getCompatibilityInfo(),
getClassLoader(), mApplication == null ? null
: mApplication.getResources().getLoaders());
}
@@ -1231,7 +1230,7 @@ public final class LoadedApk {
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
+ null, null, getCompatibilityInfo(),
getClassLoader(), null);
}
return mResources;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 1aafe2cc6350..7cd3fcad177b 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -17,6 +17,8 @@
package android.app;
import static android.app.ActivityThread.DEBUG_CONFIGURATION;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -61,6 +63,7 @@ import java.util.List;
import java.util.Objects;
import java.util.WeakHashMap;
import java.util.function.Consumer;
+import java.util.function.Function;
/** @hide */
public class ResourcesManager {
@@ -82,6 +85,12 @@ public class ResourcesManager {
private final Configuration mResConfiguration = new Configuration();
/**
+ * The display upon which all Resources are based. Activity, window token, and display context
+ * resources apply their overrides to this display id.
+ */
+ private int mResDisplayId = DEFAULT_DISPLAY;
+
+ /**
* A mapping of ResourceImpls and their configurations. These are heavy weight objects
* which should be reused as much as possible.
*/
@@ -155,20 +164,79 @@ public class ResourcesManager {
private final ArrayMap<ApkKey, WeakReference<ApkAssets>> mCachedApkAssets = new ArrayMap<>();
/**
- * Resources and base configuration override associated with an Activity.
+ * Class containing the base configuration override and set of resources associated with an
+ * Activity or {@link WindowContext}.
*/
private static class ActivityResources {
+ /**
+ * Override config to apply to all resources associated with the token this instance is
+ * based on.
+ *
+ * @see #activityResources
+ * @see #getResources(IBinder, String, String[], String[], String[], Integer, Configuration,
+ * CompatibilityInfo, ClassLoader, List)
+ */
+ public final Configuration overrideConfig = new Configuration();
+
+ /**
+ * The display to apply to all resources associated with the token this instance is based
+ * on.
+ */
+ public int overrideDisplayId;
+
+ /** List of {@link ActivityResource} associated with the token this instance is based on. */
+ public final ArrayList<ActivityResource> activityResources = new ArrayList<>();
+
+ public final ReferenceQueue<Resources> activityResourcesQueue = new ReferenceQueue<>();
+
@UnsupportedAppUsage
- private ActivityResources() {
+ private ActivityResources() {}
+
+ /** Returns the number of live resource references within {@code activityResources}. */
+ public int countLiveReferences() {
+ int count = 0;
+ for (int i = 0; i < activityResources.size(); i++) {
+ WeakReference<Resources> resources = activityResources.get(i).resources;
+ if (resources != null && resources.get() != null) {
+ count++;
+ }
+ }
+ return count;
}
+ }
+
+ /**
+ * Contains a resource derived from an {@link Activity} or {@link WindowContext} and information
+ * about how this resource expects its configuration to differ from the token's.
+ *
+ * @see ActivityResources
+ */
+ // TODO: Ideally this class should be called something token related, like TokenBasedResource.
+ private static class ActivityResource {
+ /**
+ * The override configuration applied on top of the token's override config for this
+ * resource.
+ */
public final Configuration overrideConfig = new Configuration();
- public final ArrayList<WeakReference<Resources>> activityResources = new ArrayList<>();
- final ReferenceQueue<Resources> activityResourcesQueue = new ReferenceQueue<>();
+
+ /**
+ * If non-null this resource expects its configuration to override the display from the
+ * token's configuration.
+ *
+ * @see #applyDisplayMetricsToConfiguration(DisplayMetrics, Configuration)
+ */
+ @Nullable
+ public Integer overrideDisplayId;
+
+ @Nullable
+ public WeakReference<Resources> resources;
+
+ private ActivityResource() {}
}
/**
- * Each Activity may has a base override configuration that is applied to each Resources object,
- * which in turn may have their own override configuration specified.
+ * Each Activity or WindowToken may has a base override configuration that is applied to each
+ * Resources object, which in turn may have their own override configuration specified.
*/
@UnsupportedAppUsage
private final WeakHashMap<IBinder, ActivityResources> mActivityResourceReferences =
@@ -241,8 +309,7 @@ public class ResourcesManager {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public DisplayMetrics getDisplayMetrics() {
- return getDisplayMetrics(Display.DEFAULT_DISPLAY,
- DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ return getDisplayMetrics(mResDisplayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
/**
@@ -260,8 +327,8 @@ public class ResourcesManager {
return dm;
}
- private static void applyNonDefaultDisplayMetricsToConfiguration(
- @NonNull DisplayMetrics dm, @NonNull Configuration config) {
+ private static void applyDisplayMetricsToConfiguration(@NonNull DisplayMetrics dm,
+ @NonNull Configuration config) {
config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
config.densityDpi = dm.densityDpi;
config.screenWidthDp = (int) (dm.widthPixels / dm.density);
@@ -502,7 +569,7 @@ public class ResourcesManager {
int references = countLiveReferences(mResourceReferences);
for (ActivityResources activityResources : mActivityResourceReferences.values()) {
- references += countLiveReferences(activityResources.activityResources);
+ references += activityResources.countLiveReferences();
}
pw.println(references);
@@ -511,38 +578,36 @@ public class ResourcesManager {
}
}
- private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
+ private Configuration generateConfig(@NonNull ResourcesKey key) {
Configuration config;
- final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
final boolean hasOverrideConfig = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfig) {
+ if (hasOverrideConfig) {
config = new Configuration(getConfiguration());
- if (!isDefaultDisplay) {
- applyNonDefaultDisplayMetricsToConfiguration(dm, config);
- }
- if (hasOverrideConfig) {
- config.updateFrom(key.mOverrideConfiguration);
- if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
- }
+ config.updateFrom(key.mOverrideConfiguration);
+ if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
} else {
config = getConfiguration();
}
return config;
}
+ private int generateDisplayId(@NonNull ResourcesKey key) {
+ return key.mDisplayId != INVALID_DISPLAY ? key.mDisplayId : mResDisplayId;
+ }
+
private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key,
@Nullable ApkAssetsSupplier apkSupplier) {
- final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
- daj.setCompatibilityInfo(key.mCompatInfo);
-
final AssetManager assets = createAssetManager(key, apkSupplier);
if (assets == null) {
return null;
}
- final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj);
- final Configuration config = generateConfig(key, dm);
- final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj);
+ final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
+ daj.setCompatibilityInfo(key.mCompatInfo);
+
+ final Configuration config = generateConfig(key);
+ final DisplayMetrics displayMetrics = getDisplayMetrics(generateDisplayId(key), daj);
+ final ResourcesImpl impl = new ResourcesImpl(assets, displayMetrics, config, daj);
if (DEBUG) {
Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
@@ -652,8 +717,8 @@ public class ResourcesManager {
final int size = activityResources.activityResources.size();
for (int index = 0; index < size; index++) {
- WeakReference<Resources> ref = activityResources.activityResources.get(index);
- Resources resources = ref.get();
+ ActivityResource activityResource = activityResources.activityResources.get(index);
+ Resources resources = activityResource.resources.get();
ResourcesKey key = resources == null ? null : findKeyForResourceImplLocked(
resources.getImpl());
@@ -667,20 +732,28 @@ public class ResourcesManager {
return null;
}
- private @NonNull Resources createResourcesForActivityLocked(@NonNull IBinder activityToken,
+ @NonNull
+ private Resources createResourcesForActivityLocked(@NonNull IBinder activityToken,
+ @NonNull Configuration initialOverrideConfig, @Nullable Integer overrideDisplayId,
@NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl,
@NonNull CompatibilityInfo compatInfo) {
final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
activityToken);
cleanupReferences(activityResources.activityResources,
- activityResources.activityResourcesQueue);
+ activityResources.activityResourcesQueue,
+ (r) -> r.resources);
Resources resources = compatInfo.needsCompatResources() ? new CompatResources(classLoader)
: new Resources(classLoader);
resources.setImpl(impl);
resources.setCallbacks(mUpdateCallbacks);
- activityResources.activityResources.add(
- new WeakReference<>(resources, activityResources.activityResourcesQueue));
+
+ ActivityResource activityResource = new ActivityResource();
+ activityResource.resources = new WeakReference<>(resources,
+ activityResources.activityResourcesQueue);
+ activityResource.overrideConfig.setTo(initialOverrideConfig);
+ activityResource.overrideDisplayId = overrideDisplayId;
+ activityResources.activityResources.add(activityResource);
if (DEBUG) {
Slog.d(TAG, "- creating new ref=" + resources);
Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
@@ -706,7 +779,7 @@ public class ResourcesManager {
/**
* Creates base resources for a binder token. Calls to
- * {@link #getResources(IBinder, String, String[], String[], String[], int, Configuration,
+ * {@link #getResources(IBinder, String, String[], String[], String[], Integer, Configuration,
* CompatibilityInfo, ClassLoader, List)} with the same binder token will have their override
* configurations merged with the one specified here.
*
@@ -743,7 +816,7 @@ public class ResourcesManager {
overlayDirs,
libDirs,
displayId,
- overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
+ overrideConfig,
compatInfo,
loaders == null ? null : loaders.toArray(new ResourcesLoader[0]));
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
@@ -759,10 +832,7 @@ public class ResourcesManager {
}
// Update any existing Activity Resources references.
- updateResourcesForActivity(token, overrideConfig, displayId,
- false /* movedToDifferentDisplay */);
-
- rebaseKeyForActivity(token, key);
+ updateResourcesForActivity(token, overrideConfig, displayId);
synchronized (this) {
Resources resources = findResourcesForActivityLocked(token, key,
@@ -773,7 +843,9 @@ public class ResourcesManager {
}
// Now request an actual Resources object.
- return createResources(token, key, classLoader, /* apkSupplier */ null);
+ return createResourcesForActivity(token, key,
+ /* initialOverrideConfig */ Configuration.EMPTY, /* overrideDisplayId */ null,
+ classLoader, /* apkSupplier */ null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -781,20 +853,65 @@ public class ResourcesManager {
/**
* Rebases a key's override config on top of the Activity's base override.
+ *
+ * @param activityToken the token the supplied {@code key} is derived from.
+ * @param key the key to rebase
+ * @param overridesActivityDisplay whether this key is overriding the display from the token
*/
- private void rebaseKeyForActivity(IBinder activityToken, ResourcesKey key) {
+ private void rebaseKeyForActivity(IBinder activityToken, ResourcesKey key,
+ boolean overridesActivityDisplay) {
synchronized (this) {
final ActivityResources activityResources =
getOrCreateActivityResourcesStructLocked(activityToken);
- // Rebase the key's override config on top of the Activity's base override.
- if (key.hasOverrideConfiguration()
- && !activityResources.overrideConfig.equals(Configuration.EMPTY)) {
- final Configuration temp = new Configuration(activityResources.overrideConfig);
- temp.updateFrom(key.mOverrideConfiguration);
- key.mOverrideConfiguration.setTo(temp);
+ if (key.mDisplayId == INVALID_DISPLAY) {
+ key.mDisplayId = activityResources.overrideDisplayId;
+ }
+
+ Configuration config;
+ if (key.hasOverrideConfiguration()) {
+ config = new Configuration(activityResources.overrideConfig);
+ config.updateFrom(key.mOverrideConfiguration);
+ } else {
+ config = activityResources.overrideConfig;
+ }
+
+ if (overridesActivityDisplay
+ && key.mOverrideConfiguration.windowConfiguration.getAppBounds() == null) {
+ if (!key.hasOverrideConfiguration()) {
+ // Make a copy to handle the case where the override config is set to defaults.
+ config = new Configuration(config);
+ }
+
+ // If this key is overriding the display from the token and the key's
+ // window config app bounds is null we need to explicitly override this to
+ // ensure the display adjustments are as expected.
+ config.windowConfiguration.setAppBounds(null);
}
+
+ key.mOverrideConfiguration.setTo(config);
+ }
+ }
+
+ /**
+ * Rebases a key's override config with display metrics of the {@code overrideDisplay} paired
+ * with the {code displayAdjustments}.
+ *
+ * @see #applyDisplayMetricsToConfiguration(DisplayMetrics, Configuration)
+ */
+ private void rebaseKeyForDisplay(ResourcesKey key, int overrideDisplay) {
+ final Configuration temp = new Configuration();
+
+ DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
+ daj.setCompatibilityInfo(key.mCompatInfo);
+
+ final DisplayMetrics dm = getDisplayMetrics(overrideDisplay, daj);
+ applyDisplayMetricsToConfiguration(dm, temp);
+
+ if (key.hasOverrideConfiguration()) {
+ temp.updateFrom(key.mOverrideConfiguration);
}
+ key.mOverrideConfiguration.setTo(temp);
}
/**
@@ -802,18 +919,28 @@ public class ResourcesManager {
*/
private static <T> void cleanupReferences(ArrayList<WeakReference<T>> references,
ReferenceQueue<T> referenceQueue) {
- Reference<? extends T> enduedRef = referenceQueue.poll();
- if (enduedRef == null) {
+ cleanupReferences(references, referenceQueue, Function.identity());
+ }
+
+ /**
+ * Check WeakReferences and remove any dead references so they don't pile up.
+ */
+ private static <C, T> void cleanupReferences(ArrayList<C> referenceContainers,
+ ReferenceQueue<T> referenceQueue, Function<C, WeakReference<T>> unwrappingFunction) {
+ Reference<? extends T> enqueuedRef = referenceQueue.poll();
+ if (enqueuedRef == null) {
return;
}
final HashSet<Reference<? extends T>> deadReferences = new HashSet<>();
- for (; enduedRef != null; enduedRef = referenceQueue.poll()) {
- deadReferences.add(enduedRef);
+ for (; enqueuedRef != null; enqueuedRef = referenceQueue.poll()) {
+ deadReferences.add(enqueuedRef);
}
- ArrayUtils.unstableRemoveIf(references,
- (ref) -> ref == null || deadReferences.contains(ref));
+ ArrayUtils.unstableRemoveIf(referenceContainers, (refContainer) -> {
+ WeakReference<T> ref = unwrappingFunction.apply(refContainer);
+ return ref == null || deadReferences.contains(ref);
+ });
}
/**
@@ -849,23 +976,21 @@ public class ResourcesManager {
/**
* Creates a Resources object set with a ResourcesImpl object matching the given key.
*
- * @param activityToken The Activity this Resources object should be associated with.
* @param key The key describing the parameters of the ResourcesImpl object.
* @param classLoader The classloader to use for the Resources object.
* If null, {@link ClassLoader#getSystemClassLoader()} is used.
- * @param apkSupplier The apk assets supplier to use when creating a new ResourcesImpl object.
* @return A Resources object that gets updated when
* {@link #applyConfigurationToResourcesLocked(Configuration, CompatibilityInfo)}
* is called.
*/
- private @Nullable Resources createResources(@Nullable IBinder activityToken,
- @NonNull ResourcesKey key, @NonNull ClassLoader classLoader,
+ @Nullable
+ private Resources createResources(@NonNull ResourcesKey key, @NonNull ClassLoader classLoader,
@Nullable ApkAssetsSupplier apkSupplier) {
synchronized (this) {
if (DEBUG) {
Throwable here = new Throwable();
here.fillInStackTrace();
- Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
+ Slog.w(TAG, "!! Create resources for key=" + key, here);
}
ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key, apkSupplier);
@@ -873,12 +998,29 @@ public class ResourcesManager {
return null;
}
- if (activityToken != null) {
- return createResourcesForActivityLocked(activityToken, classLoader,
- resourcesImpl, key.mCompatInfo);
- } else {
- return createResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
+ return createResourcesLocked(classLoader, resourcesImpl, key.mCompatInfo);
+ }
+ }
+
+ @Nullable
+ private Resources createResourcesForActivity(@NonNull IBinder activityToken,
+ @NonNull ResourcesKey key, @NonNull Configuration initialOverrideConfig,
+ @Nullable Integer overrideDisplayId, @NonNull ClassLoader classLoader,
+ @Nullable ApkAssetsSupplier apkSupplier) {
+ synchronized (this) {
+ if (DEBUG) {
+ Throwable here = new Throwable();
+ here.fillInStackTrace();
+ Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
+ }
+
+ ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key, apkSupplier);
+ if (resourcesImpl == null) {
+ return null;
}
+
+ return createResourcesForActivityLocked(activityToken, initialOverrideConfig,
+ overrideDisplayId, classLoader, resourcesImpl, key.mCompatInfo);
}
}
@@ -899,7 +1041,10 @@ public class ResourcesManager {
* @param splitResDirs An array of split resource paths. Can be null.
* @param overlayDirs An array of overlay paths. Can be null.
* @param libDirs An array of resource library paths. Can be null.
- * @param displayId The ID of the display for which to create the resources.
+ * @param overrideDisplayId The ID of the display for which the returned Resources should be
+ * based. This will cause display-based configuration properties to override those of the base
+ * Resources for the {@code activityToken}, or the global configuration if {@code activityToken}
+ * is null.
* @param overrideConfig The configuration to apply on top of the base configuration. Can be
* null. Mostly used with Activities that are in multi-window which may override width and
* height properties from the base config.
@@ -909,13 +1054,14 @@ public class ResourcesManager {
* {@link ClassLoader#getSystemClassLoader()} is used.
* @return a Resources object from which to access resources.
*/
- public @Nullable Resources getResources(
+ @Nullable
+ public Resources getResources(
@Nullable IBinder activityToken,
@Nullable String resDir,
@Nullable String[] splitResDirs,
@Nullable String[] overlayDirs,
@Nullable String[] libDirs,
- int displayId,
+ @Nullable Integer overrideDisplayId,
@Nullable Configuration overrideConfig,
@NonNull CompatibilityInfo compatInfo,
@Nullable ClassLoader classLoader,
@@ -927,20 +1073,30 @@ public class ResourcesManager {
splitResDirs,
overlayDirs,
libDirs,
- displayId,
- overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
+ overrideDisplayId != null ? overrideDisplayId : INVALID_DISPLAY,
+ overrideConfig,
compatInfo,
loaders == null ? null : loaders.toArray(new ResourcesLoader[0]));
classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
- if (activityToken != null) {
- rebaseKeyForActivity(activityToken, key);
- }
-
// Preload the ApkAssets required by the key to prevent performing heavy I/O while the
// ResourcesManager lock is held.
final ApkAssetsSupplier assetsSupplier = createApkAssetsSupplierNotLocked(key);
- return createResources(activityToken, key, classLoader, assetsSupplier);
+
+ if (overrideDisplayId != null) {
+ rebaseKeyForDisplay(key, overrideDisplayId);
+ }
+
+ Resources resources;
+ if (activityToken != null) {
+ Configuration initialOverrideConfig = new Configuration(key.mOverrideConfiguration);
+ rebaseKeyForActivity(activityToken, key, overrideDisplayId != null);
+ resources = createResourcesForActivity(activityToken, key, initialOverrideConfig,
+ overrideDisplayId, classLoader, assetsSupplier);
+ } else {
+ resources = createResources(key, classLoader, assetsSupplier);
+ }
+ return resources;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -949,24 +1105,26 @@ public class ResourcesManager {
/**
* Updates an Activity's Resources object with overrideConfig. The Resources object
* that was previously returned by {@link #getResources(IBinder, String, String[], String[],
- * String[], int, Configuration, CompatibilityInfo, ClassLoader, List)} is still valid and will
- * have the updated configuration.
+ * String[], Integer, Configuration, CompatibilityInfo, ClassLoader, List)} is still valid and
+ * will have the updated configuration.
*
* @param activityToken The Activity token.
* @param overrideConfig The configuration override to update.
* @param displayId Id of the display where activity currently resides.
- * @param movedToDifferentDisplay Indicates if the activity was moved to different display.
*/
public void updateResourcesForActivity(@NonNull IBinder activityToken,
- @Nullable Configuration overrideConfig, int displayId,
- boolean movedToDifferentDisplay) {
+ @Nullable Configuration overrideConfig, int displayId) {
try {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
"ResourcesManager#updateResourcesForActivity");
+ if (displayId == INVALID_DISPLAY) {
+ throw new IllegalArgumentException("displayId can not be INVALID_DISPLAY");
+ }
synchronized (this) {
final ActivityResources activityResources =
getOrCreateActivityResourcesStructLocked(activityToken);
+ boolean movedToDifferentDisplay = activityResources.overrideDisplayId != displayId;
if (Objects.equals(activityResources.overrideConfig, overrideConfig)
&& !movedToDifferentDisplay) {
// They are the same and no change of display id, no work to do.
@@ -983,6 +1141,8 @@ public class ResourcesManager {
} else {
activityResources.overrideConfig.unset();
}
+ // Update the Activity's override display id.
+ activityResources.overrideDisplayId = displayId;
if (DEBUG) {
Throwable here = new Throwable();
@@ -1000,24 +1160,26 @@ public class ResourcesManager {
// Rebase each Resources associated with this Activity.
final int refCount = activityResources.activityResources.size();
for (int i = 0; i < refCount; i++) {
- final WeakReference<Resources> weakResRef =
+ final ActivityResource activityResource =
activityResources.activityResources.get(i);
- final Resources resources = weakResRef.get();
+ final Resources resources = activityResource.resources.get();
if (resources == null) {
continue;
}
- final ResourcesKey newKey = rebaseActivityOverrideConfig(resources, oldConfig,
+ final ResourcesKey newKey = rebaseActivityOverrideConfig(activityResource,
overrideConfig, displayId);
- if (newKey != null) {
- final ResourcesImpl resourcesImpl =
- findOrCreateResourcesImplForKeyLocked(newKey);
- if (resourcesImpl != null && resourcesImpl != resources.getImpl()) {
- // Set the ResourcesImpl, updating it for all users of this Resources
- // object.
- resources.setImpl(resourcesImpl);
- }
+ if (newKey == null) {
+ continue;
+ }
+
+ final ResourcesImpl resourcesImpl =
+ findOrCreateResourcesImplForKeyLocked(newKey);
+ if (resourcesImpl != null && resourcesImpl != resources.getImpl()) {
+ // Set the ResourcesImpl, updating it for all users of this Resources
+ // object.
+ resources.setImpl(resourcesImpl);
}
}
}
@@ -1031,9 +1193,13 @@ public class ResourcesManager {
* that an Activity's Resources should be set to.
*/
@Nullable
- private ResourcesKey rebaseActivityOverrideConfig(@NonNull Resources resources,
- @NonNull Configuration oldOverrideConfig, @Nullable Configuration newOverrideConfig,
- int displayId) {
+ private ResourcesKey rebaseActivityOverrideConfig(@NonNull ActivityResource activityResource,
+ @Nullable Configuration newOverrideConfig, int displayId) {
+ final Resources resources = activityResource.resources.get();
+ if (resources == null) {
+ return null;
+ }
+
// Extract the ResourcesKey that was last used to create the Resources for this
// activity.
final ResourcesKey oldKey = findKeyForResourceImplLocked(resources.getImpl());
@@ -1049,16 +1215,33 @@ public class ResourcesManager {
rebasedOverrideConfig.setTo(newOverrideConfig);
}
- final boolean hadOverrideConfig = !oldOverrideConfig.equals(Configuration.EMPTY);
- if (hadOverrideConfig && oldKey.hasOverrideConfiguration()) {
- // Generate a delta between the old base Activity override configuration and
- // the actual final override configuration that was used to figure out the
- // real delta this Resources object wanted.
- Configuration overrideOverrideConfig = Configuration.generateDelta(
- oldOverrideConfig, oldKey.mOverrideConfiguration);
- rebasedOverrideConfig.updateFrom(overrideOverrideConfig);
+ final Integer overrideDisplayId = activityResource.overrideDisplayId;
+ if (overrideDisplayId != null) {
+ DisplayAdjustments displayAdjustments = new DisplayAdjustments(rebasedOverrideConfig);
+ displayAdjustments.getConfiguration().setTo(activityResource.overrideConfig);
+ displayAdjustments.setCompatibilityInfo(oldKey.mCompatInfo);
+
+ DisplayMetrics dm = getDisplayMetrics(overrideDisplayId, displayAdjustments);
+ applyDisplayMetricsToConfiguration(dm, rebasedOverrideConfig);
+ }
+
+ final boolean hasOverrideConfig =
+ !activityResource.overrideConfig.equals(Configuration.EMPTY);
+ if (hasOverrideConfig) {
+ rebasedOverrideConfig.updateFrom(activityResource.overrideConfig);
}
+ if (activityResource.overrideDisplayId != null
+ && activityResource.overrideConfig.windowConfiguration.getAppBounds() == null) {
+ // If this activity resource is overriding the display from the token and the key's
+ // window config app bounds is null we need to explicitly override this to
+ // ensure the display adjustments are as expected.
+ rebasedOverrideConfig.windowConfiguration.setAppBounds(null);
+ }
+
+ // Ensure the new key keeps the expected override display instead of the new token display.
+ displayId = overrideDisplayId != null ? overrideDisplayId : displayId;
+
// Create the new ResourcesKey with the rebased override config.
final ResourcesKey newKey = new ResourcesKey(oldKey.mResDir,
oldKey.mSplitResDirs, oldKey.mOverlayDirs, oldKey.mLibDirs,
@@ -1090,12 +1273,11 @@ public class ResourcesManager {
+ mResConfiguration.seq + ", newSeq=" + config.seq);
return false;
}
- int changes = mResConfiguration.updateFrom(config);
+
// Things might have changed in display manager, so clear the cached displays.
mAdjustedDisplays.clear();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
-
+ int changes = mResConfiguration.updateFrom(config);
if (compat != null && (mResCompatibilityInfo == null ||
!mResCompatibilityInfo.equals(compat))) {
mResCompatibilityInfo = compat;
@@ -1104,10 +1286,10 @@ public class ResourcesManager {
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
}
- Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
+ DisplayMetrics displayMetrics = getDisplayMetrics();
+ Resources.updateSystemConfiguration(config, displayMetrics, compat);
ApplicationPackageManager.configurationChanged();
- //Slog.i(TAG, "Configuration changed in " + currentPackageName());
Configuration tmpConfig = new Configuration();
@@ -1137,11 +1319,7 @@ public class ResourcesManager {
}
tmpConfig.setTo(config);
-
- // Apply the override configuration before setting the display adjustments to ensure that
- // the process config does not override activity display adjustments.
- final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
- if (hasOverrideConfiguration) {
+ if (key.hasOverrideConfiguration()) {
tmpConfig.updateFrom(key.mOverrideConfiguration);
}
@@ -1153,22 +1331,8 @@ public class ResourcesManager {
daj = new DisplayAdjustments(daj);
daj.setCompatibilityInfo(compat);
}
-
- final int displayId = key.mDisplayId;
- if (displayId == Display.DEFAULT_DISPLAY) {
- daj.setConfiguration(tmpConfig);
- }
- DisplayMetrics dm = getDisplayMetrics(displayId, daj);
- if (displayId != Display.DEFAULT_DISPLAY) {
- applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
-
- // Re-apply the override configuration to ensure that configuration contexts based on
- // a display context (ex: createDisplayContext().createConfigurationContext()) have the
- // correct override.
- if (hasOverrideConfiguration) {
- tmpConfig.updateFrom(key.mOverrideConfiguration);
- }
- }
+ daj.setConfiguration(tmpConfig);
+ DisplayMetrics dm = getDisplayMetrics(generateDisplayId(key), daj);
resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
}
@@ -1305,8 +1469,10 @@ public class ResourcesManager {
for (ActivityResources activityResources : mActivityResourceReferences.values()) {
final int resCount = activityResources.activityResources.size();
for (int i = 0; i < resCount; i++) {
- final WeakReference<Resources> ref = activityResources.activityResources.get(i);
- final Resources r = ref != null ? ref.get() : null;
+ final ActivityResource activityResource =
+ activityResources.activityResources.get(i);
+ final Resources r = activityResource != null
+ ? activityResource.resources.get() : null;
if (r != null) {
final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
if (key != null) {
@@ -1338,10 +1504,16 @@ public class ResourcesManager {
if (tokenResources == null) {
return false;
}
- final ArrayList<WeakReference<Resources>> resourcesRefs =
- tokenResources.activityResources;
+ final ArrayList<ActivityResource> resourcesRefs = tokenResources.activityResources;
for (int i = resourcesRefs.size() - 1; i >= 0; i--) {
- final Resources res = resourcesRefs.get(i).get();
+ final ActivityResource activityResource = resourcesRefs.get(i);
+ if (activityResource.overrideDisplayId != null) {
+ // This resource overrides the display of the token so we should not be
+ // modifying its display adjustments here.
+ continue;
+ }
+
+ final Resources res = activityResource.resources.get();
if (res != null) {
res.overrideDisplayAdjustments(override);
handled = true;
diff --git a/core/java/android/app/WindowTokenClient.java b/core/java/android/app/WindowTokenClient.java
index b5d103959818..9092ef36deb6 100644
--- a/core/java/android/app/WindowTokenClient.java
+++ b/core/java/android/app/WindowTokenClient.java
@@ -71,8 +71,7 @@ public class WindowTokenClient extends IWindowToken.Stub {
final boolean configChanged = config.diff(newConfig) != 0;
if (displayChanged || configChanged) {
// TODO(ag/9789103): update resource manager logic to track non-activity tokens
- mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId,
- displayChanged);
+ mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);
}
if (displayChanged) {
context.updateDisplay(newDisplayId);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 200604801b97..0f1f276ce0f9 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -88,7 +88,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
import android.util.apk.ApkSignatureVerifier;
-import android.view.Display;
import android.view.Gravity;
import com.android.internal.R;
@@ -8536,7 +8535,7 @@ public class PackageParser {
null,
androidAppInfo.resourceDirs,
androidAppInfo.sharedLibraryFiles,
- Display.DEFAULT_DISPLAY,
+ null,
null,
systemResources.getCompatibilityInfo(),
systemResources.getClassLoader(),
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 9da0f20d1006..fcb80aa3e58d 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -16,6 +16,8 @@
package android.content.res;
+import static android.os.Build.VERSION_CODES.O;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -41,8 +43,17 @@ public final class ResourcesKey {
@Nullable
public final String[] mLibDirs;
- public final int mDisplayId;
-
+ /**
+ * The display ID that overrides the global resources display to produce the Resources display.
+ * If set to something other than {@link android.view.Display#INVALID_DISPLAY} this will
+ * override the global resources display for this key.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = O)
+ public int mDisplayId;
+
+ /**
+ * The configuration applied to the global configuration to produce the Resources configuration.
+ */
@NonNull
public final Configuration mOverrideConfiguration;
@@ -58,7 +69,7 @@ public final class ResourcesKey {
@Nullable String[] splitResDirs,
@Nullable String[] overlayDirs,
@Nullable String[] libDirs,
- int displayId,
+ int overrideDisplayId,
@Nullable Configuration overrideConfig,
@Nullable CompatibilityInfo compatInfo,
@Nullable ResourcesLoader[] loader) {
@@ -67,7 +78,7 @@ public final class ResourcesKey {
mOverlayDirs = overlayDirs;
mLibDirs = libDirs;
mLoaders = (loader != null && loader.length == 0) ? null : loader;
- mDisplayId = displayId;
+ mDisplayId = overrideDisplayId;
mOverrideConfiguration = new Configuration(overrideConfig != null
? overrideConfig : Configuration.EMPTY);
mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
@@ -77,7 +88,7 @@ public final class ResourcesKey {
hash = 31 * hash + Arrays.hashCode(mSplitResDirs);
hash = 31 * hash + Arrays.hashCode(mOverlayDirs);
hash = 31 * hash + Arrays.hashCode(mLibDirs);
- hash = 31 * hash + mDisplayId;
+ hash = 31 * hash + Objects.hashCode(mDisplayId);
hash = 31 * hash + Objects.hashCode(mOverrideConfiguration);
hash = 31 * hash + Objects.hashCode(mCompatInfo);
hash = 31 * hash + Arrays.hashCode(mLoaders);
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index a6e6d057d48c..b80718018652 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -938,7 +938,6 @@ public class PhoneStateListener {
* {@link SubscriptionManager#getDefaultSubscriptionId})
* and the value as the list of {@link EmergencyNumber};
* null if this information is not available.
- * @hide
*/
public void onEmergencyNumberListChanged(
@NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList) {
@@ -948,17 +947,50 @@ public class PhoneStateListener {
/**
* Callback invoked when an outgoing call is placed to an emergency number.
*
- * @param placedEmergencyNumber the emergency number {@link EmergencyNumber} the call is placed
- * to.
+ * This method will be called when an emergency call is placed on any subscription (including
+ * the no-SIM case), regardless of which subscription this listener was registered on.
+ *
+ * This method is deprecated. Both this method and the new
+ * {@link #onOutgoingEmergencyCall(EmergencyNumber, int)} will be called when an outgoing
+ * emergency call is placed.
+ *
+ * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
+ *
+ * @deprecated Use {@link #onOutgoingEmergencyCall(EmergencyNumber, int)}.
* @hide
*/
@SystemApi
@TestApi
+ @Deprecated
public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
// default implementation empty
}
/**
+ * Callback invoked when an outgoing call is placed to an emergency number.
+ *
+ * This method will be called when an emergency call is placed on any subscription (including
+ * the no-SIM case), regardless of which subscription this listener was registered on.
+ *
+ * Both this method and the deprecated {@link #onOutgoingEmergencyCall(EmergencyNumber)} will be
+ * called when an outgoing emergency call is placed. You should only implement one of these
+ * methods.
+ *
+ * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was placed to.
+ * @param subscriptionId The subscription ID used to place the emergency call. If the
+ * emergency call was placed without a valid subscription (e.g. when there
+ * are no SIM cards in the device), this will be equal to
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
+ int subscriptionId) {
+ }
+
+ /**
* Callback invoked when an outgoing SMS is placed to an emergency number.
*
* @param sentEmergencyNumber the emergency number {@link EmergencyNumber} the SMS is sent to.
@@ -1336,13 +1368,19 @@ public class PhoneStateListener {
() -> psl.onEmergencyNumberListChanged(emergencyNumberList)));
}
- public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber) {
+ public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
+ int subscriptionId) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(
() -> psl.onOutgoingEmergencyCall(placedEmergencyNumber)));
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onOutgoingEmergencyCall(placedEmergencyNumber,
+ subscriptionId)));
}
public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber) {
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
index f44b9fb7e723..9698f190a419 100644
--- a/core/java/com/android/internal/os/TEST_MAPPING
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -26,5 +26,20 @@
"KernelSingleUidTimeReader\\.java"
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "com.android.internal.os.BstatsCpuTimesValidationTest"
+ }
+ ],
+ "file_patterns": [
+ "BatteryStatsImpl\\.java",
+ "KernelCpuUidFreqTimeReader\\.java",
+ "KernelSingleUidTimeReader\\.java"
+ ]
+ }
]
}
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index b2c5a998e254..d41d30735d7d 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -61,7 +61,7 @@ oneway interface IPhoneStateListener {
void onRadioPowerStateChanged(in int state);
void onCallAttributesChanged(in CallAttributes callAttributes);
void onEmergencyNumberListChanged(in Map emergencyNumberList);
- void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber);
+ void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber, int subscriptionId);
void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber);
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 26dac618ee7e..b6f6627a5b8e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -515,9 +515,9 @@
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"‏للسماح للتطبيق بتلقّي الحِزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام جهاز Android TV فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق ما يتم استهلاكه في وضع البث غير المتعدد."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"‏للسماح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام هاتفك فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
<string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"الدخول إلى إعدادات بلوتوث"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"للسماح للتطبيق بتهيئة لوحة البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"للسماح للتطبيق بإعداد لوحة البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"‏للسماح للتطبيق بضبط البلوتوث على جهاز Android TV واكتشاف الأجهزة البعيدة والاقتران بها."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"للسماح للتطبيق بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"للسماح للتطبيق بإعداد هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
<string name="permlab_accessWimaxState" msgid="7029563339012437434">"‏الاتصال بـشبكة WiMAX وقطع الاتصال بها"</string>
<string name="permdesc_accessWimaxState" msgid="5372734776802067708">"‏للسماح للتطبيق بتحديد ما إذا تم تفعيل WiMAX وتحديد معلومات حول أي شبكات WiMAX متصلة."</string>
<string name="permlab_changeWimaxState" msgid="6223305780806267462">"‏تغيير حالة WiMAX"</string>
@@ -1412,7 +1412,7 @@
<string name="select_input_method" msgid="3971267998568587025">"اختيار أسلوب الإدخال"</string>
<string name="show_ime" msgid="6406112007347443383">"استمرار عرضها على الشاشة أثناء نشاط لوحة المفاتيح الفعلية"</string>
<string name="hardware" msgid="1800597768237606953">"إظهار لوحة المفاتيح الافتراضية"</string>
- <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"تهيئة لوحة المفاتيح الفعلية"</string>
+ <string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"إعداد لوحة المفاتيح الفعلية"</string>
<string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"انقر لاختيار لغة وتنسيق"</string>
<string name="fast_scroll_alphabet" msgid="8854435958703888376">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
<string name="fast_scroll_numeric_alphabet" msgid="2529539945421557329">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 085df65907f8..f9e3e2fa97e7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -945,7 +945,7 @@
<string name="autofill_postal_code" msgid="7034789388968295591">"Kode pos"</string>
<string name="autofill_state" msgid="3341725337190434069">"Negara Bagian"</string>
<string name="autofill_zip_code" msgid="1315503730274962450">"Kode pos"</string>
- <string name="autofill_county" msgid="7781382735643492173">"Wilayah"</string>
+ <string name="autofill_county" msgid="7781382735643492173">"County"</string>
<string name="autofill_island" msgid="5367139008536593734">"Pulau"</string>
<string name="autofill_district" msgid="6428712062213557327">"Distrik"</string>
<string name="autofill_department" msgid="9047276226873531529">"Departemen"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 8871293c1b2f..df7781e089dd 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1773,7 +1773,7 @@
<string name="restr_pin_try_later" msgid="5897719962541636727">"Обиди се повторно подоцна"</string>
<string name="immersive_cling_title" msgid="2307034298721541791">"Се прикажува на цел екран"</string>
<string name="immersive_cling_description" msgid="7092737175345204832">"За да излезете, повлечете одозгора надолу."</string>
- <string name="immersive_cling_positive" msgid="7047498036346489883">"Разбрав"</string>
+ <string name="immersive_cling_positive" msgid="7047498036346489883">"Сфатив"</string>
<string name="done_label" msgid="7283767013231718521">"Готово"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Приказ на часови во кружно движење"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Приказ на минути во кружно движење"</string>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 000e870369db..0a751dd7c66b 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -408,6 +408,9 @@ public class ActivityThreadTest {
int originalVirtualDisplayOrientation = virtualDisplayContext.getResources()
.getConfiguration().orientation;
+
+ // Perform global config change and verify there is no config change in derived display
+ // context.
Configuration newAppConfig = new Configuration(originalAppConfig);
newAppConfig.seq++;
newAppConfig.orientation = newAppConfig.orientation == ORIENTATION_PORTRAIT
@@ -417,7 +420,7 @@ public class ActivityThreadTest {
activityThread.handleConfigurationChanged(newAppConfig);
try {
- assertEquals("Virtual display orientation should not change when process"
+ assertEquals("Virtual display orientation must not change when process"
+ " configuration orientation changes.",
originalVirtualDisplayOrientation,
virtualDisplayContext.getResources().getConfiguration().orientation);
@@ -438,6 +441,50 @@ public class ActivityThreadTest {
}
@Test
+ public void testActivityOrientationChanged_DoesntOverrideVirtualDisplayOrientation() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+ final ActivityThread activityThread = activity.getActivityThread();
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ Configuration originalActivityConfig =
+ new Configuration(activity.getResources().getConfiguration());
+ DisplayManager dm = activity.getSystemService(DisplayManager.class);
+
+ int virtualDisplayWidth;
+ int virtualDisplayHeight;
+ if (originalActivityConfig.orientation == ORIENTATION_PORTRAIT) {
+ virtualDisplayWidth = 100;
+ virtualDisplayHeight = 200;
+ } else {
+ virtualDisplayWidth = 200;
+ virtualDisplayHeight = 100;
+ }
+ Display virtualDisplay = dm.createVirtualDisplay("virtual-display",
+ virtualDisplayWidth, virtualDisplayHeight, 200, null, 0).getDisplay();
+ Context virtualDisplayContext = activity.createDisplayContext(virtualDisplay);
+ int originalVirtualDisplayOrientation = virtualDisplayContext.getResources()
+ .getConfiguration().orientation;
+
+ // Perform activity config change and verify there is no config change in derived
+ // display context.
+ Configuration newActivityConfig = new Configuration(originalActivityConfig);
+ newActivityConfig.seq++;
+ newActivityConfig.orientation = newActivityConfig.orientation == ORIENTATION_PORTRAIT
+ ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
+
+ activityThread.updatePendingActivityConfiguration(activity.getActivityToken(),
+ newActivityConfig);
+ activityThread.handleActivityConfigurationChanged(activity.getActivityToken(),
+ newActivityConfig, INVALID_DISPLAY);
+
+ assertEquals("Virtual display orientation must not change when activity"
+ + " configuration orientation changes.",
+ originalVirtualDisplayOrientation,
+ virtualDisplayContext.getResources().getConfiguration().orientation);
+ });
+ }
+
+ @Test
public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index efcd458e19cc..45adf833de97 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -29,31 +29,50 @@ import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
+import java.util.HashMap;
+import java.util.Map;
+
public class ResourcesManagerTest extends TestCase {
+ private static final int SECONDARY_DISPLAY_ID = 1;
private static final String APP_ONE_RES_DIR = "app_one.apk";
private static final String APP_ONE_RES_SPLIT_DIR = "app_one_split.apk";
private static final String APP_TWO_RES_DIR = "app_two.apk";
private static final String LIB_RES_DIR = "lib.apk";
private ResourcesManager mResourcesManager;
- private DisplayMetrics mDisplayMetrics;
+ private Map<Integer, DisplayMetrics> mDisplayMetricsMap;
@Override
protected void setUp() throws Exception {
super.setUp();
- mDisplayMetrics = new DisplayMetrics();
- mDisplayMetrics.setToDefaults();
+ mDisplayMetricsMap = new HashMap<>();
+
+ DisplayMetrics defaultDisplayMetrics = new DisplayMetrics();
+ defaultDisplayMetrics.setToDefaults();
// Override defaults (which take device specific properties).
- mDisplayMetrics.density = 1.0f;
- mDisplayMetrics.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
- mDisplayMetrics.xdpi = DisplayMetrics.DENSITY_DEFAULT;
- mDisplayMetrics.ydpi = DisplayMetrics.DENSITY_DEFAULT;
- mDisplayMetrics.noncompatDensity = mDisplayMetrics.density;
- mDisplayMetrics.noncompatDensityDpi = mDisplayMetrics.densityDpi;
- mDisplayMetrics.noncompatXdpi = DisplayMetrics.DENSITY_DEFAULT;
- mDisplayMetrics.noncompatYdpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.density = 1.0f;
+ defaultDisplayMetrics.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.xdpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.ydpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.widthPixels = 1440;
+ defaultDisplayMetrics.heightPixels = 2960;
+ defaultDisplayMetrics.noncompatDensity = defaultDisplayMetrics.density;
+ defaultDisplayMetrics.noncompatDensityDpi = defaultDisplayMetrics.densityDpi;
+ defaultDisplayMetrics.noncompatXdpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.noncompatYdpi = DisplayMetrics.DENSITY_DEFAULT;
+ defaultDisplayMetrics.noncompatWidthPixels = defaultDisplayMetrics.widthPixels;
+ defaultDisplayMetrics.noncompatHeightPixels = defaultDisplayMetrics.heightPixels;
+ mDisplayMetricsMap.put(Display.DEFAULT_DISPLAY, defaultDisplayMetrics);
+
+ DisplayMetrics secondaryDisplayMetrics = new DisplayMetrics();
+ secondaryDisplayMetrics.setTo(defaultDisplayMetrics);
+ secondaryDisplayMetrics.widthPixels = 50;
+ secondaryDisplayMetrics.heightPixels = 100;
+ secondaryDisplayMetrics.noncompatWidthPixels = secondaryDisplayMetrics.widthPixels;
+ secondaryDisplayMetrics.noncompatHeightPixels = secondaryDisplayMetrics.heightPixels;
+ mDisplayMetricsMap.put(SECONDARY_DISPLAY_ID, secondaryDisplayMetrics);
mResourcesManager = new ResourcesManager() {
@Override
@@ -63,7 +82,7 @@ public class ResourcesManagerTest extends TestCase {
@Override
protected DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments daj) {
- return mDisplayMetrics;
+ return mDisplayMetricsMap.get(displayId);
}
};
}
@@ -71,12 +90,12 @@ public class ResourcesManagerTest extends TestCase {
@SmallTest
public void testMultipleCallsWithIdenticalParametersCacheReference() {
Resources resources = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources);
Resources newResources = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(newResources);
assertSame(resources, newResources);
@@ -85,14 +104,14 @@ public class ResourcesManagerTest extends TestCase {
@SmallTest
public void testMultipleCallsWithDifferentParametersReturnDifferentReferences() {
Resources resources = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources);
Configuration overrideConfig = new Configuration();
overrideConfig.smallestScreenWidthDp = 200;
Resources newResources = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, overrideConfig,
+ null, APP_ONE_RES_DIR, null, null, null, null, overrideConfig,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(newResources);
assertNotSame(resources, newResources);
@@ -101,13 +120,13 @@ public class ResourcesManagerTest extends TestCase {
@SmallTest
public void testAddingASplitCreatesANewImpl() {
Resources resources1 = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources1);
Resources resources2 = mResourcesManager.getResources(
null, APP_ONE_RES_DIR, new String[] { APP_ONE_RES_SPLIT_DIR }, null, null,
- Display.DEFAULT_DISPLAY, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,null,
+ null, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null,
null);
assertNotNull(resources2);
@@ -118,12 +137,12 @@ public class ResourcesManagerTest extends TestCase {
@SmallTest
public void testUpdateConfigurationUpdatesAllAssetManagers() {
Resources resources1 = mResourcesManager.getResources(
- null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources1);
Resources resources2 = mResourcesManager.getResources(
- null, APP_TWO_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ null, APP_TWO_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources2);
@@ -131,7 +150,7 @@ public class ResourcesManagerTest extends TestCase {
final Configuration overrideConfig = new Configuration();
overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
Resources resources3 = mResourcesManager.getResources(
- activity, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+ activity, APP_ONE_RES_DIR, null, null, null, null,
overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources3);
@@ -152,7 +171,7 @@ public class ResourcesManagerTest extends TestCase {
final Configuration expectedConfig = new Configuration();
expectedConfig.setToDefaults();
expectedConfig.setLocales(LocaleList.getAdjustedDefault());
- expectedConfig.densityDpi = mDisplayMetrics.densityDpi;
+ expectedConfig.densityDpi = mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).densityDpi;
expectedConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
assertEquals(expectedConfig, resources1.getConfiguration());
@@ -164,13 +183,13 @@ public class ResourcesManagerTest extends TestCase {
public void testTwoActivitiesWithIdenticalParametersShareImpl() {
Binder activity1 = new Binder();
Resources resources1 = mResourcesManager.getResources(
- activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ activity1, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources1);
Binder activity2 = new Binder();
Resources resources2 = mResourcesManager.getResources(
- activity2, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ activity2, APP_ONE_RES_DIR, null, null, null, null, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources1);
@@ -201,7 +220,7 @@ public class ResourcesManagerTest extends TestCase {
final Configuration overrideConfig = new Configuration();
overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
mResourcesManager.updateResourcesForActivity(activity1, overrideConfig,
- Display.DEFAULT_DISPLAY, false /* movedToDifferentDisplay */);
+ Display.DEFAULT_DISPLAY);
assertSame(resources1, theme.getResources());
// Make sure we can still access the data.
@@ -226,7 +245,7 @@ public class ResourcesManagerTest extends TestCase {
Configuration config2 = new Configuration();
config2.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
Resources resources2 = mResourcesManager.getResources(
- activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, config2,
+ activity1, APP_ONE_RES_DIR, null, null, null, null, config2,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
assertNotNull(resources2);
@@ -250,8 +269,7 @@ public class ResourcesManagerTest extends TestCase {
// Now update the Activity base override, and both resources should update.
config1.orientation = Configuration.ORIENTATION_LANDSCAPE;
- mResourcesManager.updateResourcesForActivity(activity1, config1, Display.DEFAULT_DISPLAY,
- false /* movedToDifferentDisplay */);
+ mResourcesManager.updateResourcesForActivity(activity1, config1, Display.DEFAULT_DISPLAY);
expectedConfig1.orientation = Configuration.ORIENTATION_LANDSCAPE;
assertEquals(expectedConfig1, resources1.getConfiguration());
@@ -290,4 +308,41 @@ public class ResourcesManagerTest extends TestCase {
assertEquals(originalOverrideDensity,
resources.getDisplayAdjustments().getConfiguration().densityDpi);
}
+
+ @SmallTest
+ public void testChangingActivityDisplayDoesntOverrideDisplayRequestedByResources() {
+ Binder activity = new Binder();
+
+ // Create a base token resources that are based on the default display.
+ Resources activityResources = mResourcesManager.createBaseTokenResources(
+ activity, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
+ // Create another resources that explicitly override the display of the base token above
+ // and set it to DEFAULT_DISPLAY.
+ Resources defaultDisplayResources = mResourcesManager.getResources(
+ activity, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null, null);
+
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).widthPixels,
+ activityResources.getDisplayMetrics().widthPixels);
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).heightPixels,
+ activityResources.getDisplayMetrics().heightPixels);
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).widthPixels,
+ defaultDisplayResources.getDisplayMetrics().widthPixels);
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).widthPixels,
+ defaultDisplayResources.getDisplayMetrics().widthPixels);
+
+ // Now change the display of the activity and ensure the activity's display metrics match
+ // the new display, but the other resources remain based on the default display.
+ mResourcesManager.updateResourcesForActivity(activity, null, SECONDARY_DISPLAY_ID);
+
+ assertEquals(mDisplayMetricsMap.get(SECONDARY_DISPLAY_ID).widthPixels,
+ activityResources.getDisplayMetrics().widthPixels);
+ assertEquals(mDisplayMetricsMap.get(SECONDARY_DISPLAY_ID).heightPixels,
+ activityResources.getDisplayMetrics().heightPixels);
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).widthPixels,
+ defaultDisplayResources.getDisplayMetrics().widthPixels);
+ assertEquals(mDisplayMetricsMap.get(Display.DEFAULT_DISPLAY).widthPixels,
+ defaultDisplayResources.getDisplayMetrics().widthPixels);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 7807f019914e..bef27e2a2f63 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -39,6 +39,7 @@ import org.junit.runners.Suite;
BatteryStatsTimerTest.class,
BatteryStatsUidTest.class,
BatteryStatsUserLifecycleTests.class,
+ BstatsCpuTimesValidationTest.class,
KernelCpuProcStringReaderTest.class,
KernelCpuUidActiveTimeReaderTest.class,
KernelCpuUidBpfMapReaderTest.class,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index aeda2d923490..283fd8d997c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -68,7 +68,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
- protected DisplayImeController(IWindowManager wmService, DisplayController displayController,
+ public DisplayImeController(IWindowManager wmService, DisplayController displayController,
Handler mainHandler, TransactionPool transactionPool) {
mHandler = mainHandler;
mWmService = wmService;
@@ -76,7 +76,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
mDisplayController = displayController;
}
- protected void startMonitorDisplays() {
+ /** Starts monitor displays changes and set insets controller for each displays. */
+ public void startMonitorDisplays() {
mDisplayController.addDisplayWindowListener(this);
}
@@ -493,29 +494,4 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
return IInputMethodManager.Stub.asInterface(
ServiceManager.getService(Context.INPUT_METHOD_SERVICE));
}
-
- /** Builds {@link DisplayImeController} instance. */
- public static class Builder {
- private IWindowManager mWmService;
- private DisplayController mDisplayController;
- private Handler mHandler;
- private TransactionPool mTransactionPool;
-
- public Builder(IWindowManager wmService, DisplayController displayController,
- Handler handler, TransactionPool transactionPool) {
- mWmService = wmService;
- mDisplayController = displayController;
- mHandler = handler;
- mTransactionPool = transactionPool;
- }
-
- /** Builds and initializes {@link DisplayImeController} instance. */
- public DisplayImeController build() {
- DisplayImeController displayImeController = new DisplayImeController(mWmService,
- mDisplayController, mHandler, mTransactionPool);
- // Separates startMonitorDisplays from constructor to prevent circular init issue.
- displayImeController.startMonitorDisplays();
- return displayImeController;
- }
- }
}
diff --git a/libs/WindowManager/Shell/tests/README.md b/libs/WindowManager/Shell/tests/README.md
new file mode 100644
index 000000000000..c19db76a358c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/README.md
@@ -0,0 +1,15 @@
+# WM Shell Test
+
+This contains all tests written for WM (WindowManager) Shell and it's currently
+divided into 3 categories
+
+- unittest, tests against individual functions, usually @SmallTest and do not
+ require UI automation nor real device to run
+- integration, this maybe a mix of functional and integration tests. Contains
+ tests verify the WM Shell as a whole, like talking to WM core. This usually
+ involves mocking the window manager service or even talking to the real one.
+ Due to this nature, test cases in this package is normally annotated as
+ @LargeTest and runs with UI automation on real device
+- flicker, similar to functional tests with its sole focus on flickerness. See
+ [WM Shell Flicker Test Package](http://cs/android/framework/base/libs/WindowManager/Shell/tests/flicker/)
+ for more details
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
new file mode 100644
index 000000000000..587902221826
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "WMShellFlickerTests",
+ srcs: ["src/**/*.java", "src/**/*.kt"],
+ manifest: "AndroidManifest.xml",
+ test_config: "AndroidTest.xml",
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "flickerlib",
+ "truth-prebuilt",
+ "app-helpers-core",
+ "launcher-helper-lib",
+ "launcher-aosp-tapl"
+ ],
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
new file mode 100644
index 000000000000..8b2f6681554a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wm.shell.flicker">
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
+ <!-- Read and write traces from external storage -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <!-- Write secure settings -->
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <!-- Capture screen contents -->
+ <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+ <!-- Enable / Disable tracing !-->
+ <uses-permission android:name="android.permission.DUMP" />
+ <!-- Run layers trace -->
+ <uses-permission android:name="android.permission.HARDWARE_TEST"/>
+ <!-- Workaround grant runtime permission exception from b/152733071 -->
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+ <uses-permission android:name="android.permission.READ_LOGS"/>
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.wm.shell.flicker"
+ android:label="WindowManager Shell Flicker Tests">
+ </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
new file mode 100644
index 000000000000..526fc502c0fb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright 2020 Google Inc. All Rights Reserved.
+ -->
+<configuration description="Runs WindowManager Shell Flicker Tests">
+ <option name="test-tag" value="FlickerTests" />
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <!-- keeps the screen on during tests -->
+ <option name="screen-always-on" value="on" />
+ <!-- prevents the phone from restarting -->
+ <option name="force-skip-system-props" value="true" />
+ <!-- set WM tracing verbose level to all -->
+ <option name="run-command" value="cmd window tracing level all" />
+ <!-- inform WM to log all transactions -->
+ <option name="run-command" value="cmd window tracing transaction" />
+ <!-- restart launcher to activate TAPL -->
+ <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner">
+ <!-- reboot the device to teardown any crashed tests -->
+ <option name="cleanup-action" value="REBOOT" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="WMShellFlickerTests.apk"/>
+ <option name="test-file-name" value="WMShellFlickerTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.wm.shell.flicker"/>
+ <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
+ <option name="shell-timeout" value="6600s" />
+ <option name="test-timeout" value="6000s" />
+ <option name="hidden-api-checks" value="false" />
+ </test>
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/storage/emulated/0/Android/data/com.android.wm.shell.flicker/files" />
+ <option name="collect-on-run-ended-only" value="true" />
+ <option name="clean-up" value="true" />
+ </metrics_collector>
+</configuration>
diff --git a/libs/WindowManager/Shell/tests/flicker/README.md b/libs/WindowManager/Shell/tests/flicker/README.md
new file mode 100644
index 000000000000..4502d498a65b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/README.md
@@ -0,0 +1,10 @@
+# WM Shell Flicker Test Package
+
+Please reference the following links
+
+- [Introduction to Flicker Test Library](http://cs/android/platform_testing/libraries/flicker/)
+- [Flicker Test in frameworks/base](http://cs/android/frameworks/base/tests/FlickerTests/)
+
+on what is Flicker Test and how to write a Flicker Test
+
+To run the Flicker Tests for WM Shell, simply run `atest WMShellFlickerTests`
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
new file mode 100644
index 000000000000..4ff2bfca3a4a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import com.android.server.wm.flicker.dsl.EventLogAssertion
+import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.dsl.WmAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
+
+@JvmOverloads
+fun WmAssertion.statusBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun WmAssertion.navBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.noUncoveredRegions(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ allStates: Boolean = true,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
+ val endingBounds = WindowUtils.getDisplayBounds(endRotation)
+ if (allStates) {
+ all("noUncoveredRegions", enabled, bugId) {
+ if (startingBounds == endingBounds) {
+ this.coversAtLeastRegion(startingBounds)
+ } else {
+ this.coversAtLeastRegion(startingBounds)
+ .then()
+ .coversAtLeastRegion(endingBounds)
+ }
+ }
+ } else {
+ start("noUncoveredRegions_StartingPos") {
+ this.coversAtLeastRegion(startingBounds)
+ }
+ end("noUncoveredRegions_EndingPos") {
+ this.coversAtLeastRegion(endingBounds)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerRotatesAndScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
+ val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
+
+ start("navBarLayerRotatesAndScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("navBarLayerRotatesAndScales_EndingPost", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, endingPos)
+ }
+
+ if (startingPos == endingPos) {
+ all("navBarLayerRotatesAndScales", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerRotatesScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
+ val endingPos = WindowUtils.getStatusBarPosition(endRotation)
+
+ start("statusBarLayerRotatesScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("statusBarLayerRotatesScales_EndingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, endingPos)
+ }
+}
+
+fun EventLogAssertion.focusChanges(
+ vararg windows: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusChanges(windows)
+ }
+}
+
+fun EventLogAssertion.focusDoesNotChange(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusDoesNotChange()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
new file mode 100644
index 000000000000..99f824bb8341
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.os.RemoteException
+import android.os.SystemClock
+import android.platform.helpers.IAppHelper
+import android.view.Surface
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.server.wm.flicker.Flicker
+
+/**
+ * Base class of all Flicker test that performs common functions for all flicker tests:
+ *
+ *
+ * - Caches transitions so that a transition is run once and the transition results are used by
+ * tests multiple times. This is needed for parameterized tests which call the BeforeClass methods
+ * multiple times.
+ * - Keeps track of all test artifacts and deletes ones which do not need to be reviewed.
+ * - Fails tests if results are not available for any test due to jank.
+ */
+abstract class FlickerTestBase {
+ val instrumentation by lazy {
+ InstrumentationRegistry.getInstrumentation()
+ }
+ val uiDevice by lazy {
+ UiDevice.getInstance(instrumentation)
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param rotation Initial screen rotation
+ *
+ * @return test tag with pattern <NAME>__<APP>__<ROTATION>
+ </ROTATION></APP></NAME> */
+ protected fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
+ return buildTestTag(
+ testName, app, rotation, rotation, app2 = null, extraInfo = "")
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ *
+ * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
+ </END_ROTATION></BEGIN_ROTATION></APP></NAME> */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int
+ ): String {
+ return buildTestTag(
+ testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
+ }
+
+ /**
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param app2 Second app being launched (if any)
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ * @param extraInfo Additional information to append to the tag
+ *
+ * @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
+ </EXTRA></NAME> */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int,
+ app2: IAppHelper?,
+ extraInfo: String
+ ): String {
+ var testTag = "${testName}__${app.launcherName}"
+ if (app2 != null) {
+ testTag += "-${app2.launcherName}"
+ }
+ testTag += "__${Surface.rotationToString(beginRotation)}"
+ if (endRotation != beginRotation) {
+ testTag += "-${Surface.rotationToString(endRotation)}"
+ }
+ if (extraInfo.isNotEmpty()) {
+ testTag += "__$extraInfo"
+ }
+ return testTag
+ }
+
+ protected fun Flicker.setRotation(rotation: Int) {
+ try {
+ when (rotation) {
+ Surface.ROTATION_270 -> device.setOrientationLeft()
+ Surface.ROTATION_90 -> device.setOrientationRight()
+ Surface.ROTATION_0 -> device.setOrientationNatural()
+ else -> device.setOrientationNatural()
+ }
+ // Wait for animation to complete
+ SystemClock.sleep(1000)
+ } catch (e: RemoteException) {
+ throw RuntimeException(e)
+ }
+ }
+
+ companion object {
+ const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
+ const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
+ const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
new file mode 100644
index 000000000000..90334ae91e9d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NonRotationTestBase.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.view.Surface
+import org.junit.runners.Parameterized
+
+abstract class NonRotationTestBase(
+ protected val rotationName: String,
+ protected val rotation: Int
+) : FlickerTestBase() {
+ companion object {
+ const val SCREENSHOT_LAYER = "RotationLayer"
+
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
new file mode 100644
index 000000000000..308a36efef87
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.helpers
+
+import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import com.android.server.wm.flicker.StandardAppHelper
+
+abstract class FlickerAppHelper(
+ instr: Instrumentation,
+ launcherName: String,
+ launcherStrategy: ILauncherStrategy
+) : StandardAppHelper(instr, sFlickerPackage, launcherName, launcherStrategy) {
+ companion object {
+ var sFlickerPackage = "com.android.wm.shell.flicker.testapp"
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
new file mode 100644
index 000000000000..539170202b8a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.helpers
+
+import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import android.support.test.launcherhelper.LauncherStrategyFactory
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.closePipWindow
+import org.junit.Assert
+
+class PipAppHelper(
+ instr: Instrumentation,
+ launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
+ .getInstance(instr)
+ .launcherStrategy
+) : FlickerAppHelper(instr, "PipApp", launcherStrategy) {
+ fun clickEnterPipButton(device: UiDevice) {
+ val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"))
+ Assert.assertNotNull("Pip button not found, this usually happens when the device " +
+ "was left in an unknown state (e.g. in split screen)", enterPipButton)
+ enterPipButton.click()
+ device.hasPipWindow()
+ }
+
+ fun closePipWindow(device: UiDevice) {
+ device.closePipWindow()
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
new file mode 100644
index 000000000000..4b04449bdbc2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip
+
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.LargeTest
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.expandPipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible
+import com.android.wm.shell.flicker.navBarLayerRotatesAndScales
+import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.noUncoveredRegions
+import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible
+import com.android.wm.shell.flicker.statusBarLayerRotatesScales
+import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest FlickerTests:PipToAppTest`
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 152738416)
+class EnterPipTest(
+ rotationName: String,
+ rotation: Int
+) : PipTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("enterPip", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ device.pressHome()
+ testApp.open()
+ this.setRotation(rotation)
+ }
+ }
+ teardown {
+ eachRun {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ }
+ }
+ transitions {
+ testApp.clickEnterPipButton(device)
+ device.expandPipWindow()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ all("pipWindowBecomesVisible") {
+ this.showsAppWindow(testApp.`package`)
+ .then()
+ .showsAppWindow(sPipWindowTitle)
+ }
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation, Surface.ROTATION_0)
+ statusBarLayerRotatesScales(rotation, Surface.ROTATION_0)
+
+ all("pipLayerBecomesVisible") {
+ this.showsLayer(testApp.launcherName)
+ .then()
+ .showsLayer(sPipWindowTitle)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
index f1ead3c8a441..3822d69a65f5 100644
--- a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/WindowManagerShellTest.java
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt
@@ -14,25 +14,18 @@
* limitations under the License.
*/
-package com.android.wm.shell;
+package com.android.wm.shell.flicker.pip
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
+import com.android.wm.shell.flicker.NonRotationTestBase
+import com.android.wm.shell.flicker.helpers.PipAppHelper
-import org.junit.Test;
-import org.junit.runner.RunWith;
+abstract class PipTestBase(
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ protected val testApp = PipAppHelper(instrumentation)
-/**
- * Tests for the shell.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class WindowManagerShellTest {
-
- WindowManagerShell mShell;
-
- @Test
- public void testNothing() {
- // Do nothing
+ companion object {
+ const val sPipWindowTitle = "PipMenuActivity"
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/Android.bp
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
new file mode 100644
index 000000000000..d12b49245277
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "WMShellFlickerTestApp",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ test_suites: ["device-tests"],
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
new file mode 100644
index 000000000000..95dc1d48eee8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wm.shell.flicker.testapp">
+
+ <uses-sdk android:minSdkVersion="29"
+ android:targetSdkVersion="29"/>
+ <application android:allowBackup="false"
+ android:supportsRtl="true">
+ <activity android:name=".PipActivity"
+ android:resizeableActivity="true"
+ android:supportsPictureInPicture="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
+ android:taskAffinity="com.android.wm.shell.flicker.testapp.PipActivity"
+ android:label="PipApp"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
new file mode 100644
index 000000000000..e1870d9c523d
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/holo_blue_bright">
+ <Button android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/enter_pip"
+ android:text="Enter PIP"/>
+</LinearLayout>
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java
new file mode 100644
index 000000000000..305281691e11
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.testapp;
+
+import android.app.Activity;
+import android.app.PictureInPictureParams;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Rational;
+import android.view.WindowManager;
+import android.widget.Button;
+
+public class PipActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ WindowManager.LayoutParams p = getWindow().getAttributes();
+ p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
+ .LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ getWindow().setAttributes(p);
+ setContentView(R.layout.activity_pip);
+ Button enterPip = (Button) findViewById(R.id.enter_pip);
+
+ PictureInPictureParams params = new PictureInPictureParams.Builder()
+ .setAspectRatio(new Rational(1, 1))
+ .setSourceRectHint(new Rect(0, 0, 100, 100))
+ .build();
+
+ enterPip.setOnClickListener((v) -> enterPictureInPictureMode(params));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 9868879cebb9..692e2fa88fc3 100644
--- a/libs/WindowManager/Shell/tests/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test {
- name: "WindowManagerShellTests",
+ name: "WMShellUnitTests",
srcs: ["**/*.java"],
diff --git a/libs/WindowManager/Shell/tests/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index a8f795ec8a8d..a8f795ec8a8d 100644
--- a/libs/WindowManager/Shell/tests/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
diff --git a/libs/WindowManager/Shell/tests/AndroidTest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidTest.xml
index 4dce4db360e4..21ed2c075dff 100644
--- a/libs/WindowManager/Shell/tests/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidTest.xml
@@ -17,12 +17,12 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="install-arg" value="-t" />
- <option name="test-file-name" value="WindowManagerShellTests.apk" />
+ <option name="test-file-name" value="WMShellUnitTests.apk" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="framework-base-presubmit" />
- <option name="test-tag" value="WindowManagerShellTests" />
+ <option name="test-tag" value="WMShellUnitTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.wm.shell.tests" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/libs/WindowManager/Shell/tests/res/values/config.xml b/libs/WindowManager/Shell/tests/unittest/res/values/config.xml
index c894eb0133b5..c894eb0133b5 100644
--- a/libs/WindowManager/Shell/tests/res/values/config.xml
+++ b/libs/WindowManager/Shell/tests/unittest/res/values/config.xml
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 10672c8d87ad..10672c8d87ad 100644
--- a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
diff --git a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
index 2b5b77e49e3a..2b5b77e49e3a 100644
--- a/libs/WindowManager/Shell/tests/src/com/android/wm/shell/common/DisplayLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 5770c6797404..5db672993df1 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -2060,7 +2060,7 @@ static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& sett
env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I")));
FrontendInnerFec innerFec =
static_cast<FrontendInnerFec>(
- env->GetLongField(settings, env->GetFieldID(clazz, "mFec", "J")));
+ env->GetLongField(settings, env->GetFieldID(clazz, "mInnerFec", "J")));
uint32_t symbolRate =
static_cast<uint32_t>(
env->GetIntField(settings, env->GetFieldID(clazz, "mSymbolRate", "I")));
@@ -2069,7 +2069,7 @@ static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& sett
env->GetIntField(settings, env->GetFieldID(clazz, "mOuterFec", "I")));
FrontendDvbcAnnex annex =
static_cast<FrontendDvbcAnnex>(
- env->GetByteField(settings, env->GetFieldID(clazz, "mAnnex", "B")));
+ env->GetIntField(settings, env->GetFieldID(clazz, "mAnnex", "I")));
FrontendDvbcSpectralInversion spectralInversion =
static_cast<FrontendDvbcSpectralInversion>(
env->GetIntField(
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index cfdb48bb4476..e0ebec6cbd01 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -45992,6 +45992,7 @@ package android.telephony {
method public void onDataConnectionStateChanged(int);
method public void onDataConnectionStateChanged(int, int);
method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
+ method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 0cfad1c769b1..d1264dfdd36d 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -9683,7 +9683,8 @@ package android.telephony {
public class PhoneStateListener {
method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
+ method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
method public void onRadioPowerStateChanged(int);
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 039f2c039ded..d3277ded6c5b 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -121,7 +121,6 @@
<string-array name="config_systemUIServiceComponentsExclude" translatable="false">
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
- <item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.statusbar.phone.StatusBar</item>
<item>com.android.systemui.keyboard.KeyboardUI</item>
<item>com.android.systemui.pip.PipUI</item>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 797a178c9a4b..3971e18bb968 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -34,7 +34,6 @@ import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
import com.android.systemui.shortcut.ShortcutKeyDispatcher;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
@@ -42,6 +41,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.theme.ThemeOverlayController;
import com.android.systemui.toast.ToastUI;
import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.wmshell.WMShell;
import dagger.Binds;
import dagger.Module;
@@ -59,12 +59,6 @@ public abstract class CarSystemUIBinder {
@ClassKey(AuthController.class)
public abstract SystemUI bindAuthController(AuthController sysui);
- /** Inject into Divider. */
- @Binds
- @IntoMap
- @ClassKey(Divider.class)
- public abstract SystemUI bindDivider(Divider sysui);
-
/** Inject Car Navigation Bar. */
@Binds
@IntoMap
@@ -192,4 +186,10 @@ public abstract class CarSystemUIBinder {
@IntoMap
@ClassKey(SideLoadedAppController.class)
public abstract SystemUI bindSideLoadedAppController(SideLoadedAppController sysui);
+
+ /** Inject into WMShell. */
+ @Binds
+ @IntoMap
+ @ClassKey(WMShell.class)
+ public abstract SystemUI bindWMShell(WMShell sysui);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 290700fad147..3eea5132da1d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -47,7 +47,6 @@ import com.android.systemui.qs.dagger.QSModule;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
-import com.android.systemui.stackdivider.DividerModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
@@ -75,7 +74,6 @@ import dagger.Provides;
@Module(
includes = {
- DividerModule.class,
QSModule.class,
CarWMShellModule.class
})
diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
index e493c97a9b46..c7354ed5b459 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
@@ -49,7 +49,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
private final Context mContext;
private SparseArray<PerDisplay> mPerDisplaySparseArray;
- private DisplaySystemBarsController(
+ public DisplaySystemBarsController(
Context context,
IWindowManager wmService,
DisplayController displayController,
@@ -167,33 +167,4 @@ public class DisplaySystemBarsController extends DisplayImeController {
}
}
}
-
- /** Builds {@link DisplaySystemBarsController} instance. */
- public static class Builder {
- private Context mContext;
- private IWindowManager mWmService;
- private DisplayController mDisplayController;
- private Handler mHandler;
- private TransactionPool mTransactionPool;
-
- public Builder(Context context, IWindowManager wmService,
- DisplayController displayController, Handler handler,
- TransactionPool transactionPool) {
- mContext = context;
- mWmService = wmService;
- mDisplayController = displayController;
- mHandler = handler;
- mTransactionPool = transactionPool;
- }
-
- /** Builds and initializes {@link DisplaySystemBarsController} instance. */
- public DisplaySystemBarsController build() {
- DisplaySystemBarsController displaySystemBarsController =
- new DisplaySystemBarsController(
- mContext, mWmService, mDisplayController, mHandler, mTransactionPool);
- // Separates startMonitorDisplays from constructor to prevent circular init issue.
- displaySystemBarsController.startMonitorDisplays();
- return displaySystemBarsController;
- }
- }
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
index 2324c3d59155..fd6685ffdb8f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java
@@ -40,8 +40,8 @@ public class CarWMShellModule {
DisplayImeController provideDisplayImeController(Context context,
IWindowManager wmService, DisplayController displayController,
@Main Handler mainHandler, TransactionPool transactionPool) {
- return new DisplaySystemBarsController.Builder(context, wmService, displayController,
- mainHandler, transactionPool).build();
+ return new DisplaySystemBarsController(context, wmService, displayController,
+ mainHandler, transactionPool);
}
/** TODO(b/150319024): PipMenuActivity will move to a Window */
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
index b65578dbe02c..391f75e35382 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
@@ -64,13 +64,13 @@ public class DisplaySystemBarsControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new DisplaySystemBarsController.Builder(
+ mController = new DisplaySystemBarsController(
mContext,
mIWindowManager,
mDisplayController,
mHandler,
mTransactionPool
- ).build();
+ );
}
@Test
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 596947dfb6dc..719fc9219450 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -31,7 +31,7 @@
<string name="template_all_pages" msgid="3322235982020148762">"همه <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
<string name="template_page_range" msgid="428638530038286328">"محدوده <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
<string name="pages_range_example" msgid="8558694453556945172">"‏‏‎مثلاً ۱—۵،‏۹،۷—۱۰"</string>
- <string name="print_preview" msgid="8010217796057763343">"پیش‌نمایش چاپ"</string>
+ <string name="print_preview" msgid="8010217796057763343">"پیش‌نمای چاپ"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"‏نصب نمایشگر PDF برای پیش‌نمایش"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"برنامه چاپ خراب شد"</string>
<string name="generating_print_job" msgid="3119608742651698916">"در حال ایجاد کار چاپ"</string>
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index 68b9553749e7..148fabbbaf2c 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -88,11 +88,6 @@ activity. It provides this cached data to RecentsActivity when it is started.
Registers all the callbacks/listeners required to show the Volume dialog when
it should be shown.
-### [com.android.systemui.stackdivider.Divider](/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java)
-
-Shows the drag handle for the divider between two apps when in split screen
-mode.
-
### [com.android.systemui.status.phone.StatusBar](/packages/SystemUI/src/com/android/systemui/status/phone/StatusBar.java)
This shows the UI for the status bar and the notification shade it contains.
@@ -153,6 +148,10 @@ Draws decorations about the screen in software (e.g. rounded corners, cutouts).
Biometric UI.
+### [com.android.systemui.wmshell.WMShell](/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java)
+
+Delegates SysUI events to WM Shell controllers.
+
---
* [Plugins](/packages/SystemUI/docs/plugins.md)
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 7b1479acc35e..b2d057b4bcd8 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -28,7 +28,6 @@
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.volume.VolumeUI</item>
- <item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.statusbar.tv.TvStatusBar</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
@@ -42,6 +41,7 @@
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.onehanded.OneHandedUI</item>
+ <item>com.android.systemui.wmshell.WMShell</item>
</string-array>
<!-- Show a separate icon for low and high volume on the volume dialog -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index ce1ca5ad1723..130bb4fc90b9 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -301,7 +301,6 @@
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
- <item>com.android.systemui.stackdivider.Divider</item>
<item>com.android.systemui.statusbar.phone.StatusBar</item>
<item>com.android.systemui.usb.StorageNotification</item>
<item>com.android.systemui.power.PowerUI</item>
@@ -323,6 +322,7 @@
<item>com.android.systemui.accessibility.SystemActions</item>
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.onehanded.OneHandedUI</item>
+ <item>com.android.systemui.wmshell.WMShell</item>
</string-array>
<!-- QS tile shape store width. negative implies fill configuration instead of stroke-->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 823c1ff2fdd0..bfa7532349aa 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -278,14 +278,10 @@
<string name="screenrecord_cancel_label">Cancel</string>
<!-- Label for notification action to share screen recording [CHAR LIMIT=35] -->
<string name="screenrecord_share_label">Share</string>
- <!-- Label for notification action to delete a screen recording file [CHAR LIMIT=35] -->
- <string name="screenrecord_delete_label">Delete</string>
<!-- A toast message shown after successfully canceling a screen recording [CHAR LIMIT=NONE] -->
<string name="screenrecord_cancel_success">Screen recording canceled</string>
<!-- Notification text shown after saving a screen recording to prompt the user to view it [CHAR LIMIT=100] -->
<string name="screenrecord_save_message">Screen recording saved, tap to view</string>
- <!-- A toast message shown after successfully deleting a screen recording [CHAR LIMIT=NONE] -->
- <string name="screenrecord_delete_description">Screen recording deleted</string>
<!-- A toast message shown when there is an error deleting a screen recording [CHAR LIMIT=NONE] -->
<string name="screenrecord_delete_error">Error deleting screen recording</string>
<!-- A toast message shown when the screen recording cannot be started due to insufficient permissions [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 748a9c9448c5..27809b50d746 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -65,7 +65,6 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -324,7 +323,6 @@ public class Dependency {
@Inject Lazy<DisplayImeController> mDisplayImeController;
@Inject Lazy<RecordingController> mRecordingController;
@Inject Lazy<ProtoTracer> mProtoTracer;
- @Inject Lazy<Divider> mDivider;
@Inject
public Dependency() {
@@ -521,7 +519,6 @@ public class Dependency {
mProviders.put(AutoHideController.class, mAutoHideController::get);
mProviders.put(RecordingController.class, mRecordingController::get);
- mProviders.put(Divider.class, mDivider::get);
Dependency.setInstance(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index eeb3b28357d7..a3339f6fc051 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -19,6 +19,7 @@ package com.android.systemui.appops;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.location.LocationManager;
import android.media.AudioManager;
import android.media.AudioRecordingConfiguration;
import android.os.Handler;
@@ -66,6 +67,13 @@ public class AppOpsControllerImpl implements AppOpsController,
private final AppOpsManager mAppOps;
private final AudioManager mAudioManager;
+ private final LocationManager mLocationManager;
+
+ // mLocationProviderPackages are cached and updated only occasionally
+ private static final long LOCATION_PROVIDER_UPDATE_FREQUENCY_MS = 30000;
+ private long mLastLocationProviderPackageUpdate;
+ private List<String> mLocationProviderPackages;
+
private H mBGHandler;
private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
private final SparseArray<Set<Callback>> mCallbacksByCode = new SparseArray<>();
@@ -83,8 +91,10 @@ public class AppOpsControllerImpl implements AppOpsController,
protected static final int[] OPS = new int[] {
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION,
AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_PHONE_CALL_CAMERA,
AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION
};
@@ -105,6 +115,7 @@ public class AppOpsControllerImpl implements AppOpsController,
mCallbacksByCode.put(OPS[i], new ArraySet<>());
}
mAudioManager = audioManager;
+ mLocationManager = context.getSystemService(LocationManager.class);
dumpManager.registerDumpable(TAG, this);
}
@@ -288,6 +299,26 @@ public class AppOpsControllerImpl implements AppOpsController,
return isUserVisible(item.getCode(), item.getUid(), item.getPackageName());
}
+ /**
+ * Checks if a package is the current location provider.
+ *
+ * <p>Data is cached to avoid too many calls into system server
+ *
+ * @param packageName The package that might be the location provider
+ *
+ * @return {@code true} iff the package is the location provider.
+ */
+ private boolean isLocationProvider(String packageName) {
+ long now = System.currentTimeMillis();
+
+ if (mLastLocationProviderPackageUpdate + LOCATION_PROVIDER_UPDATE_FREQUENCY_MS < now) {
+ mLastLocationProviderPackageUpdate = now;
+ mLocationProviderPackages = mLocationManager.getProviderPackages(
+ LocationManager.FUSED_PROVIDER);
+ }
+
+ return mLocationProviderPackages.contains(packageName);
+ }
/**
* Does the app-op, uid and package name, refer to an operation that should be shown to the
@@ -303,7 +334,13 @@ public class AppOpsControllerImpl implements AppOpsController,
// does not correspond to a platform permission
// which may be user sensitive, so for now always show it to the user.
if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW
- || appOpCode == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION) {
+ || appOpCode == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION
+ || appOpCode == AppOpsManager.OP_PHONE_CALL_CAMERA
+ || appOpCode == AppOpsManager.OP_PHONE_CALL_MICROPHONE) {
+ return true;
+ }
+
+ if (appOpCode == AppOpsManager.OP_CAMERA && isLocationProvider(packageName)) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 2fc5cba35616..e5e3a1d16c01 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -61,7 +61,7 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -193,7 +193,7 @@ public class DependencyProvider {
SysUiState sysUiFlagsContainer,
BroadcastDispatcher broadcastDispatcher,
CommandQueue commandQueue,
- Divider divider,
+ Optional<SplitScreenController> splitScreenControllerOptional,
Optional<Recents> recentsOptional,
Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
@@ -215,7 +215,7 @@ public class DependencyProvider {
sysUiFlagsContainer,
broadcastDispatcher,
commandQueue,
- divider,
+ splitScreenControllerOptional,
recentsOptional,
statusBarLazy,
shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 0aebb7eaf823..9dfd9f8fd9bf 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -34,7 +34,6 @@ import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
import com.android.systemui.shortcut.ShortcutKeyDispatcher;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -43,6 +42,7 @@ import com.android.systemui.theme.ThemeOverlayController;
import com.android.systemui.toast.ToastUI;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
+import com.android.systemui.wmshell.WMShell;
import dagger.Binds;
import dagger.Module;
@@ -61,12 +61,6 @@ public abstract class SystemUIBinder {
@ClassKey(AuthController.class)
public abstract SystemUI bindAuthController(AuthController service);
- /** Inject into Divider. */
- @Binds
- @IntoMap
- @ClassKey(Divider.class)
- public abstract SystemUI bindDivider(Divider sysui);
-
/** Inject into GarbageMonitor.Service. */
@Binds
@IntoMap
@@ -187,4 +181,10 @@ public abstract class SystemUIBinder {
@IntoMap
@ClassKey(WindowMagnification.class)
public abstract SystemUI bindWindowMagnification(WindowMagnification sysui);
+
+ /** Inject into WMShell. */
+ @Binds
+ @IntoMap
+ @ClassKey(WMShell.class)
+ public abstract SystemUI bindWMShell(WMShell sysui);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 3b225d5313c1..a021114c138b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -41,7 +41,6 @@ import com.android.systemui.qs.dagger.QSModule;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
-import com.android.systemui.stackdivider.DividerModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
@@ -75,7 +74,6 @@ import dagger.Provides;
* overridden by the System UI implementation.
*/
@Module(includes = {
- DividerModule.class,
QSModule.class,
WMShellModule.class
})
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index d0e45432c13b..e985e3d7ef90 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -27,7 +27,6 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.Recents;
import com.android.systemui.screenshot.dagger.ScreenshotModule;
import com.android.systemui.settings.dagger.SettingsModule;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
@@ -95,9 +94,6 @@ public abstract class SystemUIModule {
abstract CommandQueue optionalCommandQueue();
@BindsOptionalOf
- abstract Divider optionalDivider();
-
- @BindsOptionalOf
abstract HeadsUpManager optionalHeadsUpManager();
@BindsOptionalOf
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
index fdbff98ea831..6bd5274fa331 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
@@ -54,32 +54,35 @@ class MediaTimeoutListener @Inject constructor(
if (mediaListeners.containsKey(key)) {
return
}
- // Having an old key means that we're migrating from/to resumption. We should invalidate
- // the old listener and create a new one.
+ // Having an old key means that we're migrating from/to resumption. We should update
+ // the old listener to make sure that events will be dispatched to the new location.
val migrating = oldKey != null && key != oldKey
var wasPlaying = false
if (migrating) {
- if (mediaListeners.containsKey(oldKey)) {
- val oldListener = mediaListeners.remove(oldKey)
- wasPlaying = oldListener?.playing ?: false
- oldListener?.destroy()
+ val reusedListener = mediaListeners.remove(oldKey)
+ if (reusedListener != null) {
+ wasPlaying = reusedListener.playing ?: false
if (DEBUG) Log.d(TAG, "migrating key $oldKey to $key, for resumption")
+ reusedListener.mediaData = data
+ reusedListener.key = key
+ mediaListeners[key] = reusedListener
+ if (wasPlaying != reusedListener.playing) {
+ // If a player becomes active because of a migration, we'll need to broadcast
+ // its state. Doing it now would lead to reentrant callbacks, so let's wait
+ // until we're done.
+ mainExecutor.execute {
+ if (mediaListeners[key]?.playing == true) {
+ if (DEBUG) Log.d(TAG, "deliver delayed playback state for $key")
+ timeoutCallback.invoke(key, false /* timedOut */)
+ }
+ }
+ }
+ return
} else {
Log.w(TAG, "Old key $oldKey for player $key doesn't exist. Continuing...")
}
}
mediaListeners[key] = PlaybackStateListener(key, data)
-
- // If a player becomes active because of a migration, we'll need to broadcast its state.
- // Doing it now would lead to reentrant callbacks, so let's wait until we're done.
- if (migrating && mediaListeners[key]?.playing != wasPlaying) {
- mainExecutor.execute {
- if (mediaListeners[key]?.playing == true) {
- if (DEBUG) Log.d(TAG, "deliver delayed playback state for $key")
- timeoutCallback.invoke(key, false /* timedOut */)
- }
- }
- }
}
override fun onMediaDataRemoved(key: String) {
@@ -91,26 +94,34 @@ class MediaTimeoutListener @Inject constructor(
}
private inner class PlaybackStateListener(
- private val key: String,
+ var key: String,
data: MediaData
) : MediaController.Callback() {
var timedOut = false
var playing: Boolean? = null
+ var mediaData: MediaData = data
+ set(value) {
+ mediaController?.unregisterCallback(this)
+ field = value
+ mediaController = if (field.token != null) {
+ mediaControllerFactory.create(field.token)
+ } else {
+ null
+ }
+ mediaController?.registerCallback(this)
+ // Let's register the cancellations, but not dispatch events now.
+ // Timeouts didn't happen yet and reentrant events are troublesome.
+ processState(mediaController?.playbackState, dispatchEvents = false)
+ }
+
// Resume controls may have null token
- private val mediaController = if (data.token != null) {
- mediaControllerFactory.create(data.token)
- } else {
- null
- }
+ private var mediaController: MediaController? = null
private var cancellation: Runnable? = null
init {
- mediaController?.registerCallback(this)
- // Let's register the cancellations, but not dispatch events now.
- // Timeouts didn't happen yet and reentrant events are troublesome.
- processState(mediaController?.playbackState, dispatchEvents = false)
+ mediaData = data
}
fun destroy() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 6c8a23ba96d1..94a2bd915016 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -111,7 +111,6 @@ import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.buttons.KeyButtonView;
@@ -123,7 +122,7 @@ import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -180,7 +179,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
private final NavigationModeController mNavigationModeController;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
- private final Divider mDivider;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private final Optional<Recents> mRecentsOptional;
private final SystemActions mSystemActions;
private final Handler mHandler;
@@ -377,22 +376,22 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
- @Override
- public void onPropertiesChanged(DeviceConfig.Properties properties) {
- if (properties.getKeyset().contains(NAV_BAR_HANDLE_FORCE_OPAQUE)) {
- mForceNavBarHandleOpaque = properties.getBoolean(
- NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ true);
- }
- }
- };
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ if (properties.getKeyset().contains(NAV_BAR_HANDLE_FORCE_OPAQUE)) {
+ mForceNavBarHandleOpaque = properties.getBoolean(
+ NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ true);
+ }
+ }
+ };
private final DeviceProvisionedController.DeviceProvisionedListener mUserSetupListener =
new DeviceProvisionedController.DeviceProvisionedListener() {
- @Override
- public void onUserSetupChanged() {
- mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
- }
- };
+ @Override
+ public void onUserSetupChanged() {
+ mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup();
+ }
+ };
public NavigationBar(Context context,
WindowManager windowManager,
@@ -406,7 +405,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
StatusBarStateController statusBarStateController,
SysUiState sysUiFlagsContainer,
BroadcastDispatcher broadcastDispatcher,
- CommandQueue commandQueue, Divider divider,
+ CommandQueue commandQueue,
+ Optional<SplitScreenController> splitScreenControllerOptional,
Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
NotificationRemoteInputManager notificationRemoteInputManager,
@@ -430,7 +430,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
mNavBarMode = navigationModeController.addListener(this);
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
- mDivider = divider;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mRecentsOptional = recentsOptional;
mSystemActions = systemActions;
mHandler = mainHandler;
@@ -528,6 +528,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
}
mNavigationBarView.setNavigationIconHints(mNavigationIconHints);
mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
+ mSplitScreenControllerOptional.ifPresent(mNavigationBarView::registerDockedListener);
prepareNavigationBarView();
checkNavBarModes();
@@ -559,7 +560,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
setDisabled2Flags(mDisabledFlags2);
if (mIsOnDefaultDisplay) {
mAssistHandlerViewController =
- new AssistHandleViewController(mHandler, mNavigationBarView);
+ new AssistHandleViewController(mHandler, mNavigationBarView);
getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
}
@@ -690,7 +691,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
return;
}
- if (mStartingQuickSwitchRotation == -1 || mDivider.isDividerVisible()) {
+ if (mStartingQuickSwitchRotation == -1 || mSplitScreenControllerOptional
+ .map(SplitScreenController::isDividerVisible).orElse(false)) {
// Hide the secondary home handle if we are in multiwindow since apps in multiwindow
// aren't allowed to set the display orientation
resetSecondaryHandle();
@@ -1121,7 +1123,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
}
mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
mUiEventLogger.log(NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS);
- Bundle args = new Bundle();
+ Bundle args = new Bundle();
args.putInt(
AssistManager.INVOCATION_TYPE_KEY, AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS);
mAssistManagerLazy.get().startAssist(args);
@@ -1246,10 +1248,12 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
private boolean onLongPressRecents() {
if (mRecentsOptional.isPresent() || !ActivityTaskManager.supportsMultiWindow(mContext)
- || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()
|| ActivityManager.isLowRamDeviceStatic()
// If we are connected to the overview service, then disable the recents button
- || mOverviewProxyService.getProxy() != null) {
+ || mOverviewProxyService.getProxy() != null
+ || !mSplitScreenControllerOptional.map(splitScreen ->
+ splitScreen.getDividerView().getSnapAlgorithm().isSplitScreenFeasible())
+ .orElse(false)) {
return false;
}
@@ -1311,6 +1315,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
/**
* Returns the system UI flags corresponding the the current accessibility button state
+ *
* @param outFeedbackEnabled if non-null, sets it to true if accessibility feedback is enabled.
*/
public int getA11yButtonState(@Nullable boolean[] outFeedbackEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index fd157c632c7c..23ef71a6541e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -55,7 +55,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -96,7 +96,7 @@ public class NavigationBarController implements Callbacks,
private final SysUiState mSysUiFlagsContainer;
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
- private final Divider mDivider;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private final Optional<Recents> mRecentsOptional;
private final Lazy<StatusBar> mStatusBarLazy;
private final ShadeController mShadeController;
@@ -130,7 +130,7 @@ public class NavigationBarController implements Callbacks,
SysUiState sysUiFlagsContainer,
BroadcastDispatcher broadcastDispatcher,
CommandQueue commandQueue,
- Divider divider,
+ Optional<SplitScreenController> splitScreenControllerOptional,
Optional<Recents> recentsOptional,
Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
@@ -152,7 +152,7 @@ public class NavigationBarController implements Callbacks,
mSysUiFlagsContainer = sysUiFlagsContainer;
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
- mDivider = divider;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mRecentsOptional = recentsOptional;
mStatusBarLazy = statusBarLazy;
mShadeController = shadeController;
@@ -278,7 +278,7 @@ public class NavigationBarController implements Callbacks,
mSysUiFlagsContainer,
mBroadcastDispatcher,
mCommandQueue,
- mDivider,
+ mSplitScreenControllerOptional,
mRecentsOptional,
mStatusBarLazy,
mShadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index a3351838ecf2..7e3aa1050d10 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -87,14 +87,13 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -329,8 +328,9 @@ public class NavigationBarView extends FrameLayout implements
mContextualButtonGroup.addButton(accessibilityButton);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
mFloatingRotationButton = new FloatingRotationButton(context);
+ // TODO(165014649): Temporarily disable onboarding
+ // mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
mRotationButtonController = new RotationButtonController(mLightContext,
mLightIconColor, mDarkIconColor,
isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
@@ -886,7 +886,9 @@ public class NavigationBarView extends FrameLayout implements
mNavBarMode = mode;
mBarTransitions.onNavigationModeChanged(mNavBarMode);
mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
- mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
+ if (mRecentsOnboarding != null) {
+ mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
+ }
if (isGesturalMode(mNavBarMode)) {
mRegionSamplingHelper.start(mSamplingBounds);
@@ -902,7 +904,9 @@ public class NavigationBarView extends FrameLayout implements
}
void hideRecentsOnboarding() {
- mRecentsOnboarding.hide(true);
+ if (mRecentsOnboarding != null) {
+ mRecentsOnboarding.hide(true);
+ }
}
@Override
@@ -912,9 +916,6 @@ public class NavigationBarView extends FrameLayout implements
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
-
- Divider divider = Dependency.get(Divider.class);
- divider.registerInSplitScreenListener(mDockedListener);
updateOrientationViews();
reloadNavIcons();
}
@@ -953,7 +954,9 @@ public class NavigationBarView extends FrameLayout implements
super.onLayout(changed, left, top, right, bottom);
notifyActiveTouchRegions();
- mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
+ if (mRecentsOnboarding != null) {
+ mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
+ }
}
/**
@@ -1115,7 +1118,9 @@ public class NavigationBarView extends FrameLayout implements
boolean uiCarModeChanged = updateCarMode();
updateIcons(mTmpLastConfiguration);
updateRecentsIcon();
- mRecentsOnboarding.onConfigurationChanged(mConfiguration);
+ if (mRecentsOnboarding != null) {
+ mRecentsOnboarding.onConfigurationChanged(mConfiguration);
+ }
if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
|| mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
// If car mode or density changes, we need to reset the icons.
@@ -1205,10 +1210,12 @@ public class NavigationBarView extends FrameLayout implements
}
private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
- if (connectedToOverviewProxy) {
- mRecentsOnboarding.onConnectedToLauncher();
- } else {
- mRecentsOnboarding.onDisconnectedFromLauncher();
+ if (mRecentsOnboarding != null) {
+ if (connectedToOverviewProxy) {
+ mRecentsOnboarding.onConnectedToLauncher();
+ } else {
+ mRecentsOnboarding.onDisconnectedFromLauncher();
+ }
}
}
@@ -1254,7 +1261,9 @@ public class NavigationBarView extends FrameLayout implements
mNavigationInflaterView.dump(pw);
}
mContextualButtonGroup.dump(pw);
- mRecentsOnboarding.dump(pw);
+ if (mRecentsOnboarding != null) {
+ mRecentsOnboarding.dump(pw);
+ }
mRegionSamplingHelper.dump(pw);
mEdgeBackGestureHandler.dump(pw);
}
@@ -1287,6 +1296,10 @@ public class NavigationBarView extends FrameLayout implements
return super.onApplyWindowInsets(insets);
}
+ void registerDockedListener(SplitScreenController splitScreenController) {
+ splitScreenController.registerInSplitScreenListener(mDockedListener);
+ }
+
private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
pw.print(" " + caption + ": ");
if (button == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 1ea58887ddc7..3adf7ffb347b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -58,7 +58,7 @@ import android.window.WindowOrganizer;
import com.android.internal.os.SomeArgs;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.pip.phone.PipUpdateThread;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
@@ -69,6 +69,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.function.Consumer;
/**
@@ -104,7 +105,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
private final int mEnterExitAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
- private final Divider mSplitDivider;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
// These callbacks are called on the update thread
@@ -207,7 +208,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
- @Nullable Divider divider,
+ Optional<SplitScreenController> splitScreenControllerOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
@@ -220,7 +221,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
mPipAnimationController = new PipAnimationController(mSurfaceTransactionHelper);
mPipUiEventLoggerLogger = pipUiEventLogger;
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
- mSplitDivider = divider;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mTaskOrganizer = shellTaskOrganizer;
mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED);
displayController.addDisplayWindowListener(this);
@@ -336,9 +337,11 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
wct.setWindowingMode(mToken, getOutPipWindowingMode());
// Simply reset the activity mode set prior to the animation running.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
- if (mSplitDivider != null && direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
- wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
- }
+ mSplitScreenControllerOptional.ifPresent(splitScreen -> {
+ if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
+ wct.reparent(mToken, splitScreen.getSecondaryRoot(), true /* onTop */);
+ }
+ });
}
/**
@@ -934,20 +937,27 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize
}
/**
- * Sync with {@link #mSplitDivider} on destination bounds if PiP is going to split screen.
+ * Sync with {@link SplitScreenController} on destination bounds if PiP is going to split
+ * screen.
*
* @param destinationBoundsOut contain the updated destination bounds if applicable
* @return {@code true} if destinationBounds is altered for split screen
*/
private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut) {
- if (mSplitDivider == null || !mSplitDivider.isDividerVisible()) {
- // bail early if system is not in split screen mode
+ if (!mSplitScreenControllerOptional.isPresent()) {
return false;
}
+
+ SplitScreenController splitScreenController = mSplitScreenControllerOptional.get();
+ if (!splitScreenController.isDividerVisible()) {
+ // fail early if system is not in split screen mode
+ return false;
+ }
+
// PiP window will go to split-secondary mode instead of fullscreen, populates the
// split screen bounds here.
- destinationBoundsOut.set(
- mSplitDivider.getView().getNonMinimizedSplitScreenSecondaryBounds());
+ destinationBoundsOut.set(splitScreenController.getDividerView()
+ .getNonMinimizedSplitScreenSecondaryBounds());
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 27cc3d458062..6aec14449d70 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -56,7 +56,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
@@ -65,6 +65,7 @@ import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import java.io.PrintWriter;
+import java.util.Optional;
import javax.inject.Inject;
@@ -270,7 +271,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
ConfigurationController configController,
DeviceConfigProxy deviceConfig,
DisplayController displayController,
- Divider divider,
+ Optional<SplitScreenController> splitScreenControllerOptional,
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
PipUiEventLogger pipUiEventLogger,
@@ -290,8 +291,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mPipBoundsHandler = new PipBoundsHandler(mContext);
mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController);
mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler,
- mPipSurfaceTransactionHelper, divider, mDisplayController, pipUiEventLogger,
- shellTaskOrganizer);
+ mPipSurfaceTransactionHelper, splitScreenControllerOptional, mDisplayController,
+ pipUiEventLogger, shellTaskOrganizer);
mPipTaskOrganizer.registerPipTransitionCallback(this);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 0531ca195f95..5d8e6306ba69 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -60,13 +60,14 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import javax.inject.Inject;
@@ -237,7 +238,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
public PipManager(Context context, BroadcastDispatcher broadcastDispatcher,
ConfigurationController configController,
DisplayController displayController,
- Divider divider,
+ Optional<SplitScreenController> splitScreenControllerOptional,
@NonNull PipUiEventLogger pipUiEventLogger,
ShellTaskOrganizer shellTaskOrganizer) {
if (mInitialized) {
@@ -257,8 +258,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
.getInteger(R.integer.config_pipResizeAnimationDuration);
mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context, configController);
mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler,
- mPipSurfaceTransactionHelper, divider, displayController, pipUiEventLogger,
- shellTaskOrganizer);
+ mPipSurfaceTransactionHelper, splitScreenControllerOptional, displayController,
+ pipUiEventLogger, shellTaskOrganizer);
mPipTaskOrganizer.registerPipTransitionCallback(this);
mActivityTaskManager = ActivityTaskManager.getService();
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 255ba1b61db1..e57478eb0988 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -57,7 +57,8 @@ class PrivacyItemController @Inject constructor(
@VisibleForTesting
internal companion object {
val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA,
- AppOpsManager.OP_RECORD_AUDIO)
+ AppOpsManager.OP_PHONE_CALL_CAMERA, AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_PHONE_CALL_MICROPHONE)
val OPS_LOCATION = intArrayOf(
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION)
@@ -248,9 +249,11 @@ class PrivacyItemController @Inject constructor(
private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
val type: PrivacyType = when (appOpItem.code) {
+ AppOpsManager.OP_PHONE_CALL_CAMERA,
AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
- AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
+ AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
+ AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 0347867b61fc..3decb9688828 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -38,7 +38,7 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.phone.StatusBar;
import java.util.Optional;
@@ -56,7 +56,7 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
private final static String TAG = "OverviewProxyRecentsImpl";
@Nullable
private final Lazy<StatusBar> mStatusBarLazy;
- private final Optional<Divider> mDividerOptional;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private Context mContext;
private Handler mHandler;
@@ -66,9 +66,9 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyRecentsImpl(Optional<Lazy<StatusBar>> statusBarLazy,
- Optional<Divider> dividerOptional) {
+ Optional<SplitScreenController> splitScreenControllerOptional) {
mStatusBarLazy = statusBarLazy.orElse(null);
- mDividerOptional = dividerOptional;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
}
@Override
@@ -163,12 +163,12 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
if (runningTask.supportsSplitScreenMultiWindow) {
if (ActivityManagerWrapper.getInstance().setTaskWindowingModeSplitScreenPrimary(
runningTask.id, stackCreateMode, initialBounds)) {
- mDividerOptional.ifPresent(Divider::onDockedTopTask);
-
- // The overview service is handling split screen, so just skip the wait for the
- // first draw and notify the divider to start animating now
- mDividerOptional.ifPresent(Divider::onRecentsDrawn);
-
+ mSplitScreenControllerOptional.ifPresent(splitScreen -> {
+ splitScreen.onDockedTopTask();
+ // The overview service is handling split screen, so just skip the wait
+ // for the first draw and notify the divider to start animating now
+ splitScreen.onRecentsDrawn();
+ });
return true;
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index e931a6bf179a..304dc93c5dee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -86,7 +86,7 @@ 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.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -123,7 +123,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
private final Context mContext;
private final PipUI mPipUI;
private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
- private final Optional<Divider> mDividerOptional;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private SysUiState mSysUiState;
private final Handler mHandler;
private final Lazy<NavigationBarController> mNavBarControllerLazy;
@@ -232,7 +232,9 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- mDividerOptional.ifPresent(Divider::onDockedFirstAnimationFrame);
+ mSplitScreenControllerOptional.ifPresent(splitScreen -> {
+ splitScreen.onDockedFirstAnimationFrame();
+ });
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -262,8 +264,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
long token = Binder.clearCallingIdentity();
try {
- return mDividerOptional.map(
- divider -> divider.getView().getNonMinimizedSplitScreenSecondaryBounds())
+ return mSplitScreenControllerOptional.map(splitScreen ->
+ splitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds())
.orElse(null);
} finally {
Binder.restoreCallingIdentity(token);
@@ -399,10 +401,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
@Override
public void setSplitScreenMinimized(boolean minimized) {
- Divider divider = mDividerOptional.get();
- if (divider != null) {
- divider.setMinimized(minimized);
- }
+ mSplitScreenControllerOptional.ifPresent(
+ splitScreen -> splitScreen.setMinimized(minimized));
}
@Override
@@ -602,7 +602,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
public OverviewProxyService(Context context, CommandQueue commandQueue,
Lazy<NavigationBarController> navBarControllerLazy, NavigationModeController navModeController,
NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
- PipUI pipUI, Optional<Divider> dividerOptional,
+ PipUI pipUI, Optional<SplitScreenController> splitScreenControllerOptional,
Optional<Lazy<StatusBar>> statusBarOptionalLazy, OneHandedUI oneHandedUI,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
@@ -613,7 +613,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
mNavBarControllerLazy = navBarControllerLazy;
mStatusBarWinController = statusBarWinController;
mConnectionBackoffAttempts = 0;
- mDividerOptional = dividerOptional;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
@@ -755,10 +755,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
startConnectionToCurrentUser();
// Clean up the minimized state if launcher dies
- Divider divider = mDividerOptional.get();
- if (divider != null) {
- divider.setMinimized(false);
- }
+ mSplitScreenControllerOptional.ifPresent(
+ splitScreen -> splitScreen.setMinimized(false));
}
public void startConnectionToCurrentUser() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 1d29ac629cd8..a641730ac64e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -35,7 +35,6 @@ public interface RecentsImplementation {
default void showRecentApps(boolean triggeredFromAltTab) {}
default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {}
default void toggleRecentApps() {}
- default void growRecents() {}
default boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
int metricsDockAction) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 469c4a7b4c57..8ec3db59117d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -21,7 +21,6 @@ import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -70,7 +69,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
private static final String ACTION_STOP_NOTIF =
"com.android.systemui.screenrecord.STOP_FROM_NOTIF";
private static final String ACTION_SHARE = "com.android.systemui.screenrecord.SHARE";
- private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private final RecordingController mController;
private final KeyguardDismissUtil mKeyguardDismissUtil;
@@ -184,25 +182,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
// Close quick shade
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
break;
- case ACTION_DELETE:
- mKeyguardDismissUtil.executeWhenUnlocked(() -> {
- // Close quick shade
- sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- ContentResolver resolver = getContentResolver();
- Uri uri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
- resolver.delete(uri, null, null);
-
- Toast.makeText(
- this,
- R.string.screenrecord_delete_description,
- Toast.LENGTH_LONG).show();
- Log.d(TAG, "Deleted recording " + uri);
-
- // Remove notification
- mNotificationManager.cancelAsUser(null, NOTIFICATION_VIEW_ID, currentUser);
- return false;
- }, false);
- break;
}
return Service.START_STICKY;
}
@@ -312,16 +291,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
.build();
- Notification.Action deleteAction = new Notification.Action.Builder(
- Icon.createWithResource(this, R.drawable.ic_screenrecord),
- getResources().getString(R.string.screenrecord_delete_label),
- PendingIntent.getService(
- this,
- REQUEST_CODE,
- getDeleteIntent(this, uri.toString()),
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
- .build();
-
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
getResources().getString(R.string.screenrecord_name));
@@ -335,7 +304,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
viewIntent,
PendingIntent.FLAG_IMMUTABLE))
.addAction(shareAction)
- .addAction(deleteAction)
.setAutoCancel(true)
.addExtras(extras);
@@ -414,11 +382,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
.putExtra(EXTRA_PATH, path);
}
- private static Intent getDeleteIntent(Context context, String path) {
- return new Intent(context, RecordingService.class).setAction(ACTION_DELETE)
- .putExtra(EXTRA_PATH, path);
- }
-
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
Log.d(TAG, "Media recorder info: " + what);
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index ee3303bf33ef..e2118a798a43 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -30,8 +30,10 @@ import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.DividerView;
+import com.android.systemui.stackdivider.SplitScreenController;
+
+import java.util.Optional;
import javax.inject.Inject;
@@ -43,7 +45,7 @@ public class ShortcutKeyDispatcher extends SystemUI
implements ShortcutKeyServiceProxy.Callbacks {
private static final String TAG = "ShortcutKeyDispatcher";
- private final Divider mDivider;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private final Recents mRecents;
private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
@@ -58,14 +60,16 @@ public class ShortcutKeyDispatcher extends SystemUI
protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
@Inject
- public ShortcutKeyDispatcher(Context context, Divider divider, Recents recents) {
+ public ShortcutKeyDispatcher(Context context,
+ Optional<SplitScreenController> splitScreenControllerOptional, Recents recents) {
super(context);
- mDivider = divider;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mRecents = recents;
}
/**
* Registers a shortcut key to window manager.
+ *
* @param shortcutCode packed representation of shortcut key code and meta information
*/
public void registerShortcutKey(long shortcutCode) {
@@ -92,24 +96,28 @@ public class ShortcutKeyDispatcher extends SystemUI
}
private void handleDockKey(long shortcutCode) {
- if (mDivider == null || !mDivider.isDividerVisible()) {
- // Split the screen
- mRecents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
- ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
- : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
- } else {
- // If there is already a docked window, we respond by resizing the docking pane.
- DividerView dividerView = mDivider.getView();
- DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
- int dividerPosition = dividerView.getCurrentPosition();
- DividerSnapAlgorithm.SnapTarget currentTarget =
- snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
- DividerSnapAlgorithm.SnapTarget target = (shortcutCode == SC_DOCK_LEFT)
- ? snapAlgorithm.getPreviousTarget(currentTarget)
- : snapAlgorithm.getNextTarget(currentTarget);
- dividerView.startDragging(true /* animate */, false /* touching */);
- dividerView.stopDragging(target.position, 0f, false /* avoidDismissStart */,
- true /* logMetrics */);
+ if (mSplitScreenControllerOptional.isPresent()) {
+ SplitScreenController splitScreenController = mSplitScreenControllerOptional.get();
+ if (splitScreenController.isDividerVisible()) {
+ // If there is already a docked window, we respond by resizing the docking pane.
+ DividerView dividerView = splitScreenController.getDividerView();
+ DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
+ int dividerPosition = dividerView.getCurrentPosition();
+ DividerSnapAlgorithm.SnapTarget currentTarget =
+ snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
+ DividerSnapAlgorithm.SnapTarget target = (shortcutCode == SC_DOCK_LEFT)
+ ? snapAlgorithm.getPreviousTarget(currentTarget)
+ : snapAlgorithm.getNextTarget(currentTarget);
+ dividerView.startDragging(true /* animate */, false /* touching */);
+ dividerView.stopDragging(target.position, 0f, false /* avoidDismissStart */,
+ true /* logMetrics */);
+ return;
+ }
}
+
+ // Split the screen
+ mRecents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
+ ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+ : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
deleted file mode 100644
index e9c880ebbcc9..000000000000
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2015 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.stackdivider;
-
-import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.window.WindowContainerToken;
-
-import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.function.Consumer;
-
-/**
- * Controls the docked stack divider.
- */
-@SysUISingleton
-public class Divider extends SystemUI {
- private final KeyguardStateController mKeyguardStateController;
- private final DividerController mDividerController;
-
- Divider(Context context, DividerController dividerController,
- KeyguardStateController keyguardStateController) {
- super(context);
- mDividerController = dividerController;
- mKeyguardStateController = keyguardStateController;
- }
-
- @Override
- public void start() {
- mDividerController.start();
- // Hide the divider when keyguard is showing. Even though keyguard/statusbar is above
- // everything, it is actually transparent except for notifications, so we still need to
- // hide any surfaces that are below it.
- // TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
- mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
- @Override
- public void onKeyguardShowingChanged() {
- mDividerController.onKeyguardShowingChanged(mKeyguardStateController.isShowing());
- }
- });
- // Don't initialize the divider or anything until we get the default display.
-
- ActivityManagerWrapper.getInstance().registerTaskStackListener(
- new TaskStackChangeListener() {
- @Override
- public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
- boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
- != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || !mDividerController.isSplitScreenSupported()) {
- return;
- }
-
- if (mDividerController.isMinimized()) {
- onUndockingTask();
- }
- }
-
- @Override
- public void onActivityForcedResizable(String packageName, int taskId,
- int reason) {
- mDividerController.onActivityForcedResizable(packageName, taskId, reason);
- }
-
- @Override
- public void onActivityDismissingDockedStack() {
- mDividerController.onActivityDismissingSplitScreen();
- }
-
- @Override
- public void onActivityLaunchOnSecondaryDisplayFailed() {
- mDividerController.onActivityLaunchOnSecondaryDisplayFailed();
- }
- }
- );
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mDividerController.dump(pw);
- }
-
- /** Switch to minimized state if appropriate. */
- public void setMinimized(final boolean minimized) {
- mDividerController.setMinimized(minimized);
- }
-
- public boolean isMinimized() {
- return mDividerController.isMinimized();
- }
-
- public boolean isHomeStackResizable() {
- return mDividerController.isHomeStackResizable();
- }
-
- /** Callback for undocking task. */
- public void onUndockingTask() {
- mDividerController.onUndockingTask();
- }
-
- public void onRecentsDrawn() {
- mDividerController.onRecentsDrawn();
- }
-
- public void onDockedFirstAnimationFrame() {
- mDividerController.onDockedFirstAnimationFrame();
- }
-
- public void onDockedTopTask() {
- mDividerController.onDockedTopTask();
- }
-
- public void onAppTransitionFinished() {
- mDividerController.onAppTransitionFinished();
- }
-
- public DividerView getView() {
- return mDividerController.getDividerView();
- }
-
- /** @return the container token for the secondary split root task. */
- public WindowContainerToken getSecondaryRoot() {
- return mDividerController.getSecondaryRoot();
- }
-
- /** Register a listener that gets called whenever the existence of the divider changes */
- public void registerInSplitScreenListener(Consumer<Boolean> listener) {
- mDividerController.registerInSplitScreenListener(listener);
- }
-
- /** {@code true} if this is visible */
- public boolean isDividerVisible() {
- return mDividerController.isDividerVisible();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
index c915f071297f..64ee7ed5e0e0 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
@@ -38,7 +38,7 @@ import com.android.wm.shell.common.TransactionPool;
class DividerImeController implements DisplayImeController.ImePositionProcessor {
private static final String TAG = "DividerImeController";
- private static final boolean DEBUG = DividerController.DEBUG;
+ private static final boolean DEBUG = SplitScreenController.DEBUG;
private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
@@ -100,15 +100,15 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
}
private DividerView getView() {
- return mSplits.mDividerController.getDividerView();
+ return mSplits.mSplitScreenController.getDividerView();
}
private SplitDisplayLayout getLayout() {
- return mSplits.mDividerController.getSplitLayout();
+ return mSplits.mSplitScreenController.getSplitLayout();
}
private boolean isDividerVisible() {
- return mSplits.mDividerController.isDividerVisible();
+ return mSplits.mSplitScreenController.isDividerVisible();
}
private boolean getSecondaryHasFocus(int displayId) {
@@ -151,7 +151,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mSecondaryHasFocus = getSecondaryHasFocus(displayId);
final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
&& !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
- && !mSplits.mDividerController.isMinimized();
+ && !mSplits.mSplitScreenController.isMinimized();
if (mLastAdjustTop < 0) {
mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
} else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
@@ -236,7 +236,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
}
- if (!mSplits.mDividerController.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
+ if (!mSplits.mSplitScreenController.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
WindowOrganizer.applyTransaction(wct);
}
}
@@ -250,7 +250,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
: DisplayImeController.ANIMATION_DURATION_HIDE_MS);
}
}
- mSplits.mDividerController.setAdjustedForIme(mTargetShown && !mPaused);
+ mSplits.mSplitScreenController.setAdjustedForIme(mTargetShown && !mPaused);
}
public void updateAdjustForIme() {
@@ -402,7 +402,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mTargetAdjusted = mPausedTargetAdjusted;
updateDimTargets();
final DividerView view = getView();
- if ((mTargetAdjusted != mAdjusted) && !mSplits.mDividerController.isMinimized()
+ if ((mTargetAdjusted != mAdjusted) && !mSplits.mSplitScreenController.isMinimized()
&& view != null) {
// End unminimize animations since they conflict with adjustment animations.
view.finishAnimations();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
deleted file mode 100644
index 9acb96bb45e9..000000000000
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.stackdivider;
-
-import android.content.Context;
-import android.os.Handler;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.SystemWindows;
-import com.android.wm.shell.common.TransactionPool;
-
-import dagger.Module;
-import dagger.Provides;
-
-/**
- * Module which provides a Divider.
- */
-@Module
-public class DividerModule {
- @SysUISingleton
- @Provides
- static Divider provideDivider(Context context, DisplayController displayController,
- SystemWindows systemWindows, DisplayImeController imeController, @Main Handler handler,
- KeyguardStateController keyguardStateController, TransactionPool transactionPool,
- ShellTaskOrganizer shellTaskOrganizer) {
- // TODO(b/161116823): fetch DividerProxy from WM shell lib.
- DividerController dividerController = new DividerController(context, displayController,
- systemWindows, imeController, handler, transactionPool, shellTaskOrganizer);
- return new Divider(context, dividerController, keyguardStateController);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index e5c02d6fc454..95f048b0b06d 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -76,7 +76,7 @@ import java.util.function.Consumer;
public class DividerView extends FrameLayout implements OnTouchListener,
OnComputeInternalInsetsListener {
private static final String TAG = "DividerView";
- private static final boolean DEBUG = DividerController.DEBUG;
+ private static final boolean DEBUG = SplitScreenController.DEBUG;
public interface DividerCallbacks {
void onDraggingStart();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index ff8bab07db05..4c26694cc22a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -69,9 +69,9 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider
}
public ForcedResizableInfoActivityController(Context context,
- DividerController dividerController) {
+ SplitScreenController splitScreenController) {
mContext = context;
- dividerController.registerInSplitScreenListener(mDockedStackExistsListener);
+ splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java
index 9b5833b4c116..4cba9c7752eb 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenController.java
@@ -49,26 +49,34 @@ import java.util.ArrayList;
import java.util.function.Consumer;
/**
- * Controls the docked stack divider.
+ * Controls split screen.
*/
-public class DividerController implements DisplayController.OnDisplaysChangedListener {
+// TODO(b/161116823): Extract as an interface to expose to SysUISingleton scope.
+public class SplitScreenController implements DisplayController.OnDisplaysChangedListener {
static final boolean DEBUG = false;
+
private static final String TAG = "Divider";
+ private static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+
+ private final Context mContext;
+ private final DisplayChangeController.OnDisplayChangingListener mRotationController;
+ private final DisplayController mDisplayController;
+ private final DisplayImeController mImeController;
+ private final DividerImeController mImePositionProcessor;
+ private final DividerState mDividerState = new DividerState();
+ private final ForcedResizableInfoActivityController mForcedResizableController;
+ private final Handler mHandler;
+ private final SplitScreenTaskOrganizer mSplits;
+ private final SystemWindows mSystemWindows;
+ final TransactionPool mTransactionPool;
+ private final WindowManagerProxy mWindowManagerProxy;
+
+ private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
+ new ArrayList<>();
- static final int DEFAULT_APP_TRANSITION_DURATION = 336;
private DividerWindowManager mWindowManager;
private DividerView mView;
- private final DividerState mDividerState = new DividerState();
- private boolean mVisible = false;
- private boolean mMinimized = false;
- private boolean mAdjustedForIme = false;
- private boolean mHomeStackResizable = false;
- private ForcedResizableInfoActivityController mForcedResizableController;
- private SystemWindows mSystemWindows;
- private DisplayController mDisplayController;
- private DisplayImeController mImeController;
- final TransactionPool mTransactionPool;
// Keeps track of real-time split geometry including snap positions and ime adjustments
private SplitDisplayLayout mSplitLayout;
@@ -78,19 +86,13 @@ public class DividerController implements DisplayController.OnDisplaysChangedLis
// layout that we sent back to WM.
private SplitDisplayLayout mRotateSplitLayout;
- private final Handler mHandler;
- private final WindowManagerProxy mWindowManagerProxy;
-
- private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
- new ArrayList<>();
-
- private final SplitScreenTaskOrganizer mSplits;
- private final DisplayChangeController.OnDisplayChangingListener mRotationController;
- private final DividerImeController mImePositionProcessor;
- private final Context mContext;
private boolean mIsKeyguardShowing;
+ private boolean mVisible = false;
+ private boolean mMinimized = false;
+ private boolean mAdjustedForIme = false;
+ private boolean mHomeStackResizable = false;
- public DividerController(Context context,
+ public SplitScreenController(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController imeController, Handler handler, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer) {
@@ -142,10 +144,7 @@ public class DividerController implements DisplayController.OnDisplaysChangedLis
wct.merge(t, true /* transfer */);
}
};
- }
- /** Inits the divider service. */
- public void start() {
mWindowManager = new DividerWindowManager(mSystemWindows);
mDisplayController.addDisplayWindowListener(this);
// Don't initialize the divider or anything until we get the default display.
@@ -157,15 +156,15 @@ public class DividerController implements DisplayController.OnDisplaysChangedLis
}
/** Called when keyguard showing state changed. */
- public void onKeyguardShowingChanged(boolean isShowing) {
+ public void onKeyguardVisibilityChanged(boolean showing) {
if (!isSplitActive() || mView == null) {
return;
}
- mView.setHidden(isShowing);
- if (!isShowing) {
+ mView.setHidden(showing);
+ if (!showing) {
mImePositionProcessor.updateAdjustForIme();
}
- mIsKeyguardShowing = isShowing;
+ mIsKeyguardShowing = showing;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index ffd0c7c061d6..325c5597f9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -37,7 +37,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
private static final String TAG = "SplitScreenTaskOrg";
- private static final boolean DEBUG = DividerController.DEBUG;
+ private static final boolean DEBUG = SplitScreenController.DEBUG;
private final ShellTaskOrganizer mTaskOrganizer;
@@ -48,14 +48,14 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
SurfaceControl mPrimaryDim;
SurfaceControl mSecondaryDim;
Rect mHomeBounds = new Rect();
- final DividerController mDividerController;
+ final SplitScreenController mSplitScreenController;
private boolean mSplitScreenSupported = false;
final SurfaceSession mSurfaceSession = new SurfaceSession();
- SplitScreenTaskOrganizer(DividerController dividerController,
+ SplitScreenTaskOrganizer(SplitScreenController splitScreenController,
ShellTaskOrganizer shellTaskOrganizer) {
- mDividerController = dividerController;
+ mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
mTaskOrganizer.addListener(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
@@ -81,11 +81,11 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
}
SurfaceControl.Transaction getTransaction() {
- return mDividerController.mTransactionPool.acquire();
+ return mSplitScreenController.mTransactionPool.acquire();
}
void releaseTransaction(SurfaceControl.Transaction t) {
- mDividerController.mTransactionPool.release(t);
+ mSplitScreenController.mTransactionPool.release(t);
}
@Override
@@ -146,7 +146,7 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
t.apply();
releaseTransaction(t);
- mDividerController.onTaskVanished();
+ mSplitScreenController.onTaskVanished();
}
}
}
@@ -156,7 +156,7 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
if (taskInfo.displayId != DEFAULT_DISPLAY) {
return;
}
- mDividerController.post(() -> handleTaskInfoChanged(taskInfo));
+ mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
}
/**
@@ -175,7 +175,7 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
}
final boolean secondaryImpliedMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
|| (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
- && mDividerController.isHomeStackResizable());
+ && mSplitScreenController.isHomeStackResizable());
final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
if (info.token.asBinder() == mPrimary.token.asBinder()) {
@@ -187,7 +187,7 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryImpliesMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
|| (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
- && mDividerController.isHomeStackResizable());
+ && mSplitScreenController.isHomeStackResizable());
if (DEBUG) {
Log.d(TAG, "onTaskInfoChanged " + mPrimary + " " + mSecondary);
}
@@ -203,14 +203,14 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
+ " " + mSecondary.topActivityType);
}
- if (mDividerController.isDividerVisible()) {
+ if (mSplitScreenController.isDividerVisible()) {
// Was in split-mode, which means we are leaving split, so continue that.
// This happens when the stack in the primary-split is dismissed.
if (DEBUG) {
Log.d(TAG, " was in split, so this means leave it "
+ mPrimary.topActivityType + " " + mSecondary.topActivityType);
}
- mDividerController.startDismissSplit();
+ mSplitScreenController.startDismissSplit();
} else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) {
// Wasn't in split-mode (both were empty), but now that the primary split is
// populated, we should fully enter split by moving everything else into secondary.
@@ -219,15 +219,15 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
if (DEBUG) {
Log.d(TAG, " was not in split, but primary is populated, so enter it");
}
- mDividerController.startEnterSplit();
+ mSplitScreenController.startEnterSplit();
}
} else if (secondaryImpliesMinimize) {
// Both splits are populated but the secondary split has a home/recents stack on top,
// so enter minimized mode.
- mDividerController.ensureMinimizedSplit();
+ mSplitScreenController.ensureMinimizedSplit();
} else {
// Both splits are populated by normal activities, so make sure we aren't minimized.
- mDividerController.ensureNormalSplit();
+ mSplitScreenController.ensureNormalSplit();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
index f2500e59abab..13ed02e9513e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
@@ -33,7 +33,7 @@ import java.util.ArrayList;
* Helper for serializing sync-transactions and corresponding callbacks.
*/
class SyncTransactionQueue {
- private static final boolean DEBUG = DividerController.DEBUG;
+ private static final boolean DEBUG = SplitScreenController.DEBUG;
private static final String TAG = "SyncTransactionQueue";
// Just a little longer than the sync-engine timeout of 5s
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index ea614fb210b3..c27f66356ff3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -55,12 +55,13 @@ import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -80,13 +81,14 @@ public class InstantAppNotifier extends SystemUI
private final CommandQueue mCommandQueue;
private boolean mDockedStackExists;
private KeyguardStateController mKeyguardStateController;
- private final Divider mDivider;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
@Inject
public InstantAppNotifier(Context context, CommandQueue commandQueue,
- @UiBackground Executor uiBgExecutor, Divider divider) {
+ @UiBackground Executor uiBgExecutor,
+ Optional<SplitScreenController> splitScreenControllerOptional) {
super(context);
- mDivider = divider;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mCommandQueue = commandQueue;
mUiBgExecutor = uiBgExecutor;
}
@@ -105,11 +107,11 @@ public class InstantAppNotifier extends SystemUI
mCommandQueue.addCallback(this);
mKeyguardStateController.addCallback(this);
- mDivider.registerInSplitScreenListener(
- exists -> {
+ mSplitScreenControllerOptional.ifPresent(splitScreen ->
+ splitScreen.registerInSplitScreenListener(exists -> {
mDockedStackExists = exists;
updateForegroundInstantApps();
- });
+ }));
// Clear out all old notifications on startup (only present in the case where sysui dies)
NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 6e37f90f9d94..9391104fc2b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -177,7 +177,7 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
@@ -388,7 +388,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder;
private final PluginManager mPluginManager;
- private final Optional<Divider> mDividerOptional;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
private final StatusBarNotificationActivityStarter.Builder
mStatusBarNotificationActivityStarterBuilder;
private final ShadeController mShadeController;
@@ -721,7 +721,7 @@ public class StatusBar extends SystemUI implements DemoMode,
Optional<Recents> recentsOptional,
Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
PluginManager pluginManager,
- Optional<Divider> dividerOptional,
+ Optional<SplitScreenController> splitScreenControllerOptional,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
@@ -803,7 +803,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mRecentsOptional = recentsOptional;
mStatusBarComponentBuilder = statusBarComponentBuilder;
mPluginManager = pluginManager;
- mDividerOptional = dividerOptional;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
mShadeController = shadeController;
mSuperStatusBarViewFactory = superStatusBarViewFactory;
@@ -1550,31 +1550,32 @@ public class StatusBar extends SystemUI implements DemoMode,
if (!mRecentsOptional.isPresent()) {
return false;
}
- Divider divider = null;
- if (mDividerOptional.isPresent()) {
- divider = mDividerOptional.get();
- }
- if (divider == null || !divider.isDividerVisible()) {
- final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(mDisplayId);
- if (navbarPos == NAV_BAR_POS_INVALID) {
- return false;
- }
- int createMode = navbarPos == NAV_BAR_POS_LEFT
- ? SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT
- : SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
- return mRecentsOptional.get().splitPrimaryTask(createMode, null, metricsDockAction);
- } else {
- if (divider.isMinimized() && !divider.isHomeStackResizable()) {
- // Undocking from the minimized state is not supported
- return false;
- } else {
- divider.onUndockingTask();
- if (metricsUndockAction != -1) {
- mMetricsLogger.action(metricsUndockAction);
+
+ if (mSplitScreenControllerOptional.isPresent()) {
+ SplitScreenController splitScreenController = mSplitScreenControllerOptional.get();
+ if (splitScreenController.isDividerVisible()) {
+ if (splitScreenController.isMinimized()
+ && !splitScreenController.isHomeStackResizable()) {
+ // Undocking from the minimized state is not supported
+ return false;
+ } else {
+ splitScreenController.onUndockingTask();
+ if (metricsUndockAction != -1) {
+ mMetricsLogger.action(metricsUndockAction);
+ }
}
+ return true;
}
}
- return true;
+
+ final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(mDisplayId);
+ if (navbarPos == NAV_BAR_POS_INVALID) {
+ return false;
+ }
+ int createMode = navbarPos == NAV_BAR_POS_LEFT
+ ? SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT
+ : SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+ return mRecentsOptional.get().splitPrimaryTask(createMode, null, metricsDockAction);
}
/**
@@ -3916,14 +3917,16 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void appTransitionCancelled(int displayId) {
if (displayId == mDisplayId) {
- mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
+ mSplitScreenControllerOptional.ifPresent(
+ splitScreen -> splitScreen.onAppTransitionFinished());
}
}
@Override
public void appTransitionFinished(int displayId) {
if (displayId == mDisplayId) {
- mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
+ mSplitScreenControllerOptional.ifPresent(
+ splitScreen -> splitScreen.onAppTransitionFinished());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 2768b826fcfe..024a77664781 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -46,7 +46,7 @@ import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -180,7 +180,7 @@ public interface StatusBarPhoneModule {
Optional<Recents> recentsOptional,
Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
PluginManager pluginManager,
- Optional<Divider> dividerOptional,
+ Optional<SplitScreenController> splitScreenControllerOptional,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
@@ -260,7 +260,7 @@ public interface StatusBarPhoneModule {
recentsOptional,
statusBarComponentBuilder,
pluginManager,
- dividerOptional,
+ splitScreenControllerOptional,
lightsOutNotifController,
statusBarNotificationActivityStarterBuilder,
shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index ca9cb08c0a59..e7c10f1697f5 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -42,7 +42,6 @@ import com.android.systemui.qs.dagger.QSModule;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
-import com.android.systemui.stackdivider.DividerModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
@@ -76,7 +75,6 @@ import dagger.Provides;
* overridden by the System UI implementation.
*/
@Module(includes = {
- DividerModule.class,
QSModule.class,
WMShellModule.class
},
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
new file mode 100644
index 000000000000..b7d6903be23a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.wmshell;
+
+import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+
+import android.app.ActivityManager;
+import android.content.Context;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.SystemUI;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.stackdivider.SplitScreenController;
+import com.android.wm.shell.common.DisplayImeController;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * Proxy in SysUiScope to delegate events to controllers in WM Shell library.
+ */
+@SysUISingleton
+public final class WMShell extends SystemUI {
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final DisplayImeController mDisplayImeController;
+ private final Optional<SplitScreenController> mSplitScreenControllerOptional;
+
+ @Inject
+ WMShell(Context context, KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DisplayImeController displayImeController,
+ Optional<SplitScreenController> splitScreenControllerOptional) {
+ super(context);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mDisplayImeController = displayImeController;
+ mSplitScreenControllerOptional = splitScreenControllerOptional;
+ }
+
+ @Override
+ public void start() {
+ // This is to prevent circular init problem by separating registration step out of its
+ // constructor. And make sure the initialization of DisplayImeController won't depend on
+ // specific feature anymore.
+ mDisplayImeController.startMonitorDisplays();
+
+ mSplitScreenControllerOptional.ifPresent(this::initSplitScreenController);
+ }
+
+ private void initSplitScreenController(SplitScreenController splitScreenController) {
+ mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ // Hide the divider when keyguard is showing. Even though keyguard/statusbar is
+ // above everything, it is actually transparent except for notifications, so
+ // we still need to hide any surfaces that are below it.
+ // TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
+ splitScreenController.onKeyguardVisibilityChanged(showing);
+ }
+ });
+
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(
+ new TaskStackChangeListener() {
+ @Override
+ public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+ boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+ if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
+ != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || !splitScreenController.isSplitScreenSupported()) {
+ return;
+ }
+
+ if (splitScreenController.isMinimized()) {
+ splitScreenController.onUndockingTask();
+ }
+ }
+
+ @Override
+ public void onActivityForcedResizable(String packageName, int taskId,
+ int reason) {
+ splitScreenController
+ .onActivityForcedResizable(packageName, taskId, reason);
+ }
+
+ @Override
+ public void onActivityDismissingDockedStack() {
+ splitScreenController.onActivityDismissingSplitScreen();
+ }
+
+ @Override
+ public void onActivityLaunchOnSecondaryDisplayFailed() {
+ splitScreenController.onActivityLaunchOnSecondaryDisplayFailed();
+ }
+ });
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 18cb7d3b3200..3111b13bc7f4 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -24,6 +24,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.pip.PipUiEventLogger;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -31,6 +32,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
+import dagger.BindsOptionalOf;
import dagger.Module;
import dagger.Provides;
@@ -40,7 +42,7 @@ import dagger.Provides;
*/
// TODO(b/162923491): Move most of these dependencies into WMSingleton scope.
@Module
-public class WMShellBaseModule {
+public abstract class WMShellBaseModule {
@SysUISingleton
@Provides
static TransactionPool provideTransactionPool() {
@@ -59,6 +61,7 @@ public class WMShellBaseModule {
static DeviceConfigProxy provideDeviceConfigProxy() {
return new DeviceConfigProxy();
}
+
@SysUISingleton
@Provides
static FloatingContentCoordinator provideFloatingContentCoordinator() {
@@ -80,9 +83,12 @@ public class WMShellBaseModule {
@SysUISingleton
@Provides
- public ShellTaskOrganizer provideShellTaskOrganizer() {
+ static ShellTaskOrganizer provideShellTaskOrganizer() {
ShellTaskOrganizer organizer = new ShellTaskOrganizer();
organizer.registerOrganizer();
return organizer;
}
+
+ @BindsOptionalOf
+ abstract SplitScreenController optionalSplitScreenController();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 44bb6ac5a49c..ceb6d5970007 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.wmshell;
+import android.content.Context;
import android.os.Handler;
import android.view.IWindowManager;
@@ -23,8 +24,11 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.pip.phone.PipMenuActivity;
import com.android.systemui.pip.phone.dagger.PipMenuActivityClass;
+import com.android.systemui.stackdivider.SplitScreenController;
+import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
import dagger.Module;
@@ -42,8 +46,7 @@ public class WMShellModule {
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
DisplayController displayController, @Main Handler mainHandler,
TransactionPool transactionPool) {
- return new DisplayImeController.Builder(wmService, displayController, mainHandler,
- transactionPool).build();
+ return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
}
/** TODO(b/150319024): PipMenuActivity will move to a Window */
@@ -53,4 +56,14 @@ public class WMShellModule {
static Class<?> providePipMenuActivityClass() {
return PipMenuActivity.class;
}
+
+ @SysUISingleton
+ @Provides
+ static SplitScreenController provideSplitScreenController(Context context,
+ DisplayController displayController, SystemWindows systemWindows,
+ DisplayImeController displayImeController, @Main Handler handler,
+ TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer) {
+ return new SplitScreenController(context, displayController, systemWindows,
+ displayImeController, handler, transactionPool, shellTaskOrganizer);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
index 7a8e4f7e9b85..f38524369b46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
@@ -155,6 +155,22 @@ class MediaTimeoutListenerTest : SysuiTestCase() {
}
@Test
+ fun testOnMediaDataLoaded_migratesKeys_noTimeoutExtension() {
+ // From not playing
+ mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ clearInvocations(mediaController)
+
+ // Migrate, still not playing
+ val playingState = mock(android.media.session.PlaybackState::class.java)
+ `when`(playingState.state).thenReturn(PlaybackState.STATE_PAUSED)
+ `when`(mediaController.playbackState).thenReturn(playingState)
+ mediaTimeoutListener.onMediaDataLoaded("NEWKEY", KEY, mediaData)
+
+ // Never cancels callback, or schedule another one
+ verify(cancellationRunnable, never()).run()
+ }
+
+ @Test
fun testOnPlaybackStateChanged_schedulesTimeout_whenPaused() {
// Assuming we're registered
testOnMediaDataLoaded_registersPlaybackListener()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 2e4d8a7ff472..4bc9b464334d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -52,7 +52,7 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -61,13 +61,13 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import java.util.Optional;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Optional;
+
/** atest NavigationBarControllerTest */
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -90,13 +90,13 @@ public class NavigationBarControllerTest extends SysuiTestCase {
mock(AccessibilityManagerWrapper.class),
mock(DeviceProvisionedController.class),
mock(MetricsLogger.class),
- mock(OverviewProxyService.class),
+ mock(OverviewProxyService.class),
mock(NavigationModeController.class),
mock(StatusBarStateController.class),
mock(SysUiState.class),
mock(BroadcastDispatcher.class),
mock(CommandQueue.class),
- mock(Divider.class),
+ Optional.of(mock(SplitScreenController.class)),
Optional.of(mock(Recents.class)),
() -> mock(StatusBar.class),
mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index a643c2dc0f19..63821c400e23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -68,7 +68,7 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -121,7 +121,6 @@ public class NavigationBarTest extends SysuiTestCase {
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(StatusBarStateController.class);
mDependency.injectMockDependency(NavigationBarController.class);
- mDependency.injectMockDependency(Divider.class);
mOverviewProxyService = mDependency.injectMockDependency(OverviewProxyService.class);
TestableLooper.get(this).runWithLooper(() -> {
mHandler = new Handler();
@@ -224,7 +223,7 @@ public class NavigationBarTest extends SysuiTestCase {
mMockSysUiState,
mBroadcastDispatcher,
mCommandQueue,
- mock(Divider.class),
+ Optional.of(mock(SplitScreenController.class)),
Optional.of(mock(Recents.class)),
() -> mock(StatusBar.class),
mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 8462386aaf2d..869fbd813e9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -96,7 +96,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.SplitScreenController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationListener;
@@ -238,7 +238,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private StatusBarComponent.Builder mStatusBarComponentBuilder;
@Mock private StatusBarComponent mStatusBarComponent;
@Mock private PluginManager mPluginManager;
- @Mock private Divider mDivider;
+ @Mock private SplitScreenController mSplitScreenController;
@Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Mock private LightsOutNotifController mLightsOutNotifController;
@Mock private ViewMediatorCallback mViewMediatorCallback;
@@ -397,7 +397,7 @@ public class StatusBarTest extends SysuiTestCase {
Optional.of(mRecents),
mStatusBarComponentBuilderProvider,
mPluginManager,
- Optional.of(mDivider),
+ Optional.of(mSplitScreenController),
mLightsOutNotifController,
mStatusBarNotificationActivityStarterBuilder,
mShadeController,
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index ad1986a6669f..cf9324c13ae8 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -302,24 +302,11 @@ public abstract class PackageManagerInternal {
String packageName, int userId);
/**
- * Do a straight uid lookup for the given package/application in the given user. This enforces
- * app visibility rules and permissions. Call {@link #getPackageUidInternal} for the internal
- * implementation.
- * @deprecated Use {@link PackageManager#getPackageUid(String, int)}
- * @return The app's uid, or < 0 if the package was not found in that user
- */
- @Deprecated
- public abstract int getPackageUid(String packageName,
- @PackageInfoFlags int flags, int userId);
-
- /**
* Do a straight uid lookup for the given package/application in the given user.
* @see PackageManager#getPackageUidAsUser(String, int, int)
* @return The app's uid, or < 0 if the package was not found in that user
- * TODO(b/148235092): rename this to getPackageUid
*/
- public abstract int getPackageUidInternal(String packageName,
- @PackageInfoFlags int flags, int userId);
+ public abstract int getPackageUid(String packageName, @PackageInfoFlags int flags, int userId);
/**
* Retrieve all of the information we know about a particular package/application.
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b72985cc8f2c..27c5d4a53956 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2160,7 +2160,7 @@ class StorageManagerService extends IStorageManager.Stub
Slog.i(TAG, "Remounting storage for pid: " + pid);
final String[] sharedPackages =
mPmInternal.getSharedUserPackagesForPackage(packageName, userId);
- final int uid = mPmInternal.getPackageUidInternal(packageName, 0, userId);
+ final int uid = mPmInternal.getPackageUid(packageName, 0 /* flags */, userId);
final String[] packages =
sharedPackages.length != 0 ? sharedPackages : new String[]{packageName};
try {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 19871f993d42..eb8308b56f2e 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2106,20 +2106,20 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mOutgoingCallEmergencyNumber[phoneId] = emergencyNumber;
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)
- && idMatch(r.subId, subId, phoneId)) {
- try {
- r.callback.onOutgoingEmergencyCall(emergencyNumber);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
+ }
+ for (Record r : mRecords) {
+ // Send to all listeners regardless of subscription
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)) {
+ try {
+ r.callback.onOutgoingEmergencyCall(emergencyNumber, subId);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
}
}
}
- handleRemoveListLocked();
}
+ handleRemoveListLocked();
}
@Override
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 9ab410d258cc..3fddd5ab91ee 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2591,7 +2591,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
mCurMethod = IInputMethod.Stub.asInterface(service);
final String curMethodPackage = mCurIntent.getComponent().getPackageName();
- final int curMethodUid = mPackageManagerInternal.getPackageUidInternal(
+ final int curMethodUid = mPackageManagerInternal.getPackageUid(
curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId());
if (curMethodUid < 0) {
Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
diff --git a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
index e3074dba26ef..ddd56c890c2f 100644
--- a/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
+++ b/services/core/java/com/android/server/locksettings/BiometricDeferredQueue.java
@@ -123,6 +123,10 @@ public class BiometricDeferredQueue {
final VerifyCredentialResponse response = spManager.verifyChallengeInternal(
getGatekeeperService(), userAuthInfo.gatekeeperPassword, challenge,
userAuthInfo.userId);
+ if (response == null) {
+ Slog.wtf(TAG, "VerifyChallenge failed, null response");
+ continue;
+ }
if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
Slog.wtf(TAG, "VerifyChallenge failed, response: "
+ response.getResponseCode());
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index 617f6879e65e..a234f5ac3f3e 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -605,7 +605,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
private boolean isPlatformSignedAppWithAutomaticProfilesPermission(
String packageName, int[] profileIds) {
for (int userId : profileIds) {
- final int uid = mInjector.getPackageManagerInternal().getPackageUidInternal(
+ final int uid = mInjector.getPackageManagerInternal().getPackageUid(
packageName, /* flags= */ 0, userId);
if (uid == -1) {
continue;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 28c5e964fe27..4f3d3600ae37 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1325,6 +1325,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
final int sessionIndex = mChildSessionsRemaining.indexOfKey(sessionId);
+ final String message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
if (PackageInstaller.STATUS_SUCCESS == status) {
mChildSessionsRemaining.removeAt(sessionIndex);
if (mChildSessionsRemaining.size() == 0) {
@@ -1341,10 +1342,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
PackageInstallerSession.this.sessionId);
mChildSessionsRemaining.clear(); // we're done. Don't send any more.
- try {
- mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
- } catch (IntentSender.SendIntentException ignore) {
- }
+ destroyInternal();
+ dispatchSessionFinished(INSTALL_FAILED_INTERNAL_ERROR,
+ "Child session " + sessionId + " failed: " + message, null);
}
});
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3b98d24dc709..5fd73743c3ac 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5806,10 +5806,6 @@ public class PackageManagerService extends IPackageManager.Stub
private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) {
for (int i = userList.length - 1; i >= 0; --i) {
final int userId = userList[i];
- // don't add instant app to the list of updates
- if (pkgSetting.getInstantApp(userId)) {
- continue;
- }
SparseArray<String> changedPackages = mChangedPackages.get(userId);
if (changedPackages == null) {
changedPackages = new SparseArray<>();
@@ -5854,6 +5850,11 @@ public class PackageManagerService extends IPackageManager.Stub
for (int i = sequenceNumber; i < mChangedPackagesSequenceNumber; i++) {
final String packageName = changedPackages.get(i);
if (packageName != null) {
+ // Filter out the changes if the calling package should not be able to see it.
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+ continue;
+ }
packageNames.add(packageName);
}
}
@@ -24603,12 +24604,6 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public int getPackageUid(String packageName, int flags, int userId) {
return PackageManagerService.this
- .getPackageUid(packageName, flags, userId);
- }
-
- @Override
- public int getPackageUidInternal(String packageName, int flags, int userId) {
- return PackageManagerService.this
.getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 32ec052a1fe0..7e2ef41943d6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3199,12 +3199,24 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
+ private long getFileStatSize(File file) {
+ final ParcelFileDescriptor pfd = openFileForSystem(file.getPath(), "r");
+ if (pfd == null) {
+ throw new IllegalArgumentException("Error: Can't open file: " + file.getPath());
+ }
+ try {
+ return pfd.getStatSize();
+ } finally {
+ IoUtils.closeQuietly(pfd);
+ }
+ }
+
private void processArgForLocalFile(String arg, PackageInstaller.Session session) {
final String inPath = arg;
final File file = new File(inPath);
final String name = file.getName();
- final long size = file.length();
+ final long size = getFileStatSize(file);
final Metadata metadata = Metadata.forLocalFile(inPath);
byte[] v4signatureBytes = null;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d545bd4c1531..659e2a32e267 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4551,6 +4551,7 @@ public final class Settings {
? "true" : "false");
pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
+ pw.print(prefix); pw.print(" cpuAbiOverride="); pw.println(ps.cpuAbiOverrideString);
}
pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode);
if (pkg != null) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 700f7be83e15..8412077d9a11 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3301,7 +3301,7 @@ public class ShortcutService extends IShortcutService.Stub {
final long token = Binder.clearCallingIdentity();
try {
- int packageUid = mPackageManagerInternal.getPackageUidInternal(packageName,
+ int packageUid = mPackageManagerInternal.getPackageUid(packageName,
PackageManager.MATCH_DIRECT_BOOT_AUTO, userId);
// Grant read uri permission to the caller on behalf of the shortcut owner. All
// granted permissions are revoked when the default launcher changes, or when
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index a106dc682208..0b0bb7059f3b 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -258,7 +258,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
- final int packageUid = pm.getPackageUidInternal(packageName,
+ final int packageUid = pm.getPackageUid(packageName,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, callingUserId);
if (packageUid != callingUid) {
throw new SecurityException(
@@ -336,7 +336,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
if (toPackage != null) {
mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
"takePersistableUriPermission");
- uid = mPmInternal.getPackageUidInternal(toPackage, 0, userId);
+ uid = mPmInternal.getPackageUid(toPackage, 0 /* flags */, userId);
} else {
enforceNotIsolatedCaller("takePersistableUriPermission");
uid = Binder.getCallingUid();
@@ -401,7 +401,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
if (toPackage != null) {
mAmInternal.enforceCallingPermission(FORCE_PERSISTABLE_URI_PERMISSIONS,
"releasePersistableUriPermission");
- uid = mPmInternal.getPackageUidInternal(toPackage, 0, userId);
+ uid = mPmInternal.getPackageUid(toPackage, 0 /* flags */ , userId);
} else {
enforceNotIsolatedCaller("releasePersistableUriPermission");
uid = Binder.getCallingUid();
@@ -600,7 +600,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
if (needed != null) {
targetUid = needed.targetUid;
} else {
- targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+ targetUid = mPmInternal.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
targetUserId);
if (targetUid < 0) {
if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg
@@ -690,7 +690,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
final ProviderInfo pi = getProviderInfo(uri.getAuthority(), sourceUserId,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
if (pi != null && sourcePkg.equals(pi.packageName)) {
- int targetUid = mPmInternal.getPackageUidInternal(
+ int targetUid = mPmInternal.getPackageUid(
targetPkg, MATCH_UNINSTALLED_PACKAGES, targetUserId);
if (targetUid != -1) {
final GrantUri grantUri = new GrantUri(sourceUserId, uri,
@@ -787,7 +787,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
}
- int targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+ int targetUid = mPmInternal.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
targetUserId);
targetUid = checkGrantUriPermissionUnlocked(callingUid, targetPkg, grantUri, modeFlags,
@@ -1108,7 +1108,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
int targetUid = lastTargetUid;
if (targetUid < 0 && targetPkg != null) {
- targetUid = mPmInternal.getPackageUidInternal(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+ targetUid = mPmInternal.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.getUserId(callingUid));
if (targetUid < 0) {
if (DEBUG) Slog.v(TAG, "Can't grant URI permission no uid for: " + targetPkg);
@@ -1462,7 +1462,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
boolean printed = false;
int dumpUid = -2;
if (dumpPackage != null) {
- dumpUid = mPmInternal.getPackageUidInternal(dumpPackage, MATCH_ANY_USER, 0);
+ dumpUid = mPmInternal.getPackageUid(dumpPackage,
+ MATCH_ANY_USER, 0 /* userId */);
}
for (int i = 0; i < mGrantedUriPermissions.size(); i++) {
int uid = mGrantedUriPermissions.keyAt(i);
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 9bbeb728ae33..90a153be8800 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -209,8 +209,8 @@ public class WebViewUpdateService extends SystemService {
private void grantVisibilityToCaller(String webViewPackageName, int callingUid) {
final PackageManagerInternal pmInternal = LocalServices.getService(
PackageManagerInternal.class);
- final int webviewUid = pmInternal.getPackageUidInternal(
- webViewPackageName, 0, UserHandle.getUserId(callingUid));
+ final int webviewUid = pmInternal.getPackageUid(
+ webViewPackageName, 0 /* flags */, UserHandle.getUserId(callingUid));
pmInternal.grantImplicitAccess(UserHandle.getUserId(callingUid), null,
UserHandle.getAppId(callingUid), webviewUid,
true /*direct*/);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9316c4657826..b8b20a3e80af 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2786,8 +2786,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
makeFinishingLocked();
- final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
- "finish-imm:" + reason);
+ final boolean activityRemoved = destroyImmediately("finish-imm:" + reason);
// If the display does not have running activity, the configuration may need to be
// updated for restoring original orientation of the display.
@@ -2835,7 +2834,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* @return {@code true} if activity was immediately removed from history, {@code false}
* otherwise.
*/
- boolean destroyImmediately(boolean removeFromApp, String reason) {
+ boolean destroyImmediately(String reason) {
if (DEBUG_SWITCH || DEBUG_CLEANUP) {
Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
+ ", app=" + (hasProcess() ? app.mName : "(null)"));
@@ -2857,17 +2856,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
cleanUp(false /* cleanServices */, false /* setState */);
if (hasProcess()) {
- if (removeFromApp) {
- app.removeActivity(this, true /* keepAssociation */);
- if (!app.hasActivities()) {
- mAtmService.clearHeavyWeightProcessIfEquals(app);
- // Update any services we are bound to that might care about whether
- // their client may have activities.
- // No longer have activities, so update LRU list and oom adj.
- app.updateProcessInfo(true /* updateServiceConnectionActivities */,
- false /* activityChange */, true /* updateOomAdj */,
- false /* addPendingTopUid */);
- }
+ app.removeActivity(this, true /* keepAssociation */);
+ if (!app.hasActivities()) {
+ mAtmService.clearHeavyWeightProcessIfEquals(app);
+ // Update any services we are bound to that might care about whether
+ // their client may have activities.
+ // No longer have activities, so update LRU list and oom adj.
+ app.updateProcessInfo(true /* updateServiceConnectionActivities */,
+ false /* activityChange */, true /* updateOomAdj */,
+ false /* addPendingTopUid */);
}
boolean skipDestroy = false;
@@ -2934,7 +2931,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
+ " pausing=" + stack.mPausingActivity
+ " for reason " + reason);
}
- return destroyImmediately(true /* removeFromApp */, reason);
+ return destroyImmediately(reason);
}
return false;
}
@@ -5122,7 +5119,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
setState(STOPPED, "stopIfPossible");
if (deferRelaunchUntilPaused) {
- destroyImmediately(true /* removeFromApp */, "stop-except");
+ destroyImmediately("stop-except");
}
}
}
@@ -5163,7 +5160,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
clearOptionsLocked();
} else {
if (deferRelaunchUntilPaused) {
- destroyImmediately(true /* removeFromApp */, "stop-config");
+ destroyImmediately("stop-config");
mRootWindowContainer.resumeFocusedStacksTopActivities();
} else {
mRootWindowContainer.updatePreviousProcess(this);
@@ -7113,7 +7110,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (!attachedToProcess()) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is destroying non-running " + this);
- destroyImmediately(true /* removeFromApp */, "config");
+ destroyImmediately("config");
} else if (mState == PAUSING) {
// A little annoying: we are waiting for this activity to finish pausing. Let's not
// do anything now, but just flag that it needs to be restarted when done pausing.
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 2c475e0b9bcb..34f7f79d7716 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -41,10 +41,8 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static android.os.Process.INVALID_UID;
-import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.TYPE_VIRTUAL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
@@ -1869,7 +1867,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
for (int i = 0; i < numFinishingActivities; i++) {
final ActivityRecord r = finishingActivities.get(i);
if (r.isInHistory()) {
- r.destroyImmediately(true /* removeFromApp */, "finish-" + reason);
+ r.destroyImmediately("finish-" + reason);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index f6158383d28a..4c93b9ef64de 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1693,8 +1693,9 @@ class ActivityStarter {
// we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs
final PackageManagerInternal pmInternal =
mService.getPackageManagerInternalLocked();
- final int resultToUid = pmInternal.getPackageUidInternal(
- mStartActivity.resultTo.info.packageName, 0, mStartActivity.mUserId);
+ final int resultToUid = pmInternal.getPackageUid(
+ mStartActivity.resultTo.info.packageName, 0 /* flags */,
+ mStartActivity.mUserId);
pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,
UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,
resultToUid /*visible*/, true /*direct*/);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 403f225032e9..2adaa52dfb30 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3379,7 +3379,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r == null || !r.isDestroyable()) {
return false;
}
- r.destroyImmediately(true /* removeFromApp */, "app-req");
+ r.destroyImmediately("app-req");
return r.isState(DESTROYING, DESTROYED);
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index aeaffd98f820..0bf3dd9ca4a0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2716,7 +2716,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
+ " resumed=" + r.getStack().mResumedActivity + " pausing="
+ r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
- r.destroyImmediately(true /* removeFromTask */, mDestroyAllActivitiesReason);
+ r.destroyImmediately(mDestroyAllActivitiesReason);
}
// Tries to put all activity stacks to sleep. Returns true if all stacks were
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 3c8036d4e3b6..25732e7f0d99 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -101,7 +101,6 @@ class ScreenRotationAnimation {
private final Transformation mRotateExitTransformation = new Transformation();
private final Transformation mRotateEnterTransformation = new Transformation();
// Complete transformations being applied.
- private final Transformation mEnterTransformation = new Transformation();
private final Matrix mSnapshotInitialMatrix = new Matrix();
private final WindowManagerService mService;
/** Only used for custom animations and not screen rotation. */
@@ -309,8 +308,6 @@ class ScreenRotationAnimation {
pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
- pw.print(prefix); pw.print("mEnterTransformation=");
- mEnterTransformation.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
mSnapshotInitialMatrix.dump(pw); pw.println();
pw.print(prefix); pw.print("mForceDefaultOrientation="); pw.print(mForceDefaultOrientation);
@@ -508,10 +505,6 @@ class ScreenRotationAnimation {
return mCurRotation != mOriginalRotation;
}
- public Transformation getEnterTransformation() {
- return mEnterTransformation;
- }
-
/**
* Utility class that runs a {@link ScreenRotationAnimation} on the {@link
* SurfaceAnimationRunner}.
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index c714eeb92e68..bb9cf2e2ac05 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -941,7 +941,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
final ActivityRecord r = candidates.remove(0);
if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + r
+ " in state " + r.getState() + " for reason " + reason);
- r.destroyImmediately(true /*removeFromApp*/, reason);
+ r.destroyImmediately(reason);
--maxRelease;
} while (maxRelease > 0);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0e455d2a5aa6..f262c5ad7b2b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2058,10 +2058,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// animating... let's do something.
final int left = mWindowFrames.mFrame.left;
final int top = mWindowFrames.mFrame.top;
+
+ // During the transition from pip to fullscreen, the activity windowing mode is set to
+ // fullscreen at the beginning while the task is kept in pinned mode. Skip the move
+ // animation in such case since the transition is handled in SysUI.
+ final boolean hasMovementAnimation = getTask() == null
+ ? getWindowConfiguration().hasMovementAnimations()
+ : getTask().getWindowConfiguration().hasMovementAnimations();
if (mToken.okToAnimate()
&& (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& !isDragResizing()
- && getWindowConfiguration().hasMovementAnimations()
+ && hasMovementAnimation
&& !mWinAnimator.mLastHidden
&& !mSeamlesslyRotated) {
startMoveAnimation(left, top);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 4ff985f6bd43..6f483428eaec 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -660,80 +660,7 @@ class WindowStateAnimator {
}
void computeShownFrameLocked() {
- final ScreenRotationAnimation screenRotationAnimation =
- mWin.getDisplayContent().getRotationAnimation();
- final boolean windowParticipatesInScreenRotationAnimation =
- !mWin.mForceSeamlesslyRotate;
- final boolean screenAnimation = screenRotationAnimation != null
- && screenRotationAnimation.isAnimating()
- && windowParticipatesInScreenRotationAnimation;
-
- if (screenAnimation) {
- // cache often used attributes locally
- final Rect frame = mWin.getFrameLw();
- final float tmpFloats[] = mService.mTmpFloats;
- final Matrix tmpMatrix = mWin.mTmpMatrix;
-
- // Compute the desired transformation.
- if (screenRotationAnimation.isRotating()) {
- // If we are doing a screen animation, the global rotation
- // applied to windows can result in windows that are carefully
- // aligned with each other to slightly separate, allowing you
- // to see what is behind them. An unsightly mess. This...
- // thing... magically makes it call good: scale each window
- // slightly (two pixels larger in each dimension, from the
- // window's center).
- final float w = frame.width();
- final float h = frame.height();
- if (w>=1 && h>=1) {
- tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
- } else {
- tmpMatrix.reset();
- }
- } else {
- tmpMatrix.reset();
- }
-
- tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
-
- // WindowState.prepareSurfaces expands for surface insets (in order they don't get
- // clipped by the WindowState surface), so we need to go into the other direction here.
- tmpMatrix.postTranslate(mWin.mAttrs.surfaceInsets.left,
- mWin.mAttrs.surfaceInsets.top);
-
-
- // "convert" it into SurfaceFlinger's format
- // (a 2x2 matrix + an offset)
- // Here we must not transform the position of the surface
- // since it is already included in the transformation.
- //Slog.i(TAG_WM, "Transform: " + matrix);
-
- mHaveMatrix = true;
- tmpMatrix.getValues(tmpFloats);
- mDsDx = tmpFloats[Matrix.MSCALE_X];
- mDtDx = tmpFloats[Matrix.MSKEW_Y];
- mDtDy = tmpFloats[Matrix.MSKEW_X];
- mDsDy = tmpFloats[Matrix.MSCALE_Y];
-
- // Now set the alpha... but because our current hardware
- // can't do alpha transformation on a non-opaque surface,
- // turn it off if we are running an animation that is also
- // transforming since it is more important to have that
- // animation be smooth.
- mShownAlpha = mAlpha;
- if (!mService.mLimitedAlphaCompositing
- || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
- || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)))) {
- mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
- }
-
- if ((DEBUG_ANIM || DEBUG) && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) {
- Slog.v(TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
- + " screen=" + (screenAnimation
- ? screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
- }
- return;
- } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
+ if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
return;
} else if (mWin.isDragResizeChanged()) {
// This window is awaiting a relayout because user just started (or ended)
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 4b25890e5fdb..5fa809fc89af 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -204,10 +204,10 @@ public class CrossProfileAppsServiceImplRoboTest {
CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
ShadowApplicationPackageManager.setPackageUidAsUser(
CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
- when(mPackageManagerInternal.getPackageUidInternal(
+ when(mPackageManagerInternal.getPackageUid(
CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
.thenReturn(PERSONAL_PROFILE_UID);
- when(mPackageManagerInternal.getPackageUidInternal(
+ when(mPackageManagerInternal.getPackageUid(
CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
.thenReturn(WORK_PROFILE_UID);
}
diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
index d5aee5d208f5..2c719ff9e8b3 100644
--- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsMockContext.java
@@ -120,17 +120,17 @@ public class UriGrantsMockContext extends ContextWrapper {
LocalServices.addService(PackageManagerInternal.class, mPmInternal);
for (int userId : new int[] { USER_PRIMARY, USER_SECONDARY }) {
- when(mPmInternal.getPackageUidInternal(eq(PKG_SOCIAL), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_SOCIAL), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_SOCIAL));
- when(mPmInternal.getPackageUidInternal(eq(PKG_CAMERA), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_CAMERA), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_CAMERA));
- when(mPmInternal.getPackageUidInternal(eq(PKG_PRIVATE), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_PRIVATE), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_PRIVATE));
- when(mPmInternal.getPackageUidInternal(eq(PKG_PUBLIC), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_PUBLIC), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_PUBLIC));
- when(mPmInternal.getPackageUidInternal(eq(PKG_FORCE), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_FORCE), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_FORCE));
- when(mPmInternal.getPackageUidInternal(eq(PKG_COMPLEX), anyInt(), eq(userId)))
+ when(mPmInternal.getPackageUid(eq(PKG_COMPLEX), anyInt(), eq(userId)))
.thenReturn(UserHandle.getUid(userId, UID_COMPLEX));
when(mPmInternal.resolveContentProvider(eq(PKG_CAMERA), anyInt(), eq(userId)))
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 708d802a7533..6358c0dba471 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1190,7 +1190,7 @@ public class ActivityRecordTests extends WindowTestsBase {
assertEquals(DESTROYING, mActivity.getState());
assertTrue(mActivity.finishing);
- verify(mActivity).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ verify(mActivity).destroyImmediately(anyString());
}
/**
@@ -1214,7 +1214,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Verify that the activity was not actually destroyed, but waits for next one to come up
// instead.
- verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ verify(mActivity, never()).destroyImmediately(anyString());
assertEquals(FINISHING, mActivity.getState());
assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity));
}
@@ -1238,7 +1238,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mActivity.completeFinishing("test");
// Verify that the activity is not destroyed immediately, but waits for next one to come up.
- verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ verify(mActivity, never()).destroyImmediately(anyString());
assertEquals(FINISHING, mActivity.getState());
assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity));
}
@@ -1250,26 +1250,26 @@ public class ActivityRecordTests extends WindowTestsBase {
@Test
public void testDestroyImmediately_hadApp_finishing() {
mActivity.finishing = true;
- mActivity.destroyImmediately(false /* removeFromApp */, "test");
+ mActivity.destroyImmediately("test");
assertEquals(DESTROYING, mActivity.getState());
}
/**
* Test that the activity will be moved to destroyed state immediately if it was not marked as
- * finishing before {@link ActivityRecord#destroyImmediately(boolean, String)}.
+ * finishing before {@link ActivityRecord#destroyImmediately(String)}.
*/
@Test
public void testDestroyImmediately_hadApp_notFinishing() {
mActivity.finishing = false;
- mActivity.destroyImmediately(false /* removeFromApp */, "test");
+ mActivity.destroyImmediately("test");
assertEquals(DESTROYED, mActivity.getState());
}
/**
* Test that an activity with no process attached and that is marked as finishing will be
- * removed from task when {@link ActivityRecord#destroyImmediately(boolean, String)} is called.
+ * removed from task when {@link ActivityRecord#destroyImmediately(String)} is called.
*/
@Test
public void testDestroyImmediately_noApp_finishing() {
@@ -1277,7 +1277,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mActivity.finishing = true;
final Task task = mActivity.getTask();
- mActivity.destroyImmediately(false /* removeFromApp */, "test");
+ mActivity.destroyImmediately("test");
assertEquals(DESTROYED, mActivity.getState());
assertNull(mActivity.getTask());
@@ -1294,7 +1294,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mActivity.finishing = false;
final Task task = mActivity.getTask();
- mActivity.destroyImmediately(false /* removeFromApp */, "test");
+ mActivity.destroyImmediately("test");
assertEquals(DESTROYED, mActivity.getState());
assertEquals(task, mActivity.getTask());
@@ -1310,7 +1310,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mActivity.safelyDestroy("test");
- verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ verify(mActivity, never()).destroyImmediately(anyString());
}
/**
@@ -1322,7 +1322,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mActivity.safelyDestroy("test");
- verify(mActivity).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ verify(mActivity).destroyImmediately(anyString());
}
@Test
@@ -1655,13 +1655,13 @@ public class ActivityRecordTests extends WindowTestsBase {
assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
.diff(wpc.getRequestedOverrideConfiguration()));
- secondActivity.destroyImmediately(true, "");
+ secondActivity.destroyImmediately("");
assertTrue(wpc.registeredForActivityConfigChanges());
assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
.diff(wpc.getRequestedOverrideConfiguration()));
- firstActivity.destroyImmediately(true, "");
+ firstActivity.destroyImmediately("");
assertTrue(wpc.registeredForActivityConfigChanges());
assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 72899e726b6e..191c33c61aca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -184,7 +184,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
};
activities[0].detachFromProcess();
activities[1].finishing = true;
- activities[1].destroyImmediately(true /* removeFromApp */, "test");
+ activities[1].destroyImmediately("test");
spyOn(wpc);
doReturn(true).when(wpc).isRemoved();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 1e5d92b270d2..81aad972898e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1653,8 +1653,8 @@ public class UsageStatsService extends SystemService implements
// If the calling app is asking about itself, continue, else check for permission.
if (packageName.equals(callingPackage)) {
- final int actualCallingUid = mPackageManagerInternal.getPackageUidInternal(
- callingPackage, 0, userId);
+ final int actualCallingUid = mPackageManagerInternal.getPackageUid(
+ callingPackage, /* flags= */ 0, userId);
if (actualCallingUid != callingUid) {
return false;
}
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 76f8df02465b..229a9aa65166 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -35,6 +35,7 @@ java_test_host {
"cts-install-lib-host",
],
data: [
+ ":com.android.apex.apkrollback.test_v1",
":com.android.apex.cts.shim.v2_prebuilt",
":TestAppAv1",
],
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index 781723985ec5..e5411dee7805 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -47,11 +47,7 @@ import java.util.function.Consumer;
@RunWith(JUnit4.class)
public class StagedInstallInternalTest {
-
- private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
- private static final TestApp TEST_APEX_WITH_APK_V1 = new TestApp("TestApexWithApkV1",
- APK_IN_APEX_TESTAPEX_NAME, 1, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2",
APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex");
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index 53c3b33d9845..ee7320f9a5ef 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -487,6 +487,7 @@ package android.net.wifi {
method @Nullable public String getPassphrase();
method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfig();
method @IntRange(from=0) public int getPriority();
+ method public int getPriorityGroup();
method @Nullable public String getSsid();
method public boolean isAppInteractionRequired();
method public boolean isCredentialSharedWithUser();
@@ -513,6 +514,7 @@ package android.net.wifi {
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriorityGroup(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setUntrusted(boolean);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 68eb1bbd8a79..a3c4ae764612 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -102,10 +102,15 @@ public final class WifiNetworkSuggestion implements Parcelable {
*/
private int mMeteredOverride;
/**
- * Priority of this network among other network suggestions provided by the app.
+ * Priority of this network among other network suggestions from same priority group
+ * provided by the app.
* The lower the number, the higher the priority (i.e value of 0 = highest priority).
*/
private int mPriority;
+ /**
+ * Priority group ID, while suggestion priority will only effect inside the priority group.
+ */
+ private int mPriorityGroup;
/**
* The carrier ID identifies the operator who provides this network configuration.
@@ -165,6 +170,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
mWapiPskPassphrase = null;
mWapiEnterpriseConfig = null;
mIsNetworkUntrusted = false;
+ mPriorityGroup = 0;
}
/**
@@ -329,6 +335,18 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
/**
+ * Set the priority group ID, {@link #setPriority(int)} will only impact the network
+ * suggestions from the same priority group within the same app.
+ *
+ * @param priorityGroup priority group id, if not set default is 0.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ */
+ public @NonNull Builder setPriorityGroup(int priorityGroup) {
+ mPriorityGroup = priorityGroup;
+ return this;
+ }
+
+ /**
* Set the ASCII WAPI passphrase for this network. Needed for authenticating to
* WAPI-PSK networks.
*
@@ -411,8 +429,9 @@ public final class WifiNetworkSuggestion implements Parcelable {
/**
* Specify the priority of this network among other network suggestions provided by the same
- * app (priorities have no impact on suggestions by different apps). The higher the number,
- * the higher the priority (i.e value of 0 = lowest priority).
+ * app (priorities have no impact on suggestions by different apps) and within the same
+ * priority group, see {@link #setPriorityGroup(int)}.
+ * The higher the number, the higher the priority (i.e value of 0 = lowest priority).
* <p>
* <li>If not set, defaults a lower priority than any assigned priority.</li>
*
@@ -696,7 +715,8 @@ public final class WifiNetworkSuggestion implements Parcelable {
mIsAppInteractionRequired,
mIsUserInteractionRequired,
mIsSharedWithUser,
- mIsInitialAutojoinEnabled);
+ mIsInitialAutojoinEnabled,
+ mPriorityGroup);
}
}
@@ -739,6 +759,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
*/
public final boolean isInitialAutoJoinEnabled;
+ /**
+ * Priority group ID.
+ * @hide
+ */
+ public final int priorityGroup;
+
/** @hide */
public WifiNetworkSuggestion() {
this.wifiConfiguration = new WifiConfiguration();
@@ -747,6 +773,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
this.isUserInteractionRequired = false;
this.isUserAllowedToManuallyConnect = true;
this.isInitialAutoJoinEnabled = true;
+ this.priorityGroup = 0;
}
/** @hide */
@@ -755,7 +782,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
boolean isAppInteractionRequired,
boolean isUserInteractionRequired,
boolean isUserAllowedToManuallyConnect,
- boolean isInitialAutoJoinEnabled) {
+ boolean isInitialAutoJoinEnabled, int priorityGroup) {
checkNotNull(networkConfiguration);
this.wifiConfiguration = networkConfiguration;
this.passpointConfiguration = passpointConfiguration;
@@ -764,6 +791,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
this.isUserInteractionRequired = isUserInteractionRequired;
this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect;
this.isInitialAutoJoinEnabled = isInitialAutoJoinEnabled;
+ this.priorityGroup = priorityGroup;
}
public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR =
@@ -776,7 +804,8 @@ public final class WifiNetworkSuggestion implements Parcelable {
in.readBoolean(), // isAppInteractionRequired
in.readBoolean(), // isUserInteractionRequired
in.readBoolean(), // isSharedCredentialWithUser
- in.readBoolean() // isAutojoinEnabled
+ in.readBoolean(), // isAutojoinEnabled
+ in.readInt() // priorityGroup
);
}
@@ -799,6 +828,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
dest.writeBoolean(isUserInteractionRequired);
dest.writeBoolean(isUserAllowedToManuallyConnect);
dest.writeBoolean(isInitialAutoJoinEnabled);
+ dest.writeInt(priorityGroup);
}
@Override
@@ -842,6 +872,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
.append(", isCredentialSharedWithUser=").append(isUserAllowedToManuallyConnect)
.append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled)
.append(", isUnTrusted=").append(!wifiConfiguration.trusted)
+ .append(", priorityGroup=").append(priorityGroup)
.append(" ]");
return sb.toString();
}
@@ -962,4 +993,11 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
return WifiInfo.removeDoubleQuotes(wifiConfiguration.preSharedKey);
}
+
+ /**
+ * @see Builder#setPriorityGroup(int)
+ */
+ public int getPriorityGroup() {
+ return priorityGroup;
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index f0839e9b3122..3744a5183793 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -16,7 +16,12 @@
package android.net.wifi;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
@@ -39,6 +44,8 @@ public class WifiNetworkSuggestionTest {
private static final String TEST_FQDN = "fqdn";
private static final String TEST_WAPI_CERT_SUITE = "suite";
private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";
+ private static final int DEFAULT_PRIORITY_GROUP = 0;
+ private static final int TEST_PRIORITY_GROUP = 1;
/**
* Validate correctness of WifiNetworkSuggestion object created by
@@ -612,7 +619,7 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, true, true, true);
+ configuration, null, false, true, true, true, TEST_PRIORITY_GROUP);
Parcel parcelW = Parcel.obtain();
suggestion.writeToParcel(parcelW, 0);
@@ -683,14 +690,16 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, true, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, true, false, true, true,
+ TEST_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.BSSID = TEST_BSSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, true, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, true, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertEquals(suggestion, suggestion1);
assertEquals(suggestion.hashCode(), suggestion1.hashCode());
@@ -706,13 +715,15 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID_1;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}
@@ -728,13 +739,15 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}
@@ -749,13 +762,15 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, true);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true, true,
+ DEFAULT_PRIORITY_GROUP);
assertNotEquals(suggestion, suggestion1);
}