diff options
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); } |