diff options
119 files changed, 1823 insertions, 3148 deletions
diff --git a/api/current.txt b/api/current.txt index a2f2c060428d..1bd3aa7997b9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -31106,6 +31106,7 @@ package android.net.wifi { public class ScanResult implements android.os.Parcelable { ctor public ScanResult(@NonNull android.net.wifi.ScanResult); + ctor public ScanResult(); method public int describeContents(); method @NonNull public java.util.List<android.net.wifi.ScanResult.InformationElement> getInformationElements(); method public int getWifiStandard(); @@ -31377,6 +31378,15 @@ package android.net.wifi { field public static final int LINK_SPEED_UNKNOWN = -1; // 0xffffffff } + public static final class WifiInfo.Builder { + ctor public WifiInfo.Builder(); + method @NonNull public android.net.wifi.WifiInfo build(); + method @NonNull public android.net.wifi.WifiInfo.Builder setBssid(@NonNull String); + method @NonNull public android.net.wifi.WifiInfo.Builder setNetworkId(int); + method @NonNull public android.net.wifi.WifiInfo.Builder setRssi(int); + method @NonNull public android.net.wifi.WifiInfo.Builder setSsid(@NonNull byte[]); + } + public class WifiManager { method @Deprecated public int addNetwork(android.net.wifi.WifiConfiguration); method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>); @@ -31560,6 +31570,20 @@ package android.net.wifi { public final class WifiNetworkSuggestion implements android.os.Parcelable { method public int describeContents(); + method @Nullable public android.net.MacAddress getBssid(); + method @Nullable public android.net.wifi.WifiEnterpriseConfig getEnterpriseConfig(); + method @Nullable public String getPassphrase(); + method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfig(); + method @IntRange(from=0) public int getPriority(); + method @Nullable public String getSsid(); + method public boolean isAppInteractionRequired(); + method public boolean isCredentialSharedWithUser(); + method public boolean isEnhancedOpen(); + method public boolean isHiddenSsid(); + method public boolean isInitialAutojoinEnabled(); + method public boolean isMetered(); + method public boolean isUntrusted(); + method public boolean isUserInteractionRequired(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSuggestion> CREATOR; } diff --git a/api/system-current.txt b/api/system-current.txt index 3b95f3226341..63bb7d1671e5 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4944,30 +4944,32 @@ package android.media.tv.tuner { package android.media.tv.tuner.dvr { - public class Dvr implements java.lang.AutoCloseable { - ctor protected Dvr(int); + public class DvrPlayback implements java.lang.AutoCloseable { method public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public void close(); method public int configure(@NonNull android.media.tv.tuner.dvr.DvrSettings); method public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public int flush(); + method public long read(long); + method public long read(@NonNull byte[], long, long); method public void setFileDescriptor(@NonNull android.os.ParcelFileDescriptor); method public int start(); method public int stop(); - field public static final int TYPE_PLAYBACK = 1; // 0x1 - field public static final int TYPE_RECORD = 0; // 0x0 - } - - public class DvrPlayback extends android.media.tv.tuner.dvr.Dvr { - method public long read(long); - method public long read(@NonNull byte[], long, long); field public static final int PLAYBACK_STATUS_ALMOST_EMPTY = 2; // 0x2 field public static final int PLAYBACK_STATUS_ALMOST_FULL = 4; // 0x4 field public static final int PLAYBACK_STATUS_EMPTY = 1; // 0x1 field public static final int PLAYBACK_STATUS_FULL = 8; // 0x8 } - public class DvrRecorder extends android.media.tv.tuner.dvr.Dvr { + public class DvrRecorder implements java.lang.AutoCloseable { + method public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method public void close(); + method public int configure(@NonNull android.media.tv.tuner.dvr.DvrSettings); + method public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method public int flush(); + method public void setFileDescriptor(@NonNull android.os.ParcelFileDescriptor); + method public int start(); + method public int stop(); method public long write(long); method public long write(@NonNull byte[], long, long); } @@ -7169,7 +7171,6 @@ package android.net.wifi { } public class ScanResult implements android.os.Parcelable { - ctor public ScanResult(); field public static final int CIPHER_CCMP = 3; // 0x3 field public static final int CIPHER_GCMP_256 = 4; // 0x4 field public static final int CIPHER_NONE = 0; // 0x0 @@ -7314,8 +7315,8 @@ package android.net.wifi { method @Deprecated public int getDisableReasonCounter(int); method @Deprecated public long getDisableTime(); method @Deprecated public static int getMaxNetworkSelectionDisableReason(); - method @Deprecated @Nullable public static String getNetworkDisableReasonString(int); method @Deprecated public int getNetworkSelectionDisableReason(); + method @Deprecated @Nullable public static String getNetworkSelectionDisableReasonString(int); method @Deprecated public int getNetworkSelectionStatus(); method @Deprecated @NonNull public String getNetworkStatusString(); method @Deprecated public boolean hasEverConnected(); @@ -7377,15 +7378,6 @@ package android.net.wifi { field public static final int INVALID_RSSI = -127; // 0xffffff81 } - public static final class WifiInfo.Builder { - ctor public WifiInfo.Builder(); - method @NonNull public android.net.wifi.WifiInfo build(); - method @NonNull public android.net.wifi.WifiInfo.Builder setBssid(@NonNull String); - method @NonNull public android.net.wifi.WifiInfo.Builder setNetworkId(int); - method @NonNull public android.net.wifi.WifiInfo.Builder setRssi(int); - method @NonNull public android.net.wifi.WifiInfo.Builder setSsid(@NonNull byte[]); - } - public class WifiManager { method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoin(int, boolean); @@ -7528,7 +7520,7 @@ package android.net.wifi { } public static interface WifiManager.ScoreChangeCallback { - method public void onScoreChange(int, @NonNull android.net.NetworkScore); + method public void onScoreChange(int, int); method public void onTriggerUpdateOfWifiUsabilityStats(int); } @@ -7554,51 +7546,28 @@ package android.net.wifi { method public void stop(int); } - public class WifiNetworkConnectionStatistics implements android.os.Parcelable { - ctor public WifiNetworkConnectionStatistics(int, int); - ctor public WifiNetworkConnectionStatistics(); - ctor public WifiNetworkConnectionStatistics(android.net.wifi.WifiNetworkConnectionStatistics); - method public int describeContents(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkConnectionStatistics> CREATOR; - field public int numConnection; - field public int numUsage; - } - - public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { - method public boolean satisfiedBy(android.net.NetworkSpecifier); - } - - public final class WifiNetworkSuggestion implements android.os.Parcelable { - method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfiguration(); - method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration(); - } - - public static final class WifiNetworkSuggestion.Builder { - method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int); - } - - public final class WifiOemMigrationHook { - method @Nullable public static android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData loadFromConfigStore(); - method @NonNull public static android.net.wifi.WifiOemMigrationHook.SettingsMigrationData loadFromSettings(@NonNull android.content.Context); + public final class WifiMigration { + method @Nullable public static android.net.wifi.WifiMigration.ConfigStoreMigrationData loadFromConfigStore(); + method @NonNull public static android.net.wifi.WifiMigration.SettingsMigrationData loadFromSettings(@NonNull android.content.Context); + method public static void removeConfigStore(); } - public static final class WifiOemMigrationHook.ConfigStoreMigrationData implements android.os.Parcelable { + public static final class WifiMigration.ConfigStoreMigrationData implements android.os.Parcelable { method public int describeContents(); method @Nullable public java.util.List<android.net.wifi.WifiConfiguration> getUserSavedNetworkConfigurations(); method @Nullable public android.net.wifi.SoftApConfiguration getUserSoftApConfiguration(); method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiMigration.ConfigStoreMigrationData> CREATOR; } - public static final class WifiOemMigrationHook.ConfigStoreMigrationData.Builder { - ctor public WifiOemMigrationHook.ConfigStoreMigrationData.Builder(); - method @NonNull public android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData build(); - method @NonNull public android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData.Builder setUserSavedNetworkConfigurations(@NonNull java.util.List<android.net.wifi.WifiConfiguration>); - method @NonNull public android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData.Builder setUserSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration); + public static final class WifiMigration.ConfigStoreMigrationData.Builder { + ctor public WifiMigration.ConfigStoreMigrationData.Builder(); + method @NonNull public android.net.wifi.WifiMigration.ConfigStoreMigrationData build(); + method @NonNull public android.net.wifi.WifiMigration.ConfigStoreMigrationData.Builder setUserSavedNetworkConfigurations(@NonNull java.util.List<android.net.wifi.WifiConfiguration>); + method @NonNull public android.net.wifi.WifiMigration.ConfigStoreMigrationData.Builder setUserSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration); } - public static final class WifiOemMigrationHook.SettingsMigrationData implements android.os.Parcelable { + public static final class WifiMigration.SettingsMigrationData implements android.os.Parcelable { method public int describeContents(); method @Nullable public String getP2pDeviceName(); method public boolean isP2pFactoryResetPending(); @@ -7608,19 +7577,42 @@ package android.net.wifi { method public boolean isVerboseLoggingEnabled(); method public boolean isWakeUpEnabled(); method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiOemMigrationHook.SettingsMigrationData> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiMigration.SettingsMigrationData> CREATOR; } - public static final class WifiOemMigrationHook.SettingsMigrationData.Builder { - ctor public WifiOemMigrationHook.SettingsMigrationData.Builder(); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData build(); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setP2pDeviceName(@Nullable String); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setP2pFactoryResetPending(boolean); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setScanAlwaysAvailable(boolean); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setScanThrottleEnabled(boolean); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setSoftApTimeoutEnabled(boolean); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setVerboseLoggingEnabled(boolean); - method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setWakeUpEnabled(boolean); + public static final class WifiMigration.SettingsMigrationData.Builder { + ctor public WifiMigration.SettingsMigrationData.Builder(); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData build(); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setP2pDeviceName(@Nullable String); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setP2pFactoryResetPending(boolean); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setScanAlwaysAvailable(boolean); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setScanThrottleEnabled(boolean); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setSoftApTimeoutEnabled(boolean); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setVerboseLoggingEnabled(boolean); + method @NonNull public android.net.wifi.WifiMigration.SettingsMigrationData.Builder setWakeUpEnabled(boolean); + } + + public class WifiNetworkConnectionStatistics implements android.os.Parcelable { + ctor public WifiNetworkConnectionStatistics(int, int); + ctor public WifiNetworkConnectionStatistics(); + ctor public WifiNetworkConnectionStatistics(android.net.wifi.WifiNetworkConnectionStatistics); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkConnectionStatistics> CREATOR; + field public int numConnection; + field public int numUsage; + } + + public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + method public boolean satisfiedBy(android.net.NetworkSpecifier); + } + + public final class WifiNetworkSuggestion implements android.os.Parcelable { + method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration(); + } + + public static final class WifiNetworkSuggestion.Builder { + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int); } public class WifiScanner { @@ -11795,7 +11787,6 @@ package android.telephony { method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAlwaysReportSignalStrength(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull android.telephony.CallForwardingInfo); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean); @@ -11810,7 +11801,6 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, int, boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean); - method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPolicyDataEnabled(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean); diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp index 0b0541fb6221..d4e888fd3119 100644 --- a/cmds/idmap2/idmap2/CreateMultiple.cpp +++ b/cmds/idmap2/idmap2/CreateMultiple.cpp @@ -31,6 +31,7 @@ #include "idmap2/Idmap.h" #include "idmap2/Policies.h" #include "idmap2/SysTrace.h" +#include "Commands.h" using android::ApkAssets; using android::base::StringPrintf; @@ -105,32 +106,34 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) { continue; } - const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); - if (!overlay_apk) { - LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str(); - continue; - } - - const auto idmap = - Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, !ignore_overlayable); - if (!idmap) { - LOG(WARNING) << "failed to create idmap"; - continue; - } - - umask(kIdmapFilePermissionMask); - std::ofstream fout(idmap_path); - if (fout.fail()) { - LOG(WARNING) << "failed to open idmap path " << idmap_path.c_str(); - continue; - } - - BinaryStreamVisitor visitor(fout); - (*idmap)->accept(&visitor); - fout.close(); - if (fout.fail()) { - LOG(WARNING) << "failed to write to idmap path %s" << idmap_path.c_str(); - continue; + if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}))) { + const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); + if (!overlay_apk) { + LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str(); + continue; + } + + const auto idmap = + Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, !ignore_overlayable); + if (!idmap) { + LOG(WARNING) << "failed to create idmap"; + continue; + } + + umask(kIdmapFilePermissionMask); + std::ofstream fout(idmap_path); + if (fout.fail()) { + LOG(WARNING) << "failed to open idmap path " << idmap_path.c_str(); + continue; + } + + BinaryStreamVisitor visitor(fout); + (*idmap)->accept(&visitor); + fout.close(); + if (fout.fail()) { + LOG(WARNING) << "failed to write to idmap path %s" << idmap_path.c_str(); + continue; + } } idmap_paths.emplace_back(idmap_path); diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index d48b35b6f0c8..fb315add36d2 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -215,8 +215,7 @@ public class ActivityTaskManager { public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, boolean animate, Rect initialBounds, boolean showRecents) throws SecurityException { try { - return getService().setTaskWindowingModeSplitScreenPrimary(taskId, createMode, toTop, - animate, initialBounds, showRecents); + return getService().setTaskWindowingModeSplitScreenPrimary(taskId, toTop); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 463c8c9a4528..6f0611e68cda 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -528,29 +528,6 @@ interface IActivityManager { boolean unlockUser(int userid, in byte[] token, in byte[] secret, in IProgressListener listener); void killPackageDependents(in String packageName, int userId); - /** - * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change. - * - * @param dockedBounds The bounds for the docked stack. - * @param tempDockedTaskBounds The temporary bounds for the tasks in the docked stack, which - * might be different from the stack bounds to allow more - * flexibility while resizing, or {@code null} if they should be the - * same as the stack bounds. - * @param tempDockedTaskInsetBounds The temporary bounds for the tasks to calculate the insets. - * When resizing, we usually "freeze" the layout of a task. To - * achieve that, we also need to "freeze" the insets, which - * gets achieved by changing task bounds but not bounds used - * to calculate the insets in this transient state - * @param tempOtherTaskBounds The temporary bounds for the tasks in all other stacks, or - * {@code null} if they should be the same as the stack bounds. - * @param tempOtherTaskInsetBounds Like {@code tempDockedTaskInsetBounds}, but for the other - * stacks. - * @throws RemoteException - */ - @UnsupportedAppUsage - void resizeDockedStack(in Rect dockedBounds, in Rect tempDockedTaskBounds, - in Rect tempDockedTaskInsetBounds, - in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds); @UnsupportedAppUsage void removeStack(int stackId); void makePackageIdle(String packageName, int userId); diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 266a06a7aac4..7c8926341555 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -244,8 +244,7 @@ interface IActivityTaskManager { */ boolean setTaskWindowingMode(int taskId, int windowingMode, boolean toTop); void moveTaskToStack(int taskId, int stackId, boolean toTop); - boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, - boolean animate, in Rect initialBounds, boolean showRecents); + boolean setTaskWindowingModeSplitScreenPrimary(int taskId, boolean toTop); /** * Removes stacks in the input windowing modes from the system if they are of activity type * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED diff --git a/core/java/android/debug/AdbManagerInternal.java b/core/java/android/debug/AdbManagerInternal.java index 0bd9f19f91fe..d730129507d7 100644 --- a/core/java/android/debug/AdbManagerInternal.java +++ b/core/java/android/debug/AdbManagerInternal.java @@ -53,4 +53,14 @@ public abstract class AdbManagerInternal { * Returns the file that contains all of the ADB keys and their last used time. */ public abstract File getAdbTempKeysFile(); + + /** + * Starts adbd for a transport. + */ + public abstract void startAdbdForTransport(byte transportType); + + /** + * Stops adbd for a transport. + */ + public abstract void stopAdbdForTransport(byte transportType); } diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java index 17e0456df156..fcdefac3163b 100644 --- a/core/java/android/service/autofill/InlineSuggestionRenderService.java +++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java @@ -23,16 +23,13 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.Service; import android.app.slice.Slice; -import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; -import android.hardware.display.DisplayManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; -import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.SurfaceControl; @@ -76,35 +73,41 @@ public abstract class InlineSuggestionRenderService extends Service { return; } - final DisplayManager displayManager = getSystemService(DisplayManager.class); - final Display targetDisplay = displayManager.getDisplay(displayId); - if (targetDisplay == null) { - sendResult(callback, /*surface*/ null); - return; - } - final Context displayContext = createDisplayContext(targetDisplay); - - final SurfaceControlViewHost host = new SurfaceControlViewHost(displayContext, - displayContext.getDisplay(), hostInputToken); - final SurfaceControl surface = host.getSurfacePackage().getSurfaceControl(); - - final View suggestionView = onRenderSuggestion(presentation, width, height); - - final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); - suggestionRoot.addView(suggestionView); - suggestionRoot.setOnClickListener((v) -> { - try { - callback.onAutofill(); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException calling onAutofill()"); + // When we create the UI it should be for the IME display + updateDisplay(displayId); + try { + final View suggestionView = onRenderSuggestion(presentation, width, height); + if (suggestionView == null) { + try { + callback.onError(); + } catch (RemoteException e) { + Log.w(TAG, "Null suggestion view returned by renderer"); + } + return; } - }); - WindowManager.LayoutParams lp = - new WindowManager.LayoutParams(width, height, - WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT); - host.addView(suggestionRoot, lp); - sendResult(callback, surface); + final InlineSuggestionRoot suggestionRoot = new InlineSuggestionRoot(this, callback); + suggestionRoot.addView(suggestionView); + WindowManager.LayoutParams lp = + new WindowManager.LayoutParams(width, height, + WindowManager.LayoutParams.TYPE_APPLICATION, 0, + PixelFormat.TRANSPARENT); + + final SurfaceControlViewHost host = new SurfaceControlViewHost(this, getDisplay(), + hostInputToken); + host.addView(suggestionRoot, lp); + suggestionRoot.setOnClickListener((v) -> { + try { + callback.onAutofill(); + } catch (RemoteException e) { + Log.w(TAG, "RemoteException calling onAutofill()"); + } + }); + + sendResult(callback, host.getSurfacePackage().getSurfaceControl()); + } finally { + updateDisplay(Display.DEFAULT_DISPLAY); + } } private void sendResult(@NonNull IInlineSuggestionUiCallback callback, diff --git a/core/java/android/service/controls/Control.java b/core/java/android/service/controls/Control.java index 2d1d0ede62ca..0cffe7180923 100644 --- a/core/java/android/service/controls/Control.java +++ b/core/java/android/service/controls/Control.java @@ -394,6 +394,11 @@ public final class Control implements Parcelable { return this; } + /** + * @param deviceType the device type for the {@link Control}. Setting an invalid value not + * in {@link DeviceTypes} will set it to {@link DeviceTypes#TYPE_UNKNOWN}. + * @return {@code this} + */ @NonNull public StatelessBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) { if (!DeviceTypes.validDeviceType(deviceType)) { @@ -416,6 +421,10 @@ public final class Control implements Parcelable { return this; } + /** + * @param subtitle the user facing subtitle for the {@link Control} + * @return {@code this} + */ @NonNull public StatelessBuilder setSubtitle(@NonNull CharSequence subtitle) { Preconditions.checkNotNull(subtitle); @@ -423,12 +432,22 @@ public final class Control implements Parcelable { return this; } + /** + * @param structure the user facing name of the structure for the {@link Control}. + * {@code null} indicates that it's not associated with any structure. + * @return {@code this} + */ @NonNull public StatelessBuilder setStructure(@Nullable CharSequence structure) { mStructure = structure; return this; } + /** + * @param zone the user facing name of the zone for the {@link Control}. {@code null} + * indicates that it's not associated with any zone. + * @return {@code this} + */ @NonNull public StatelessBuilder setZone(@Nullable CharSequence zone) { mZone = zone; @@ -446,12 +465,20 @@ public final class Control implements Parcelable { return this; } + /** + * @param customIcon an {@link Icon} to override the one determined by the device type. + * @return {@code this} + */ @NonNull public StatelessBuilder setCustomIcon(@Nullable Icon customIcon) { mCustomIcon = customIcon; return this; } + /** + * @param customColor a list of colors to override the ones determined by the device type. + * @return {@code this} + */ @NonNull public StatelessBuilder setCustomColor(@Nullable ColorStateList customColor) { mCustomColor = customColor; @@ -459,7 +486,7 @@ public final class Control implements Parcelable { } /** - * Build a {@link Control} + * Build a stateless {@link Control} * @return a valid {@link Control} */ @NonNull @@ -482,7 +509,7 @@ public final class Control implements Parcelable { /** * Builder class for {@link Control}. * - * This class facilitates the creation of {@link Control}. + * This class facilitates the creation of {@link Control} with an associated state. * It provides the following defaults for non-optional parameters: * <ul> * <li> Device type: {@link DeviceTypes#TYPE_UNKNOWN} @@ -551,6 +578,11 @@ public final class Control implements Parcelable { return this; } + /** + * @param deviceType the device type for the {@link Control}. Setting an invalid value not + * in {@link DeviceTypes} will set it to {@link DeviceTypes#TYPE_UNKNOWN}. + * @return {@code this} + */ @NonNull public StatefulBuilder setDeviceType(@DeviceTypes.DeviceType int deviceType) { if (!DeviceTypes.validDeviceType(deviceType)) { @@ -573,6 +605,10 @@ public final class Control implements Parcelable { return this; } + /** + * @param subtitle the user facing subtitle for the {@link Control} + * @return {@code this} + */ @NonNull public StatefulBuilder setSubtitle(@NonNull CharSequence subtitle) { Preconditions.checkNotNull(subtitle); @@ -580,12 +616,22 @@ public final class Control implements Parcelable { return this; } + /** + * @param structure the user facing name of the structure for the {@link Control}. + * {@code null} indicates that it's not associated with any structure. + * @return {@code this} + */ @NonNull public StatefulBuilder setStructure(@Nullable CharSequence structure) { mStructure = structure; return this; } + /** + * @param zone the user facing name of the zone for the {@link Control}. {@code null} + * indicates that it's not associated with any zone. + * @return {@code this} + */ @NonNull public StatefulBuilder setZone(@Nullable CharSequence zone) { mZone = zone; @@ -603,18 +649,31 @@ public final class Control implements Parcelable { return this; } + /** + * @param customIcon an {@link Icon} to override the one determined by the device type. + * @return {@code this} + */ @NonNull public StatefulBuilder setCustomIcon(@Nullable Icon customIcon) { mCustomIcon = customIcon; return this; } + /** + * @param customColor a list of colors to override the ones determined by the device type. + * @return {@code this} + */ @NonNull public StatefulBuilder setCustomColor(@Nullable ColorStateList customColor) { mCustomColor = customColor; return this; } + /** + * @param status the status of the {@link Control}. Setting an invalid value not in + * {@link Control} will set it to {@link Control#STATUS_UNKNOWN}. + * @return {@code this} + */ @NonNull public StatefulBuilder setStatus(@Status int status) { if (status < 0 || status >= NUM_STATUS) { @@ -626,6 +685,10 @@ public final class Control implements Parcelable { return this; } + /** + * @param controlTemplate a template for the {@link Control} + * @return {@code this} + */ @NonNull public StatefulBuilder setControlTemplate(@NonNull ControlTemplate controlTemplate) { Preconditions.checkNotNull(controlTemplate); @@ -633,6 +696,10 @@ public final class Control implements Parcelable { return this; } + /** + * @param statusText a user facing text representing the status of the {@link Control}. + * @return {@code this} + */ @NonNull public StatefulBuilder setStatusText(@NonNull CharSequence statusText) { Preconditions.checkNotNull(statusText); @@ -640,6 +707,10 @@ public final class Control implements Parcelable { return this; } + /** + * Build a stateless {@link Control} + * @return a valid {@link Control} + */ @NonNull public Control build() { return new Control(mControlId, diff --git a/core/java/android/service/controls/DeviceTypes.java b/core/java/android/service/controls/DeviceTypes.java index 8dbb9cf8f9f7..6594d2cf4ba2 100644 --- a/core/java/android/service/controls/DeviceTypes.java +++ b/core/java/android/service/controls/DeviceTypes.java @@ -21,6 +21,9 @@ import android.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** + * Device types for {@link Control}. + */ public class DeviceTypes { // Update this when adding new concrete types. Does not count TYPE_UNKNOWN diff --git a/core/java/android/service/controls/actions/BooleanAction.java b/core/java/android/service/controls/actions/BooleanAction.java index 02593353bfc8..b794eadf0f90 100644 --- a/core/java/android/service/controls/actions/BooleanAction.java +++ b/core/java/android/service/controls/actions/BooleanAction.java @@ -19,10 +19,15 @@ package android.service.controls.actions; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; +import android.service.controls.Control; +import android.service.controls.templates.ToggleRangeTemplate; import android.service.controls.templates.ToggleTemplate; /** - * Action sent by a {@link ToggleTemplate} + * Action sent by user toggling a {@link Control} between checked/unchecked. + * + * This action is available when the {@link Control} was constructed with either a + * {@link ToggleTemplate} or a {@link ToggleRangeTemplate}. */ public final class BooleanAction extends ControlAction { @@ -40,8 +45,8 @@ public final class BooleanAction extends ControlAction { } /** - * @param templateId the identifier of the {@link ToggleTemplate} that originated this action. - * @param newState new value for the state displayed by the {@link ToggleTemplate}. + * @param templateId the identifier of the template that originated this action. + * @param newState new value for the state displayed by the template. * @param challengeValue a value sent by the user along with the action to authenticate. {@code} * null is sent when no authentication is needed or has not been * requested. @@ -64,8 +69,7 @@ public final class BooleanAction extends ControlAction { /** * The new state set for the button in the corresponding {@link ToggleTemplate}. * - * @return {@code true} if the button was toggled from an {@code off} state to an {@code on} - * state. + * @return {@code true} if the button was toggled from unchecked to checked. */ public boolean getNewState() { return mNewState; diff --git a/core/java/android/service/controls/actions/CommandAction.java b/core/java/android/service/controls/actions/CommandAction.java index 84d60805c3e9..a560fa4268aa 100644 --- a/core/java/android/service/controls/actions/CommandAction.java +++ b/core/java/android/service/controls/actions/CommandAction.java @@ -19,15 +19,32 @@ package android.service.controls.actions; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; +import android.service.controls.Control; +import android.service.controls.templates.StatelessTemplate; +/** + * A simple {@link ControlAction} indicating that the user has interacted with a {@link Control} + * created using a {@link StatelessTemplate}. + */ public final class CommandAction extends ControlAction { private static final @ActionType int TYPE = TYPE_COMMAND; + /** + * @param templateId the identifier of the {@link StatelessTemplate} that originated this + * action. + * @param challengeValue a value sent by the user along with the action to authenticate. {@code} + * null is sent when no authentication is needed or has not been + * requested. + */ public CommandAction(@NonNull String templateId, @Nullable String challengeValue) { super(templateId, challengeValue); } + /** + * @param templateId the identifier of the {@link StatelessTemplate} that originated this + * action. + */ public CommandAction(@NonNull String templateId) { this(templateId, null); } @@ -40,6 +57,9 @@ public final class CommandAction extends ControlAction { super(b); } + /** + * @return {@link ControlAction#TYPE_COMMAND} + */ @Override public int getActionType() { return TYPE; diff --git a/core/java/android/service/controls/actions/ControlAction.java b/core/java/android/service/controls/actions/ControlAction.java index 4141da805b5a..45e63d772d73 100644 --- a/core/java/android/service/controls/actions/ControlAction.java +++ b/core/java/android/service/controls/actions/ControlAction.java @@ -21,6 +21,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; +import android.service.controls.Control; import android.service.controls.IControlsActionCallback; import android.service.controls.templates.ControlTemplate; import android.util.Log; @@ -31,7 +32,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * An abstract action that is executed from a {@link ControlTemplate}. + * An abstract action indicating a user interaction with a {@link Control}. * * The action may have a value to authenticate the input, when the provider has requested it to * complete the action. @@ -58,6 +59,9 @@ public abstract class ControlAction { }) public @interface ActionType {}; + /** + * Object returned when there is an unparcelling error. + */ public static final @NonNull ControlAction ERROR_ACTION = new ControlAction() { @Override public int getActionType() { @@ -65,6 +69,9 @@ public abstract class ControlAction { } }; + /** + * The identifier of {@link #ERROR_ACTION} + */ public static final @ActionType int TYPE_ERROR = -1; /** @@ -77,10 +84,19 @@ public abstract class ControlAction { */ public static final @ActionType int TYPE_FLOAT = 2; + /** + * The identifier of {@link MultiFloatAction}. + */ public static final @ActionType int TYPE_MULTI_FLOAT = 3; + /** + * The identifier of {@link ModeAction}. + */ public static final @ActionType int TYPE_MODE = 4; + /** + * The identifier of {@link CommandAction}. + */ public static final @ActionType int TYPE_COMMAND = 5; diff --git a/core/java/android/service/controls/actions/ModeAction.java b/core/java/android/service/controls/actions/ModeAction.java index ca40974d929b..c0e24adb18f3 100644 --- a/core/java/android/service/controls/actions/ModeAction.java +++ b/core/java/android/service/controls/actions/ModeAction.java @@ -19,7 +19,15 @@ package android.service.controls.actions; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; +import android.service.controls.Control; +import android.service.controls.templates.TemperatureControlTemplate; +/** + * Action sent by the user to indicate a change of mode. + * + * This action is available when the {@link Control} was created with a + * {@link TemperatureControlTemplate}. + */ public final class ModeAction extends ControlAction { private static final @ActionType int TYPE = TYPE_MODE; @@ -27,16 +35,32 @@ public final class ModeAction extends ControlAction { private final int mNewMode; + /** + * @return {@link ControlAction#TYPE_MODE}. + */ @Override public int getActionType() { return TYPE; } + /** + * @param templateId the identifier of the {@link TemperatureControlTemplate} that originated + * this action. + * @param newMode new value for the mode. + * @param challengeValue a value sent by the user along with the action to authenticate. {@code} + * null is sent when no authentication is needed or has not been + * requested. + */ public ModeAction(@NonNull String templateId, int newMode, @Nullable String challengeValue) { super(templateId, challengeValue); mNewMode = newMode; } + /** + * @param templateId the identifier of the {@link TemperatureControlTemplate} that originated + * this action. + * @param newMode new value for the mode. + */ public ModeAction(@NonNull String templateId, int newMode) { this(templateId, newMode, null); } diff --git a/core/java/android/service/controls/templates/ControlTemplate.java b/core/java/android/service/controls/templates/ControlTemplate.java index a5156e36f2ce..30efd80db106 100644 --- a/core/java/android/service/controls/templates/ControlTemplate.java +++ b/core/java/android/service/controls/templates/ControlTemplate.java @@ -57,6 +57,9 @@ public abstract class ControlTemplate { } }; + /** + * Object returned when there is an unparcelling error. + */ public static final @NonNull ControlTemplate ERROR_TEMPLATE = new ControlTemplate("") { @Override public int getTemplateType() { @@ -80,6 +83,9 @@ public abstract class ControlTemplate { }) public @interface TemplateType {} + /** + * Type identifier of {@link #ERROR_TEMPLATE}. + */ public static final @TemplateType int TYPE_ERROR = -1; /** @@ -102,10 +108,19 @@ public abstract class ControlTemplate { */ public static final @TemplateType int TYPE_THUMBNAIL = 3; + /** + * Type identifier of {@link ToggleRangeTemplate}. + */ public static final @TemplateType int TYPE_TOGGLE_RANGE = 6; + /** + * Type identifier of {@link TemperatureControlTemplate}. + */ public static final @TemplateType int TYPE_TEMPERATURE = 7; + /** + * Type identifier of {@link StatelessTemplate}. + */ public static final @TemplateType int TYPE_STATELESS = 8; private @NonNull final String mTemplateId; diff --git a/core/java/android/service/controls/templates/RangeTemplate.java b/core/java/android/service/controls/templates/RangeTemplate.java index fe0d16707c9d..0d977d30f7c1 100644 --- a/core/java/android/service/controls/templates/RangeTemplate.java +++ b/core/java/android/service/controls/templates/RangeTemplate.java @@ -19,7 +19,6 @@ package android.service.controls.templates; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Bundle; -import android.os.Parcel; import android.service.controls.Control; import android.service.controls.actions.FloatAction; @@ -85,7 +84,7 @@ public final class RangeTemplate extends ControlTemplate { } /** - * Construct a new {@link RangeTemplate} from a {@link Parcel}. + * Construct a new {@link RangeTemplate} from a {@link Bundle}. * * @throws IllegalArgumentException if the parameters passed do not make a valid range * @see RangeTemplate#RangeTemplate(String, float, float, float, float, CharSequence) diff --git a/core/java/android/service/controls/templates/StatelessTemplate.java b/core/java/android/service/controls/templates/StatelessTemplate.java index 3f98beac9cf8..c052412f0e4c 100644 --- a/core/java/android/service/controls/templates/StatelessTemplate.java +++ b/core/java/android/service/controls/templates/StatelessTemplate.java @@ -18,22 +18,36 @@ package android.service.controls.templates; import android.annotation.NonNull; import android.os.Bundle; +import android.service.controls.Control; +import android.service.controls.actions.CommandAction; +/** + * A template for a {@link Control} which has no state. + * + * @see CommandAction + */ public final class StatelessTemplate extends ControlTemplate { + /** + * @return {@link ControlTemplate#TYPE_STATELESS} + */ @Override public int getTemplateType() { return TYPE_STATELESS; } /** - * @param b + * Construct a new {@link StatelessTemplate} from a {@link Bundle} * @hide */ StatelessTemplate(@NonNull Bundle b) { super(b); } + /** + * Construct a new {@link StatelessTemplate} + * @param templateId the identifier for this template + */ public StatelessTemplate(@NonNull String templateId) { super(templateId); } diff --git a/core/java/android/service/controls/templates/TemperatureControlTemplate.java b/core/java/android/service/controls/templates/TemperatureControlTemplate.java index 9d8dca6278c5..0818c7e4fb82 100644 --- a/core/java/android/service/controls/templates/TemperatureControlTemplate.java +++ b/core/java/android/service/controls/templates/TemperatureControlTemplate.java @@ -19,6 +19,7 @@ package android.service.controls.templates; import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Bundle; +import android.service.controls.Control; import android.util.Log; import com.android.internal.util.Preconditions; @@ -26,6 +27,13 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** + * A template for a temperature related {@link Control} that supports multiple modes. + * + * Both the current mode and the active mode for the control can be specified. The combination of + * the {@link Control#getDeviceType} and the current and active mode will determine colors and + * transitions for the UI element. + */ public final class TemperatureControlTemplate extends ControlTemplate { private static final String TAG = "ThermostatTemplate"; @@ -51,6 +59,7 @@ public final class TemperatureControlTemplate extends ControlTemplate { public @interface Mode {} private static final int NUM_MODES = 6; + public static final @Mode int MODE_UNKNOWN = 0; public static final @Mode int MODE_OFF = 1; @@ -102,6 +111,18 @@ public final class TemperatureControlTemplate extends ControlTemplate { private final @Mode int mCurrentActiveMode; private final @ModeFlag int mModes; + /** + * Construct a new {@link TemperatureControlTemplate}. + * + * The current and active mode have to be among the ones supported by the flags. + * + * @param templateId the identifier for this template object + * @param controlTemplate a template to use for interaction with the user + * @param currentMode the current mode for the {@link Control} + * @param currentActiveMode the current active mode for the {@link Control} + * @param modesFlag a flag representing the available modes for the {@link Control} + * @throws IllegalArgumentException if the parameters passed do not make a valid template. + */ public TemperatureControlTemplate(@NonNull String templateId, @NonNull ControlTemplate controlTemplate, @Mode int currentMode, @@ -179,6 +200,9 @@ public final class TemperatureControlTemplate extends ControlTemplate { return mModes; } + /** + * @return {@link ControlTemplate#TYPE_TEMPERATURE} + */ @Override public int getTemplateType() { return TYPE; diff --git a/core/java/android/service/controls/templates/ToggleRangeTemplate.java b/core/java/android/service/controls/templates/ToggleRangeTemplate.java index af43b94699d2..cd6a2fc45612 100644 --- a/core/java/android/service/controls/templates/ToggleRangeTemplate.java +++ b/core/java/android/service/controls/templates/ToggleRangeTemplate.java @@ -18,9 +18,16 @@ package android.service.controls.templates; import android.annotation.NonNull; import android.os.Bundle; +import android.service.controls.Control; import com.android.internal.util.Preconditions; +/** + * A template for a {@link Control} supporting toggling and a range. + * + * @see ToggleTemplate + * @see RangeTemplate + */ public final class ToggleRangeTemplate extends ControlTemplate { private static final @TemplateType int TYPE = TYPE_TOGGLE_RANGE; @@ -40,6 +47,12 @@ public final class ToggleRangeTemplate extends ControlTemplate { mRangeTemplate = new RangeTemplate(b.getBundle(KEY_RANGE)); } + /** + * Constructs a new {@link ToggleRangeTemplate}. + * @param templateId the identifier for this template. + * @param button a {@link ControlButton} to use for the toggle interface + * @param range a {@link RangeTemplate} to use for the range interface + */ public ToggleRangeTemplate(@NonNull String templateId, @NonNull ControlButton button, @NonNull RangeTemplate range) { @@ -50,6 +63,14 @@ public final class ToggleRangeTemplate extends ControlTemplate { mRangeTemplate = range; } + /** + * Constructs a new {@link ToggleRangeTemplate}. + * @param templateId the identifier for this template. + * @param checked true if the toggle should be rendered as active. + * @param actionDescription action description for the button. + * @param range {@link RangeTemplate} to use for the range interface + * @see ControlButton + */ public ToggleRangeTemplate(@NonNull String templateId, boolean checked, @NonNull CharSequence actionDescription, @@ -86,6 +107,9 @@ public final class ToggleRangeTemplate extends ControlTemplate { return mControlButton.getActionDescription(); } + /** + * @return {@link ControlTemplate#TYPE_TOGGLE_RANGE} + */ @Override public int getTemplateType() { return TYPE; diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index 530dffbf0620..a60a5cca08bd 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -67,11 +67,6 @@ interface IRecentsAnimationController { void setAnimationTargetsBehindSystemBars(boolean behindSystemBars); /** - * Informs the system that the primary split-screen stack should be minimized. - */ - void setSplitScreenMinimized(boolean minimized); - - /** * Hides the current input method if one is showing. */ void hideCurrentInputMethod(); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 17303478fa50..73601d968040 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -444,8 +444,7 @@ interface IWindowManager WindowContentFrameStats getWindowContentFrameStats(IBinder token); /** - * @return the dock side the current docked stack is at; must be one of the - * WindowManagerGlobal.DOCKED_* values + * This is a no-op. */ @UnsupportedAppUsage int getDockedStackSide(); @@ -457,27 +456,11 @@ interface IWindowManager void setDockedStackDividerTouchRegion(in Rect touchableRegion); /** - * Registers a listener that will be called when the dock divider changes its visibility or when - * the docked stack gets added/removed. - */ - @UnsupportedAppUsage - void registerDockedStackListener(IDockedStackListener listener); - - /** * Registers a listener that will be called when the pinned stack state changes. */ void registerPinnedStackListener(int displayId, IPinnedStackListener listener); /** - * Updates the dim layer used while resizing. - * - * @param visible Whether the dim layer should be visible. - * @param targetWindowingMode The windowing mode of the stack the dim layer should be placed on. - * @param alpha The translucency of the dim layer, between 0 and 1. - */ - void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha); - - /** * Requests Keyboard Shortcuts from the displayed window. * * @param receiver The receiver to deliver the results to. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 11ab5724d927..15d18d145bb0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -29794,7 +29794,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // accessibility CharSequence contentDescription = getContentDescription(); - stream.addProperty("accessibility:contentDescription", + stream.addUserProperty("accessibility:contentDescription", contentDescription == null ? "" : contentDescription.toString()); stream.addProperty("accessibility:labelFor", getLabelFor()); stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 2f44fe039cf5..8a5be75b6c31 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -1209,6 +1209,7 @@ public class ViewDebug { ByteArrayOutputStream baOut = new ByteArrayOutputStream(); final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(baOut); + encoder.setUserPropertiesEnabled(false); encoder.addProperty("window:left", view.mAttachInfo.mWindowLeft); encoder.addProperty("window:top", view.mAttachInfo.mWindowTop); view.encode(encoder); diff --git a/core/java/android/view/ViewHierarchyEncoder.java b/core/java/android/view/ViewHierarchyEncoder.java index b0e0524a0d85..ace05a6b6bf9 100644 --- a/core/java/android/view/ViewHierarchyEncoder.java +++ b/core/java/android/view/ViewHierarchyEncoder.java @@ -66,10 +66,16 @@ public class ViewHierarchyEncoder { private short mPropertyId = 1; private Charset mCharset = Charset.forName("utf-8"); + private boolean mUserPropertiesEnabled = true; + public ViewHierarchyEncoder(@NonNull ByteArrayOutputStream stream) { mStream = new DataOutputStream(stream); } + public void setUserPropertiesEnabled(boolean enabled) { + mUserPropertiesEnabled = enabled; + } + public void beginObject(@NonNull Object o) { startPropertyMap(); addProperty("meta:__name__", o.getClass().getName()); @@ -121,6 +127,17 @@ public class ViewHierarchyEncoder { } /** + * Encodes a user defined property if they are allowed to be encoded + * + * @see #setUserPropertiesEnabled(boolean) + */ + public void addUserProperty(@NonNull String name, @Nullable String s) { + if (mUserPropertiesEnabled) { + addProperty(name, s); + } + } + + /** * Writes the given name as the property name, and leaves it to the callee * to fill in value for this property. */ diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 815cc5cbb10d..f3243aaf5b7d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -13174,7 +13174,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener stream.addProperty("text:selectionStart", getSelectionStart()); stream.addProperty("text:selectionEnd", getSelectionEnd()); stream.addProperty("text:curTextColor", mCurTextColor); - stream.addProperty("text:text", mText == null ? null : mText.toString()); + stream.addUserProperty("text:text", mText == null ? null : mText.toString()); stream.addProperty("text:gravity", mGravity); } diff --git a/core/java/com/android/internal/logging/InstanceIdSequence.java b/core/java/com/android/internal/logging/InstanceIdSequence.java index aa507e538944..34643105b965 100644 --- a/core/java/com/android/internal/logging/InstanceIdSequence.java +++ b/core/java/com/android/internal/logging/InstanceIdSequence.java @@ -25,7 +25,7 @@ import java.security.SecureRandom; import java.util.Random; /** - * Generates random InstanceIds in range [0, instanceIdMax) for passing to + * Generates random InstanceIds in range [1, instanceIdMax] for passing to * UiEventLogger.logWithInstanceId(). Holds a SecureRandom, which self-seeds on * first use; try to give it a long lifetime. Safe for concurrent use. */ @@ -34,12 +34,12 @@ public class InstanceIdSequence { private final Random mRandom = new SecureRandom(); /** - * Constructs a sequence with identifiers [0, instanceIdMax). Capped at INSTANCE_ID_MAX. + * Constructs a sequence with identifiers [1, instanceIdMax]. Capped at INSTANCE_ID_MAX. * @param instanceIdMax Limiting value of identifiers. Normally positive: otherwise you get - * an all-zero sequence. + * an all-1 sequence. */ public InstanceIdSequence(int instanceIdMax) { - mInstanceIdMax = min(max(0, instanceIdMax), InstanceId.INSTANCE_ID_MAX); + mInstanceIdMax = min(max(1, instanceIdMax), InstanceId.INSTANCE_ID_MAX); } /** @@ -47,7 +47,7 @@ public class InstanceIdSequence { * @return new InstanceId */ public InstanceId newInstanceId() { - return newInstanceIdInternal(mRandom.nextInt(mInstanceIdMax)); + return newInstanceIdInternal(1 + mRandom.nextInt(mInstanceIdMax)); } /** diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 08db4544d5e7..e8a0b46e8430 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -167,7 +167,7 @@ message DisplayContentProto { optional WindowContainerProto window_container = 1; optional int32 id = 2; reserved 3; // stacks - optional DockedStackDividerControllerProto docked_stack_divider_controller = 4; + optional DockedStackDividerControllerProto docked_stack_divider_controller = 4 [deprecated=true]; // Will be removed soon. optional PinnedStackControllerProto pinned_stack_controller = 5 [deprecated=true]; /* non app windows */ @@ -229,7 +229,7 @@ message DisplayFramesProto { message DockedStackDividerControllerProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; - optional bool minimized_dock = 1; + optional bool minimized_dock = 1 [deprecated=true]; } /* represents PinnedStackController */ diff --git a/data/etc/com.android.documentsui.xml b/data/etc/com.android.documentsui.xml index 4d9860387b8d..0ffaa21d3254 100644 --- a/data/etc/com.android.documentsui.xml +++ b/data/etc/com.android.documentsui.xml @@ -18,5 +18,6 @@ <privapp-permissions package="com.android.documentsui"> <permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.MODIFY_QUIET_MODE"/> </privapp-permissions> </permissions> diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 73769be3d6ad..7a684b36f460 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -18,11 +18,13 @@ package android.media.tv.tuner; import android.annotation.BytesLong; import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; +import android.hardware.tv.tuner.V1_0.Constants; import android.media.tv.TvInputService; import android.media.tv.tuner.TunerConstants.Result; import android.media.tv.tuner.dvr.DvrPlayback; @@ -45,6 +47,8 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; @@ -67,6 +71,22 @@ public class Tuner implements AutoCloseable { private static final int MSG_ON_FILTER_STATUS = 3; private static final int MSG_ON_LNB_EVENT = 4; + /** @hide */ + @IntDef(prefix = "DVR_TYPE_", value = {DVR_TYPE_RECORD, DVR_TYPE_PLAYBACK}) + @Retention(RetentionPolicy.SOURCE) + public @interface DvrType {} + + /** + * DVR for recording. + * @hide + */ + public static final int DVR_TYPE_RECORD = Constants.DvrType.RECORD; + /** + * DVR for playback of recorded programs. + * @hide + */ + public static final int DVR_TYPE_PLAYBACK = Constants.DvrType.PLAYBACK; + static { System.loadLibrary("media_tv_tuner"); nativeInit(); diff --git a/media/java/android/media/tv/tuner/dvr/Dvr.java b/media/java/android/media/tv/tuner/dvr/Dvr.java deleted file mode 100644 index 4183e3bbe640..000000000000 --- a/media/java/android/media/tv/tuner/dvr/Dvr.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 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 android.media.tv.tuner.dvr; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.SystemApi; -import android.hardware.tv.tuner.V1_0.Constants; -import android.media.tv.tuner.TunerConstants.Result; -import android.media.tv.tuner.filter.Filter; -import android.os.ParcelFileDescriptor; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Digital Video Record (DVR) interface provides record control on Demux's output buffer and - * playback control on Demux's input buffer. - * - * @hide - */ -@SystemApi -public class Dvr implements AutoCloseable { - - /** @hide */ - @IntDef(prefix = "TYPE_", value = {TYPE_RECORD, TYPE_PLAYBACK}) - @Retention(RetentionPolicy.SOURCE) - public @interface Type {} - - /** - * DVR for recording. - */ - public static final int TYPE_RECORD = Constants.DvrType.RECORD; - /** - * DVR for playback of recorded programs. - */ - public static final int TYPE_PLAYBACK = Constants.DvrType.PLAYBACK; - - - final int mType; - long mNativeContext; - - private native int nativeAttachFilter(Filter filter); - private native int nativeDetachFilter(Filter filter); - private native int nativeConfigureDvr(DvrSettings settings); - private native int nativeStartDvr(); - private native int nativeStopDvr(); - private native int nativeFlushDvr(); - private native int nativeClose(); - private native void nativeSetFileDescriptor(int fd); - - protected Dvr(int type) { - mType = type; - } - - /** - * Attaches a filter to DVR interface for recording. - * - * @param filter the filter to be attached. - * @return result status of the operation. - */ - @Result - public int attachFilter(@NonNull Filter filter) { - return nativeAttachFilter(filter); - } - - /** - * Detaches a filter from DVR interface. - * - * @param filter the filter to be detached. - * @return result status of the operation. - */ - @Result - public int detachFilter(@NonNull Filter filter) { - return nativeDetachFilter(filter); - } - - /** - * Configures the DVR. - * - * @param settings the settings of the DVR interface. - * @return result status of the operation. - */ - @Result - public int configure(@NonNull DvrSettings settings) { - return nativeConfigureDvr(settings); - } - - /** - * Starts DVR. - * - * <p>Starts consuming playback data or producing data for recording. - * - * @return result status of the operation. - */ - @Result - public int start() { - return nativeStartDvr(); - } - - /** - * Stops DVR. - * - * <p>Stops consuming playback data or producing data for recording. - * - * @return result status of the operation. - */ - @Result - public int stop() { - return nativeStopDvr(); - } - - /** - * Flushed DVR data. - * - * <p>The data in DVR buffer is cleared. - * - * @return result status of the operation. - */ - @Result - public int flush() { - return nativeFlushDvr(); - } - - /** - * Closes the DVR instance to release resources. - */ - public void close() { - nativeClose(); - } - - /** - * Sets file descriptor to read/write data. - * - * @param fd the file descriptor to read/write data. - */ - public void setFileDescriptor(@NonNull ParcelFileDescriptor fd) { - nativeSetFileDescriptor(fd.getFd()); - } - - @Type - int getType() { - return mType; - } -} diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java index eb3157434a95..7c15bb74a94b 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java +++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java @@ -21,6 +21,9 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.TunerConstants.Result; +import android.media.tv.tuner.filter.Filter; +import android.os.ParcelFileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -33,7 +36,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi -public class DvrPlayback extends Dvr { +public class DvrPlayback implements AutoCloseable { /** @hide */ @@ -66,17 +69,110 @@ public class DvrPlayback extends Dvr { */ public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL; + long mNativeContext; - + private native int nativeAttachFilter(Filter filter); + private native int nativeDetachFilter(Filter filter); + private native int nativeConfigureDvr(DvrSettings settings); + private native int nativeStartDvr(); + private native int nativeStopDvr(); + private native int nativeFlushDvr(); + private native int nativeClose(); + private native void nativeSetFileDescriptor(int fd); private native long nativeRead(long size); private native long nativeRead(byte[] bytes, long offset, long size); private DvrPlayback() { - super(Dvr.TYPE_PLAYBACK); } /** + * Attaches a filter to DVR interface for recording. + * + * @param filter the filter to be attached. + * @return result status of the operation. + */ + @Result + public int attachFilter(@NonNull Filter filter) { + return nativeAttachFilter(filter); + } + + /** + * Detaches a filter from DVR interface. + * + * @param filter the filter to be detached. + * @return result status of the operation. + */ + @Result + public int detachFilter(@NonNull Filter filter) { + return nativeDetachFilter(filter); + } + + /** + * Configures the DVR. + * + * @param settings the settings of the DVR interface. + * @return result status of the operation. + */ + @Result + public int configure(@NonNull DvrSettings settings) { + return nativeConfigureDvr(settings); + } + + /** + * Starts DVR. + * + * <p>Starts consuming playback data or producing data for recording. + * + * @return result status of the operation. + */ + @Result + public int start() { + return nativeStartDvr(); + } + + /** + * Stops DVR. + * + * <p>Stops consuming playback data or producing data for recording. + * + * @return result status of the operation. + */ + @Result + public int stop() { + return nativeStopDvr(); + } + + /** + * Flushed DVR data. + * + * <p>The data in DVR buffer is cleared. + * + * @return result status of the operation. + */ + @Result + public int flush() { + return nativeFlushDvr(); + } + + /** + * Closes the DVR instance to release resources. + */ + @Override + public void close() { + nativeClose(); + } + + /** + * Sets file descriptor to read/write data. + * + * @param fd the file descriptor to read/write data. + */ + public void setFileDescriptor(@NonNull ParcelFileDescriptor fd) { + nativeSetFileDescriptor(fd.getFd()); + } + + /** * Reads data from the file for DVR playback. * * @param size the maximum number of bytes to read. diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java index 3128ca5da641..52ef5e63389f 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java +++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java @@ -19,6 +19,9 @@ package android.media.tv.tuner.dvr; import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.media.tv.tuner.TunerConstants.Result; +import android.media.tv.tuner.filter.Filter; +import android.os.ParcelFileDescriptor; /** * Digital Video Record (DVR) recorder class which provides record control on Demux's output buffer. @@ -26,12 +29,108 @@ import android.annotation.SystemApi; * @hide */ @SystemApi -public class DvrRecorder extends Dvr { +public class DvrRecorder implements AutoCloseable { + long mNativeContext; + + private native int nativeAttachFilter(Filter filter); + private native int nativeDetachFilter(Filter filter); + private native int nativeConfigureDvr(DvrSettings settings); + private native int nativeStartDvr(); + private native int nativeStopDvr(); + private native int nativeFlushDvr(); + private native int nativeClose(); + private native void nativeSetFileDescriptor(int fd); private native long nativeWrite(long size); private native long nativeWrite(byte[] bytes, long offset, long size); private DvrRecorder() { - super(Dvr.TYPE_RECORD); + } + + + /** + * Attaches a filter to DVR interface for recording. + * + * @param filter the filter to be attached. + * @return result status of the operation. + */ + @Result + public int attachFilter(@NonNull Filter filter) { + return nativeAttachFilter(filter); + } + + /** + * Detaches a filter from DVR interface. + * + * @param filter the filter to be detached. + * @return result status of the operation. + */ + @Result + public int detachFilter(@NonNull Filter filter) { + return nativeDetachFilter(filter); + } + + /** + * Configures the DVR. + * + * @param settings the settings of the DVR interface. + * @return result status of the operation. + */ + @Result + public int configure(@NonNull DvrSettings settings) { + return nativeConfigureDvr(settings); + } + + /** + * Starts DVR. + * + * <p>Starts consuming playback data or producing data for recording. + * + * @return result status of the operation. + */ + @Result + public int start() { + return nativeStartDvr(); + } + + /** + * Stops DVR. + * + * <p>Stops consuming playback data or producing data for recording. + * + * @return result status of the operation. + */ + @Result + public int stop() { + return nativeStopDvr(); + } + + /** + * Flushed DVR data. + * + * <p>The data in DVR buffer is cleared. + * + * @return result status of the operation. + */ + @Result + public int flush() { + return nativeFlushDvr(); + } + + /** + * Closes the DVR instance to release resources. + */ + @Override + public void close() { + nativeClose(); + } + + /** + * Sets file descriptor to read/write data. + * + * @param fd the file descriptor to read/write data. + */ + public void setFileDescriptor(@NonNull ParcelFileDescriptor fd) { + nativeSetFileDescriptor(fd.getFd()); } /** diff --git a/media/java/android/media/tv/tuner/dvr/DvrSettings.java b/media/java/android/media/tv/tuner/dvr/DvrSettings.java index f9dc6821039a..362b108e41fd 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrSettings.java +++ b/media/java/android/media/tv/tuner/dvr/DvrSettings.java @@ -30,7 +30,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * DVR settings used to configure {@link Dvr}. + * DVR settings used to configure {@link DvrPlayback} and {@link DvrRecorder}. * * @hide */ diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index a4eada4ebe0b..f39f9124efbb 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -122,6 +122,7 @@ import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -324,6 +325,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt KeyguardDismissUtil keyguardDismissUtil, ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, DismissCallbackRegistry dismissCallbackRegistry, StatusBarTouchableRegionManager statusBarTouchableRegionManager, /* Car Settings injected components. */ @@ -407,6 +409,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt keyguardDismissUtil, extensionController, userInfoControllerImpl, + phoneStatusBarPolicy, dismissCallbackRegistry, statusBarTouchableRegionManager); mUserSwitcherController = userSwitcherController; diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java index 729496580bf6..843e7c55852a 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java @@ -82,6 +82,7 @@ import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -197,6 +198,7 @@ public class CarStatusBarModule { KeyguardDismissUtil keyguardDismissUtil, ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, DismissCallbackRegistry dismissCallbackRegistry, StatusBarTouchableRegionManager statusBarTouchableRegionManager, CarServiceProvider carServiceProvider, @@ -278,6 +280,7 @@ public class CarStatusBarModule { keyguardDismissUtil, extensionController, userInfoControllerImpl, + phoneStatusBarPolicy, dismissCallbackRegistry, statusBarTouchableRegionManager, carServiceProvider, diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 6d11461d6cfa..2297ddf5272b 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -892,9 +892,9 @@ <!-- UI debug setting: enable gpu debug layers summary [CHAR LIMIT=50] --> <string name="enable_gpu_debug_layers_summary">Allow loading GPU debug layers for debug apps</string> - <!-- UI debug setting: enable verbose vendor logging [CHAR LIMIT=30] --> + <!-- UI debug setting: enable verbose vendor logging [CHAR LIMIT=60] --> <string name="enable_verbose_vendor_logging">Enable verbose vendor logging</string> - <!-- UI debug setting: enable verbose vendor logging summary [CHAR LIMIT=100] --> + <!-- UI debug setting: enable verbose vendor logging summary [CHAR LIMIT=NONE] --> <string name="enable_verbose_vendor_logging_summary">Allow additional vendor logs to be included in bug reports, may contain private information</string> <!-- UI debug setting: scaling factor for window animations [CHAR LIMIT=25] --> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java index d23364952357..0e6a60bf47c1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java @@ -68,7 +68,8 @@ public class WifiUtils { for (int reason = 0; reason <= getMaxNetworkSelectionDisableReason(); reason++) { if (networkStatus.getDisableReasonCounter(reason) != 0) { summary.append(" ") - .append(NetworkSelectionStatus.getNetworkDisableReasonString(reason)) + .append(NetworkSelectionStatus + .getNetworkSelectionDisableReasonString(reason)) .append("=") .append(networkStatus.getDisableReasonCounter(reason)); } diff --git a/packages/SystemUI/res/layout/controls_management.xml b/packages/SystemUI/res/layout/controls_management.xml index a7379bedebef..6533c18a41a9 100644 --- a/packages/SystemUI/res/layout/controls_management.xml +++ b/packages/SystemUI/res/layout/controls_management.xml @@ -70,12 +70,14 @@ android:layout_height="match_parent" android:padding="4dp"> - <TextView + <Button + android:id="@+id/other_apps" + android:visibility="gone" android:layout_width="wrap_content" android:layout_height="match_parent" + android:gravity="center_vertical" android:text="See other apps" - android:textAppearance="@style/TextAppearance.Control.Title" - android:textColor="?android:attr/colorPrimary" + style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"/> @@ -85,6 +87,7 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:text="Done" + style="@*android:style/Widget.DeviceDefault.Button.Colored" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"/> diff --git a/packages/SystemUI/res/layout/controls_management_favorites.xml b/packages/SystemUI/res/layout/controls_management_favorites.xml index 62056e60372d..aab32f45e77a 100644 --- a/packages/SystemUI/res/layout/controls_management_favorites.xml +++ b/packages/SystemUI/res/layout/controls_management_favorites.xml @@ -14,97 +14,26 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<androidx.constraintlayout.widget.ConstraintLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView - android:id="@+id/error_message" + android:id="@+id/status_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/controls_management_list_margin" - android:text="@string/controls_favorite_load_error" android:textAppearance="?android:attr/textAppearanceSmall" - android:visibility="gone" android:gravity="center_horizontal" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="parent" - app:layout_constraintBottom_toTopOf="@id/text_favorites" /> - <TextView - android:id="@+id/text_favorites" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/controls_management_list_margin" - android:text="@string/controls_favorite_header_favorites" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textAllCaps="true" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintBottom_toTopOf="@id/divider1" - app:layout_constraintTop_toBottomOf="@id/error_message" - /> - - <View - android:id="@+id/divider1" - android:layout_width="match_parent" - android:layout_height="@dimen/controls_app_divider_height" - android:layout_gravity="center_horizontal|top" - android:background="?android:attr/listDivider" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toTopOf="@id/listFavorites" - app:layout_constraintTop_toBottomOf="@id/text_favorites" - /> - - <androidx.recyclerview.widget.RecyclerView - android:id="@+id/listFavorites" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="@dimen/controls_management_list_margin" - android:nestedScrollingEnabled="false" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toTopOf="@id/text_all" - app:layout_constraintTop_toBottomOf="@id/divider1"/> - - <TextView - android:id="@+id/text_all" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/controls_management_list_margin" - android:text="@string/controls_favorite_header_all" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textAllCaps="true" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintBottom_toTopOf="@id/divider2" - app:layout_constraintTop_toBottomOf="@id/listFavorites" - /> - - <View - android:id="@+id/divider2" - android:layout_width="match_parent" - android:layout_height="@dimen/controls_app_divider_height" - android:layout_gravity="center_horizontal|top" - android:background="?android:attr/listDivider" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toTopOf="@id/listAll" - app:layout_constraintTop_toBottomOf="@id/text_all" - /> - <androidx.recyclerview.widget.RecyclerView android:id="@+id/listAll" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/controls_management_list_margin" - android:nestedScrollingEnabled="false" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@id/divider2"/> + android:nestedScrollingEnabled="false"/> -</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 4fae3c500a45..f8db97dbf800 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -24,7 +24,6 @@ android:layout_width="match_parent" android:layout_height="@dimen/status_bar_height" android:id="@+id/status_bar" - android:background="@drawable/system_bar_background" android:orientation="vertical" android:focusable="false" android:descendantFocusability="afterDescendants" diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 8fee2cf9597e..7142929bab64 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -28,5 +28,6 @@ <FrameLayout android:id="@+id/status_bar_container" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:background="@drawable/system_bar_background" /> </com.android.systemui.statusbar.phone.StatusBarWindowView> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index a49aedfd4caa..8cb0c0225fd9 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -201,6 +201,13 @@ always-on display) --> <string name="doze_brightness_sensor_type" translatable="false"></string> + <!-- Override value to use for proximity sensor. --> + <string name="proximity_sensor_type" translatable="false"></string> + + <!-- If using proximity_sensor_type, specifies a threshold value to distinguish near and + far break points. A sensor value less than this is considered "near". --> + <item name="proximity_sensor_threshold" translatable="false" format="float" type="dimen"></item> + <!-- Doze: pulse parameter - how long does it take to fade in? --> <integer name="doze_pulse_duration_in">130</integer> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 4aafec886a37..ff28b4d289e8 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2614,8 +2614,8 @@ <string name="controls_providers_subtitle">Choose an app from which to add controls</string> <!-- Number of favorites for controls management screen [CHAR LIMIT=NONE]--> <plurals name="controls_number_of_favorites"> - <item quantity="one"><xliff:g id="number" example="1">%s</xliff:g> current favorite.</item> - <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> current favorites.</item> + <item quantity="one"><xliff:g id="number" example="1">%s</xliff:g> control added.</item> + <item quantity="other"><xliff:g id="number" example="3">%s</xliff:g> controls added.</item> </plurals> <!-- Controls management controls screen default title [CHAR LIMIT=30] --> @@ -2626,6 +2626,10 @@ <string name="controls_favorite_header_favorites">Favorites</string> <!-- Controls management controls screen all header [CHAR LIMIT=50] --> <string name="controls_favorite_header_all">All</string> - <!-- Controls management controls screen error on load message [CHAR LIMIT=50] --> + <!-- Controls management controls screen error on load message [CHAR LIMIT=60] --> <string name="controls_favorite_load_error">The list of all controls could not be loaded.</string> + <!-- Controls management controls screen header for Other zone [CHAR LIMIT=60] --> + <string name="controls_favorite_other_zone_header">Other</string> + + </resources> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java index a130092c77d1..49e3e5724988 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java @@ -370,8 +370,7 @@ public class ActivityManagerWrapper { Rect initialBounds) { try { return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId, - createMode, true /* onTop */, false /* animate */, initialBounds, - true /* showRecents */); + true /* onTop */); } catch (RemoteException e) { return false; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java index 6cd6118ede6b..bbb83c73446c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java @@ -61,14 +61,6 @@ public class RecentsAnimationControllerCompat { } } - public void setSplitScreenMinimized(boolean minimized) { - try { - mAnimationController.setSplitScreenMinimized(minimized); - } catch (RemoteException e) { - Log.e(TAG, "Failed to set minimize dock", e); - } - } - public void hideCurrentInputMethod() { try { mAnimationController.hideCurrentInputMethod(); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index e28b1e2806e9..d64bf77ad9d5 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -191,18 +191,6 @@ public class WindowManagerWrapper { } /** - * Registers a docked stack listener with the system. - */ - public void registerDockedStackListener(DockedStackListenerCompat listener) { - try { - WindowManagerGlobal.getWindowManagerService().registerDockedStackListener( - listener.mListener); - } catch (RemoteException e) { - Log.w(TAG, "Failed to register docked stack listener"); - } - } - - /** * Adds a pinned stack listener, which will receive updates from the window manager service * along with any other pinned stack listeners that were added via this method. */ diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 4473b010cbda..dbcdead8de9f 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -20,7 +20,9 @@ import android.app.ActivityManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; +import android.os.Handler; import android.os.HandlerThread; +import android.os.SystemClock; import android.os.Trace; import android.service.wallpaper.WallpaperService; import android.util.Log; @@ -94,18 +96,28 @@ public class ImageWallpaper extends WallpaperService { private EglHelper mEglHelper; private StatusBarStateController mController; private final Runnable mFinishRenderingTask = this::finishRendering; - private final boolean mNeedTransition; private boolean mShouldStopTransition; - @VisibleForTesting - final boolean mIsHighEndGfx; - private final boolean mDisplayNeedsBlanking; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final Object mMonitor = new Object(); + @VisibleForTesting + boolean mIsHighEndGfx; + private boolean mDisplayNeedsBlanking; + private boolean mNeedTransition; private boolean mNeedRedraw; // This variable can only be accessed in synchronized block. private boolean mWaitingForRendering; GLEngine(Context context, DozeParameters dozeParameters) { + init(dozeParameters); + } + + @VisibleForTesting + GLEngine(DozeParameters dozeParameters, Handler handler) { + super(SystemClock::elapsedRealtime, handler); + init(dozeParameters); + } + + private void init(DozeParameters dozeParameters) { mIsHighEndGfx = ActivityManager.isHighEndGfx(); mDisplayNeedsBlanking = dozeParameters.getDisplayNeedsBlanking(); mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking; diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index 10ae3434daaa..f0a82c519d48 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -164,7 +164,7 @@ public final class Prefs { get(context).unregisterOnSharedPreferenceChangeListener(listener); } - private static SharedPreferences get(Context context) { + public static SharedPreferences get(Context context) { return context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 0ac1c1215a28..79b691bb3e37 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -39,6 +39,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.sensors.ProximitySensor; @@ -69,6 +70,7 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { private final DockManager mDockManager; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private Executor mUiBgExecutor; + private final StatusBarStateController mStatusBarStateController; @Inject FalsingManagerProxy(Context context, PluginManager pluginManager, @Main Executor executor, @@ -76,12 +78,14 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { DeviceConfigProxy deviceConfig, DockManager dockManager, KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager, - @UiBackground Executor uiBgExecutor) { + @UiBackground Executor uiBgExecutor, + StatusBarStateController statusBarStateController) { mDisplayMetrics = displayMetrics; mProximitySensor = proximitySensor; mDockManager = dockManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mUiBgExecutor = uiBgExecutor; + mStatusBarStateController = statusBarStateController; mProximitySensor.setTag(PROXIMITY_SENSOR_TAG); mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME); mDeviceConfig = deviceConfig; @@ -143,7 +147,8 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { mKeyguardUpdateMonitor, mProximitySensor, mDeviceConfig, - mDockManager + mDockManager, + mStatusBarStateController ); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index a084ae6ed50f..ec81b9f5a291 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -32,6 +32,8 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.classifier.Classifier; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.sensors.ProximitySensor; @@ -59,6 +61,7 @@ public class BrightLineFalsingManager implements FalsingManager { private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ProximitySensor mProximitySensor; private final DockManager mDockManager; + private final StatusBarStateController mStatusBarStateController; private boolean mSessionStarted; private MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; @@ -88,15 +91,29 @@ public class BrightLineFalsingManager implements FalsingManager { }; private boolean mPreviousResult = false; + private StatusBarStateController.StateListener mStatusBarStateListener = + new StatusBarStateController.StateListener() { + @Override + public void onStateChanged(int newState) { + logDebug("StatusBarState=" + StatusBarState.toShortString(newState)); + mState = newState; + updateSessionActive(); + } + }; + private int mState; + public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider, KeyguardUpdateMonitor keyguardUpdateMonitor, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfigProxy, - DockManager dockManager) { + DockManager dockManager, StatusBarStateController statusBarStateController) { mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDataProvider = falsingDataProvider; mProximitySensor = proximitySensor; mDockManager = dockManager; + mStatusBarStateController = statusBarStateController; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); + mStatusBarStateController.addCallback(mStatusBarStateListener); + mState = mStatusBarStateController.getState(); mMetricsLogger = new MetricsLogger(); mClassifiers = new ArrayList<>(); @@ -116,13 +133,12 @@ public class BrightLineFalsingManager implements FalsingManager { mProximitySensor.register(mSensorEventListener); } - private void unregisterSensors() { mProximitySensor.unregister(mSensorEventListener); } private void sessionStart() { - if (!mSessionStarted && !mShowingAod && mScreenOn) { + if (!mSessionStarted && shouldSessionBeActive()) { logDebug("Starting Session"); mSessionStarted = true; mJustUnlockedWithFace = false; @@ -145,6 +161,19 @@ public class BrightLineFalsingManager implements FalsingManager { } } + + private void updateSessionActive() { + if (shouldSessionBeActive()) { + sessionStart(); + } else { + sessionEnd(); + } + } + + private boolean shouldSessionBeActive() { + return mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod; + } + private void updateInteractionType(@Classifier.InteractionType int type) { logDebug("InteractionType: " + type); mDataProvider.setInteractionType(type); @@ -232,11 +261,7 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void setShowingAod(boolean showingAod) { mShowingAod = showingAod; - if (showingAod) { - sessionEnd(); - } else { - sessionStart(); - } + updateSessionActive(); } @Override @@ -343,13 +368,13 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onScreenTurningOn() { mScreenOn = true; - sessionStart(); + updateSessionActive(); } @Override public void onScreenOff() { mScreenOn = false; - sessionEnd(); + updateSessionActive(); } @@ -421,6 +446,7 @@ public class BrightLineFalsingManager implements FalsingManager { public void cleanup() { unregisterSensors(); mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback); + mStatusBarStateController.removeCallback(mStatusBarStateListener); } static void logDebug(String msg) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt new file mode 100644 index 000000000000..c05351795aed --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt @@ -0,0 +1,114 @@ +/* + * 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.controls.management + +import android.text.TextUtils +import android.util.ArrayMap +import com.android.systemui.controls.ControlStatus +import com.android.systemui.controls.controller.ControlInfo + +/** + * This model is used to show all controls separated by zones. + * + * The model will sort the controls and zones in the following manner: + * * The zones will be sorted in a first seen basis + * * The controls in each zone will be sorted in a first seen basis. + * + * @property controls List of all controls as returned by loading + * @property initialFavoriteIds sorted ids of favorite controls + * @property noZoneString text to use as header for all controls that have blank or `null` zone. + */ +class AllModel( + private val controls: List<ControlStatus>, + initialFavoriteIds: List<String>, + private val emptyZoneString: CharSequence +) : ControlsModel { + + override val favorites: List<ControlInfo.Builder> + get() = favoriteIds.mapNotNull { id -> + val control = controls.firstOrNull { it.control.controlId == id }?.control + control?.let { + ControlInfo.Builder().apply { + controlId = it.controlId + controlTitle = it.title + deviceType = it.deviceType + } + } + } + + private val favoriteIds = initialFavoriteIds.toMutableList() + + override val elements: List<ElementWrapper> = createWrappers(controls) + + override fun changeFavoriteStatus(controlId: String, favorite: Boolean) { + if (favorite) { + favoriteIds.add(controlId) + } else { + favoriteIds.remove(controlId) + } + } + + private fun createWrappers(list: List<ControlStatus>): List<ElementWrapper> { + val map = list.groupByTo(OrderedMap(ArrayMap<CharSequence, MutableList<ControlStatus>>())) { + it.control.zone ?: "" + } + val output = mutableListOf<ElementWrapper>() + var emptyZoneValues: Sequence<ControlWrapper>? = null + for (zoneName in map.orderedKeys) { + val values = map.getValue(zoneName).asSequence().map { ControlWrapper(it) } + if (TextUtils.isEmpty(zoneName)) { + emptyZoneValues = values + } else { + output.add(ZoneNameWrapper(zoneName)) + output.addAll(values) + } + } + // Add controls with empty zone at the end + if (emptyZoneValues != null) { + if (map.size != 1) { + output.add(ZoneNameWrapper(emptyZoneString)) + } + output.addAll(emptyZoneValues) + } + return output + } + + private class OrderedMap<K, V>(private val map: MutableMap<K, V>) : MutableMap<K, V> by map { + + val orderedKeys = mutableListOf<K>() + + override fun put(key: K, value: V): V? { + if (key !in map) { + orderedKeys.add(key) + } + return map.put(key, value) + } + + override fun clear() { + orderedKeys.clear() + map.clear() + } + + override fun remove(key: K): V? { + val removed = map.remove(key) + if (removed != null) { + orderedKeys.remove(key) + } + return removed + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt index ac5e0893b526..25ebc65357ee 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt @@ -116,6 +116,10 @@ class FavoritesRenderer( fun renderFavoritesForComponent(component: ComponentName): String { val qty = favoriteFunction(component) - return resources.getQuantityString(R.plurals.controls_number_of_favorites, qty, qty) + if (qty != 0) { + return resources.getQuantityString(R.plurals.controls_number_of_favorites, qty, qty) + } else { + return "" + } } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index d3cabe67790e..0870a4d179c9 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -42,8 +42,7 @@ private typealias ModelFavoriteChanger = (String, Boolean) -> Unit * @param onlyFavorites set to true to only display favorites instead of all controls */ class ControlAdapter( - private val layoutInflater: LayoutInflater, - private val onlyFavorites: Boolean = false + private val layoutInflater: LayoutInflater ) : RecyclerView.Adapter<Holder>() { companion object { @@ -57,22 +56,21 @@ class ControlAdapter( } } - var modelList: List<ElementWrapper> = emptyList() - private var favoritesModel: FavoriteModel? = null + private var model: ControlsModel? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder { return when (viewType) { TYPE_CONTROL -> { ControlHolder( - layoutInflater.inflate(R.layout.controls_base_item, parent, false).apply { - layoutParams.apply { - width = ViewGroup.LayoutParams.MATCH_PARENT - } - elevation = 15f - }, - { id, favorite -> - favoritesModel?.changeFavoriteStatus(id, favorite) - }) + layoutInflater.inflate(R.layout.controls_base_item, parent, false).apply { + layoutParams.apply { + width = ViewGroup.LayoutParams.MATCH_PARENT + } + elevation = 15f + } + ) { id, favorite -> + model?.changeFavoriteStatus(id, favorite) + } } TYPE_ZONE -> { ZoneHolder(layoutInflater.inflate(R.layout.controls_zone_header, parent, false)) @@ -81,27 +79,26 @@ class ControlAdapter( } } - fun changeFavoritesModel(favoritesModel: FavoriteModel) { - this.favoritesModel = favoritesModel - if (onlyFavorites) { - modelList = favoritesModel.favorites - } else { - modelList = favoritesModel.all - } + fun changeModel(model: ControlsModel) { + this.model = model notifyDataSetChanged() } - override fun getItemCount() = modelList.size + override fun getItemCount() = model?.elements?.size ?: 0 override fun onBindViewHolder(holder: Holder, index: Int) { - holder.bindData(modelList[index]) + model?.let { + holder.bindData(it.elements[index]) + } } override fun getItemViewType(position: Int): Int { - return when (modelList[position]) { - is ZoneNameWrapper -> TYPE_ZONE - is ControlWrapper -> TYPE_CONTROL - } + model?.let { + return when (it.elements.get(position)) { + is ZoneNameWrapper -> TYPE_ZONE + is ControlWrapper -> TYPE_CONTROL + } + } ?: throw IllegalStateException("Getting item type for null model") } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt index af4a977022ae..2c014498fdc2 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt @@ -26,11 +26,9 @@ import android.view.ViewStub import android.widget.Button import android.widget.TextView import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import com.android.systemui.R import com.android.systemui.broadcast.BroadcastDispatcher -import com.android.systemui.controls.controller.ControlInfo import com.android.systemui.controls.controller.ControlsControllerImpl import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.settings.CurrentUserTracker @@ -51,33 +49,10 @@ class ControlsFavoritingActivity @Inject constructor( private lateinit var recyclerViewAll: RecyclerView private lateinit var adapterAll: ControlAdapter - private lateinit var recyclerViewFavorites: RecyclerView - private lateinit var adapterFavorites: ControlAdapter - private lateinit var errorText: TextView + private lateinit var statusText: TextView + private var model: ControlsModel? = null private var component: ComponentName? = null - private var currentModel: FavoriteModel? = null - private var itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback( - /* dragDirs */ ItemTouchHelper.UP - or ItemTouchHelper.DOWN - or ItemTouchHelper.LEFT - or ItemTouchHelper.RIGHT, - /* swipeDirs */0 - ) { - override fun onMove( - recyclerView: RecyclerView, - viewHolder: RecyclerView.ViewHolder, - target: RecyclerView.ViewHolder - ): Boolean { - return currentModel?.onMoveItem( - viewHolder.layoutPosition, target.layoutPosition) != null - } - - override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} - - override fun isItemViewSwipeEnabled() = false - } - private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) { private val startingUser = controller.currentUserId @@ -89,6 +64,10 @@ class ControlsFavoritingActivity @Inject constructor( } } + override fun onBackPressed() { + finish() + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.controls_management) @@ -99,21 +78,27 @@ class ControlsFavoritingActivity @Inject constructor( val app = intent.getCharSequenceExtra(EXTRA_APP) component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME) - errorText = requireViewById(R.id.error_message) + statusText = requireViewById(R.id.status_message) - setUpRecyclerViews() + setUpRecyclerView() requireViewById<TextView>(R.id.title).text = app?.let { it } ?: resources.getText(R.string.controls_favorite_default_title) requireViewById<TextView>(R.id.subtitle).text = resources.getText(R.string.controls_favorite_subtitle) + requireViewById<Button>(R.id.other_apps).apply { + visibility = View.VISIBLE + setOnClickListener { + this@ControlsFavoritingActivity.onBackPressed() + } + } + requireViewById<Button>(R.id.done).setOnClickListener { if (component == null) return@setOnClickListener - val favoritesForStorage = currentModel?.favorites?.map { - with(it.controlStatus.control) { - ControlInfo(component!!, controlId, title, deviceType) - } + val favoritesForStorage = model?.favorites?.map { + it.componentName = component!! + it.build() } if (favoritesForStorage != null) { controller.replaceFavoritesForComponent(component!!, favoritesForStorage) @@ -122,20 +107,22 @@ class ControlsFavoritingActivity @Inject constructor( } component?.let { + statusText.text = resources.getText(com.android.internal.R.string.loading) controller.loadForComponent(it, Consumer { data -> val allControls = data.allControls val favoriteKeys = data.favoritesIds val error = data.errorOnLoad executor.execute { - val favoriteModel = FavoriteModel( - allControls, - favoriteKeys, - allAdapter = adapterAll, - favoritesAdapter = adapterFavorites) - adapterAll.changeFavoritesModel(favoriteModel) - adapterFavorites.changeFavoritesModel(favoriteModel) - currentModel = favoriteModel - errorText.visibility = if (error) View.VISIBLE else View.GONE + val emptyZoneString = resources.getText( + R.string.controls_favorite_other_zone_header) + val model = AllModel(allControls, favoriteKeys, emptyZoneString) + adapterAll.changeModel(model) + this.model = model + if (error) { + statusText.text = resources.getText(R.string.controls_favorite_load_error) + } else { + statusText.visibility = View.GONE + } } }) } @@ -143,7 +130,7 @@ class ControlsFavoritingActivity @Inject constructor( currentUserTracker.startTracking() } - private fun setUpRecyclerViews() { + private fun setUpRecyclerView() { val margin = resources.getDimensionPixelSize(R.dimen.controls_card_margin) val itemDecorator = MarginItemDecorator(margin, margin) val layoutInflater = LayoutInflater.from(applicationContext) @@ -156,14 +143,6 @@ class ControlsFavoritingActivity @Inject constructor( } addItemDecoration(itemDecorator) } - - adapterFavorites = ControlAdapter(layoutInflater, true) - recyclerViewFavorites = requireViewById<RecyclerView>(R.id.listFavorites).apply { - layoutManager = GridLayoutManager(applicationContext, 2) - adapter = adapterFavorites - addItemDecoration(itemDecorator) - } - ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerViewFavorites) } override fun onDestroy() { diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt new file mode 100644 index 000000000000..a995a2ebfd25 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt @@ -0,0 +1,59 @@ +/* + * 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.controls.management + +import com.android.systemui.controls.ControlStatus +import com.android.systemui.controls.controller.ControlInfo + +/** + * Model for using with [ControlAdapter]. + * + * Implementations of this interface provide different views of the controls to show. + */ +interface ControlsModel { + + /** + * List of favorites (builders) in order. + * + * This should be obtained prior to storing the favorites using + * [ControlsController.replaceFavoritesForComponent]. + */ + val favorites: List<ControlInfo.Builder> + + /** + * List of all the elements to display by the corresponding [RecyclerView]. + */ + val elements: List<ElementWrapper> + + /** + * Change the favorite status of a particular control. + */ + fun changeFavoriteStatus(controlId: String, favorite: Boolean) {} + + /** + * Move an item (in elements) from one position to another. + */ + fun onMoveItem(from: Int, to: Int) {} +} + +/** + * Wrapper classes for the different types of elements shown in the [RecyclerView]s in + * [ControlAdapter]. + */ +sealed class ElementWrapper +data class ZoneNameWrapper(val zoneName: CharSequence) : ElementWrapper() +data class ControlWrapper(val controlStatus: ControlStatus) : ElementWrapper()
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt index ad4bdefdff3e..098caf61a873 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt @@ -21,6 +21,7 @@ import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.ViewStub +import android.widget.Button import android.widget.TextView import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -86,6 +87,10 @@ class ControlsProviderSelectorActivity @Inject constructor( requireViewById<TextView>(R.id.subtitle).text = resources.getText(R.string.controls_providers_subtitle) + requireViewById<Button>(R.id.done).setOnClickListener { + this@ControlsProviderSelectorActivity.finishAffinity() + } + currentUserTracker.startTracking() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/FavoriteModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/FavoriteModel.kt index 6bade0aeb998..5c51e3dbe4ac 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/FavoriteModel.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/FavoriteModel.kt @@ -142,12 +142,4 @@ class CharSequenceComparator : Comparator<CharSequence> { else if (p0 != null && p1 == null) return 1 return p0.toString().compareTo(p1.toString()) } -} - -/** - * Wrapper classes for the different types of elements shown in the [RecyclerView]s in - * [ControlsFavoritingActivity]. - */ -sealed class ElementWrapper -data class ZoneNameWrapper(val zoneName: CharSequence) : ElementWrapper() -data class ControlWrapper(val controlStatus: ControlStatus) : ElementWrapper()
\ No newline at end of file +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 7c0033c1d4ec..024378d56edd 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; import android.app.INotificationManager; import android.content.Context; +import android.content.SharedPreferences; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.NightDisplayListener; import android.os.Handler; @@ -34,6 +35,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.util.NotificationMessagingUtil; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.Prefs; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.AlwaysOnDisplayPolicy; @@ -79,6 +81,13 @@ public class DependencyProvider { /** */ @Provides + @Main + public SharedPreferences provideSharePreferences(Context context) { + return Prefs.get(context); + } + + /** */ + @Provides public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) { return new AmbientDisplayConfiguration(context); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java index 3aa14a31a5d9..352ee3304964 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java @@ -209,6 +209,7 @@ public class SystemServicesModule { @Provides @Singleton + @Nullable static TelecomManager provideTelecomManager(Context context) { return context.getSystemService(TelecomManager.class); } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 5da02dc57242..24f505d5a395 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -206,7 +206,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, ConfigurationController configurationController, ActivityStarter activityStarter, KeyguardStateController keyguardStateController, UserManager userManager, TrustManager trustManager, IActivityManager iActivityManager, - TelecomManager telecomManager, MetricsLogger metricsLogger, + @Nullable TelecomManager telecomManager, MetricsLogger metricsLogger, BlurUtils blurUtils, SysuiColorExtractor colorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, @@ -568,13 +568,16 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, @Override public void onPress() { mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU); - Intent intent = mTelecomManager.createLaunchEmergencyDialerIntent(null /* number */); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE, - EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); + if (mTelecomManager != null) { + Intent intent = mTelecomManager.createLaunchEmergencyDialerIntent( + null /* number */); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE, + EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index ebf45a66a23a..9f7b84aa62c1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -53,6 +53,7 @@ import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SysUIToast; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile.BooleanState; @@ -79,6 +80,7 @@ public class DndTile extends QSTileImpl<BooleanState> { private final ZenModeController mController; private final DndDetailAdapter mDetailAdapter; private final ActivityStarter mActivityStarter; + private final SharedPreferences mSharedPreferences; private final BroadcastDispatcher mBroadcastDispatcher; private boolean mListening; @@ -87,10 +89,12 @@ public class DndTile extends QSTileImpl<BooleanState> { @Inject public DndTile(QSHost host, ZenModeController zenModeController, - ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher) { + ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher, + @Main SharedPreferences sharedPreferences) { super(host); mController = zenModeController; mActivityStarter = activityStarter; + mSharedPreferences = sharedPreferences; mDetailAdapter = new DndDetailAdapter(); mBroadcastDispatcher = broadcastDispatcher; broadcastDispatcher.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE)); @@ -111,16 +115,16 @@ public class DndTile extends QSTileImpl<BooleanState> { Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible); } - public static boolean isVisible(Context context) { - return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */); + public static boolean isVisible(SharedPreferences prefs) { + return prefs.getBoolean(Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */); } public static void setCombinedIcon(Context context, boolean combined) { Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined); } - public static boolean isCombinedIcon(Context context) { - return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, + public static boolean isCombinedIcon(SharedPreferences sharedPreferences) { + return sharedPreferences.getBoolean(Prefs.Key.DND_TILE_COMBINED_ICON, false /* defaultValue */); } @@ -301,7 +305,7 @@ public class DndTile extends QSTileImpl<BooleanState> { @Override public boolean isAvailable() { - return isVisible(mContext); + return isVisible(mSharedPreferences); } private final OnSharedPreferenceChangeListener mPrefListener diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 2557226d07bd..5dcb4e3b1fb9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -16,9 +16,9 @@ package com.android.systemui.qs.tiles; -import android.content.Context; import android.content.Intent; import android.content.res.Configuration; +import android.content.res.Resources; import android.provider.Settings; import android.service.quicksettings.Tile; import android.widget.Switch; @@ -81,11 +81,11 @@ public class RotationLockTile extends QSTileImpl<BooleanState> { } public static boolean isCurrentOrientationLockPortrait(RotationLockController controller, - Context context) { + Resources resources) { int lockOrientation = controller.getRotationLockOrientation(); if (lockOrientation == Configuration.ORIENTATION_UNDEFINED) { // Freely rotating device; use current rotation - return context.getResources().getConfiguration().orientation + return resources.getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE; } else { return lockOrientation != Configuration.ORIENTATION_LANDSCAPE; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index f06cd54f7756..3afd5dc31382 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -514,12 +514,17 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset 1, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct)); mScreenshotView.setScaleX(scale); mScreenshotView.setScaleY(scale); + } else { + mScreenshotView.setScaleX(cornerScale); + mScreenshotView.setScaleY(cornerScale); } if (t < xPositionPct) { float xCenter = MathUtils.lerp(startPos.x, finalPos.x, mFastOutSlowIn.getInterpolation(t / xPositionPct)); mScreenshotView.setX(xCenter - width * mScreenshotView.getScaleX() / 2f); + } else { + mScreenshotView.setX(finalPos.x - width * mScreenshotView.getScaleX() / 2f); } float yCenter = MathUtils.lerp(startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t)); @@ -544,6 +549,10 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); + mScreenshotView.setScaleX(cornerScale); + mScreenshotView.setScaleY(cornerScale); + mScreenshotView.setX(finalPos.x - height * cornerScale / 2f); + mScreenshotView.setY(finalPos.y - height * cornerScale / 2f); Rect bounds = new Rect(); mScreenshotView.getBoundsOnScreen(bounds); mDismissButton.setX(bounds.right - mDismissButtonSize / 2f); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 56cdff43e255..27b799bc02a3 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -401,6 +401,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, return; } mMinimized = minimized; + WindowManagerProxy.applyPrimaryFocusable(mSplits, !mMinimized); mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable); updateTouchable(); }); @@ -504,6 +505,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, final boolean wasMinimized = mMinimized; mMinimized = true; setHomeStackResizable(mSplits.mSecondary.isResizable()); + WindowManagerProxy.applyPrimaryFocusable(mSplits, false /* focusable */); if (!inSplitMode()) { // Wasn't in split-mode yet, so enter now. if (DEBUG) { @@ -521,6 +523,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, } void ensureNormalSplit() { + if (mMinimized) { + WindowManagerProxy.applyPrimaryFocusable(mSplits, true /* focusable */); + } if (!inSplitMode()) { // Wasn't in split-mode, so enter now. if (DEBUG) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java index 76857337f73e..167c33abac6e 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java @@ -292,10 +292,23 @@ public class WindowManagerProxy { for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) { wct.setBounds(freeHomeAndRecents.get(i).token, null); } + // Reset focusable to true + wct.setFocusable(tiles.mPrimary.token, true /* focusable */); ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null /* organizer */); } catch (RemoteException e) { Log.w(TAG, "Failed to remove stack: " + e); } } + + static void applyPrimaryFocusable(SplitScreenTaskOrganizer splits, boolean focusable) { + try { + WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.setFocusable(splits.mPrimary.token, focusable); + ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, + null /* organizer */); + } catch (RemoteException e) { + Log.w(TAG, "Error setting focusability: " + e); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 8729e04b2dec..f38d416a6f4c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -44,8 +44,9 @@ import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.NotificationShadeWindowBlurController; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -91,6 +92,7 @@ public class NotificationShadeWindowViewController { private boolean mExpandAnimationRunning; private NotificationStackScrollLayout mStackScrollLayout; private PhoneStatusBarView mStatusBarView; + private PhoneStatusBarTransitions mBarTransitions; private StatusBar mService; private DragDownHelper mDragDownHelper; private boolean mDoubleTapEnabled; @@ -98,6 +100,7 @@ public class NotificationShadeWindowViewController { private boolean mExpandingBelowNotch; private final DockManager mDockManager; private final NotificationPanelViewController mNotificationPanelViewController; + private final SuperStatusBarViewFactory mStatusBarViewFactory; // Used for determining view / touch intersection private int[] mTempLocation = new int[2]; @@ -124,8 +127,9 @@ public class NotificationShadeWindowViewController { ShadeController shadeController, DockManager dockManager, @Nullable NotificationShadeWindowBlurController blurController, - NotificationShadeWindowView statusBarWindowView, - NotificationPanelViewController notificationPanelViewController) { + NotificationShadeWindowView notificationShadeWindowView, + NotificationPanelViewController notificationPanelViewController, + SuperStatusBarViewFactory statusBarViewFactory) { mInjectionInflationController = injectionInflationController; mCoordinator = coordinator; mPulseExpansionHandler = pulseExpansionHandler; @@ -141,11 +145,12 @@ public class NotificationShadeWindowViewController { mDozeLog = dozeLog; mDozeParameters = dozeParameters; mCommandQueue = commandQueue; - mView = statusBarWindowView; + mView = notificationShadeWindowView; mShadeController = shadeController; mDockManager = dockManager; mNotificationPanelViewController = notificationPanelViewController; mBlurController = blurController; + mStatusBarViewFactory = statusBarViewFactory; // This view is not part of the newly inflated expanded status bar. mBrightnessMirror = mView.findViewById(R.id.brightness_mirror); @@ -440,8 +445,18 @@ public class NotificationShadeWindowViewController { } } + public PhoneStatusBarTransitions getBarTransitions() { + return mBarTransitions; + } + public void setStatusBarView(PhoneStatusBarView statusBarView) { mStatusBarView = statusBarView; + if (statusBarView != null && mStatusBarViewFactory != null) { + mBarTransitions = new PhoneStatusBarTransitions( + statusBarView, + mStatusBarViewFactory.getStatusBarWindowView() + .findViewById(R.id.status_bar_container)); + } } public void setService(StatusBar statusBar) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 1ab36c5e3760..14af466a2424 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -16,15 +16,18 @@ package com.android.systemui.statusbar.phone; -import android.app.ActivityManager; +import android.annotation.Nullable; import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.AlarmManager.AlarmClockInfo; +import android.app.IActivityManager; import android.app.SynchronousUserSwitchObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.res.Resources; import android.media.AudioManager; import android.os.Handler; import android.os.RemoteException; @@ -33,13 +36,13 @@ import android.os.UserManager; import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; import android.telecom.TelecomManager; -import android.telephony.TelephonyManager; import android.text.format.DateFormat; import android.util.Log; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dagger.qualifiers.DisplayId; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.qs.tiles.DndTile; import com.android.systemui.qs.tiles.RotationLockTile; @@ -61,10 +64,13 @@ import com.android.systemui.statusbar.policy.RotationLockController.RotationLock import com.android.systemui.statusbar.policy.SensorPrivacyController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.util.time.DateFormatUtil; import java.util.Locale; import java.util.concurrent.Executor; +import javax.inject.Inject; + /** * This class contains all of the policy about which icons are installed in the status bar at boot * time. It goes through the normal API for icons, even though it probably strictly doesn't need to. @@ -82,7 +88,7 @@ public class PhoneStatusBarPolicy private static final String TAG = "PhoneStatusBarPolicy"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - public static final int LOCATION_STATUS_ICON_ID = + static final int LOCATION_STATUS_ICON_ID = com.android.internal.R.drawable.perm_group_location; private final String mSlotCast; @@ -97,20 +103,26 @@ public class PhoneStatusBarPolicy private final String mSlotHeadset; private final String mSlotDataSaver; private final String mSlotLocation; - private final String mSlotMicrophone; - private final String mSlotCamera; private final String mSlotSensorsOff; private final String mSlotScreenRecord; + private final int mDisplayId; + private final SharedPreferences mSharedPreferences; + private final DateFormatUtil mDateFormatUtil; + private final TelecomManager mTelecomManager; + private final AudioManager mAudioManager; - private final Context mContext; private final Handler mHandler = new Handler(); private final CastController mCast; private final HotspotController mHotspot; private final NextAlarmController mNextAlarmController; private final AlarmManager mAlarmManager; private final UserInfoController mUserInfoController; + private final IActivityManager mIActivityManager; private final UserManager mUserManager; private final StatusBarIconController mIconController; + private final CommandQueue mCommandQueue; + private final BroadcastDispatcher mBroadcastDispatcher; + private final Resources mResources; private final RotationLockController mRotationLockController; private final DataSaverController mDataSaver; private final ZenModeController mZenController; @@ -121,10 +133,6 @@ public class PhoneStatusBarPolicy private final SensorPrivacyController mSensorPrivacyController; private final RecordingController mRecordingController; - // Assume it's all good unless we hear otherwise. We don't always seem - // to get broadcasts that it *is* there. - int mSimState = TelephonyManager.SIM_STATE_READY; - private boolean mZenVisible; private boolean mVolumeVisible; private boolean mCurrentUserSetup; @@ -134,47 +142,70 @@ public class PhoneStatusBarPolicy private BluetoothController mBluetooth; private AlarmManager.AlarmClockInfo mNextAlarm; - public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController, + @Inject + public PhoneStatusBarPolicy(StatusBarIconController iconController, CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher, - @UiBackground Executor uiBgExecutor) { - mContext = context; + @UiBackground Executor uiBgExecutor, @Main Resources resources, + CastController castController, HotspotController hotspotController, + BluetoothController bluetoothController, NextAlarmController nextAlarmController, + UserInfoController userInfoController, RotationLockController rotationLockController, + DataSaverController dataSaverController, ZenModeController zenModeController, + DeviceProvisionedController deviceProvisionedController, + KeyguardStateController keyguardStateController, + LocationController locationController, + SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager, + AlarmManager alarmManager, UserManager userManager, AudioManager audioManager, + RecordingController recordingController, + @Nullable TelecomManager telecomManager, @DisplayId int displayId, + @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil) { mIconController = iconController; - mCast = Dependency.get(CastController.class); - mHotspot = Dependency.get(HotspotController.class); - mBluetooth = Dependency.get(BluetoothController.class); - mNextAlarmController = Dependency.get(NextAlarmController.class); - mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - mUserInfoController = Dependency.get(UserInfoController.class); - mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - mRotationLockController = Dependency.get(RotationLockController.class); - mDataSaver = Dependency.get(DataSaverController.class); - mZenController = Dependency.get(ZenModeController.class); - mProvisionedController = Dependency.get(DeviceProvisionedController.class); - mKeyguardStateController = Dependency.get(KeyguardStateController.class); - mLocationController = Dependency.get(LocationController.class); - mSensorPrivacyController = Dependency.get(SensorPrivacyController.class); - mRecordingController = Dependency.get(RecordingController.class); + mCommandQueue = commandQueue; + mBroadcastDispatcher = broadcastDispatcher; + mResources = resources; + mCast = castController; + mHotspot = hotspotController; + mBluetooth = bluetoothController; + mNextAlarmController = nextAlarmController; + mAlarmManager = alarmManager; + mUserInfoController = userInfoController; + mIActivityManager = iActivityManager; + mUserManager = userManager; + mRotationLockController = rotationLockController; + mDataSaver = dataSaverController; + mZenController = zenModeController; + mProvisionedController = deviceProvisionedController; + mKeyguardStateController = keyguardStateController; + mLocationController = locationController; + mSensorPrivacyController = sensorPrivacyController; + mRecordingController = recordingController; mUiBgExecutor = uiBgExecutor; - - mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast); - mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot); - mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth); - mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty); - mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen); - mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume); - mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock); - mSlotManagedProfile = context.getString( + mAudioManager = audioManager; + mTelecomManager = telecomManager; + + mSlotCast = resources.getString(com.android.internal.R.string.status_bar_cast); + mSlotHotspot = resources.getString(com.android.internal.R.string.status_bar_hotspot); + mSlotBluetooth = resources.getString(com.android.internal.R.string.status_bar_bluetooth); + mSlotTty = resources.getString(com.android.internal.R.string.status_bar_tty); + mSlotZen = resources.getString(com.android.internal.R.string.status_bar_zen); + mSlotVolume = resources.getString(com.android.internal.R.string.status_bar_volume); + mSlotAlarmClock = resources.getString(com.android.internal.R.string.status_bar_alarm_clock); + mSlotManagedProfile = resources.getString( com.android.internal.R.string.status_bar_managed_profile); - mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate); - mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset); - mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver); - mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location); - mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone); - mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera); - mSlotSensorsOff = context.getString(com.android.internal.R.string.status_bar_sensors_off); - mSlotScreenRecord = context.getString( + mSlotRotate = resources.getString(com.android.internal.R.string.status_bar_rotate); + mSlotHeadset = resources.getString(com.android.internal.R.string.status_bar_headset); + mSlotDataSaver = resources.getString(com.android.internal.R.string.status_bar_data_saver); + mSlotLocation = resources.getString(com.android.internal.R.string.status_bar_location); + mSlotSensorsOff = resources.getString(com.android.internal.R.string.status_bar_sensors_off); + mSlotScreenRecord = resources.getString( com.android.internal.R.string.status_bar_screen_record); + mDisplayId = displayId; + mSharedPreferences = sharedPreferences; + mDateFormatUtil = dateFormatUtil; + } + + /** Initialize the object after construction. */ + public void init() { // listen for broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); @@ -185,11 +216,11 @@ public class PhoneStatusBarPolicy filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); - broadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler); + mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter, mHandler); // listen for user / profile change. try { - ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG); + mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG); } catch (RemoteException e) { // Ignore } @@ -219,26 +250,26 @@ public class PhoneStatusBarPolicy // hotspot mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot, - mContext.getString(R.string.accessibility_status_bar_hotspot)); + mResources.getString(R.string.accessibility_status_bar_hotspot)); mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled()); // managed profile mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, - mContext.getString(R.string.accessibility_managed_profile)); + mResources.getString(R.string.accessibility_managed_profile)); mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible); // data saver mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver, - context.getString(R.string.accessibility_data_saver_on)); + mResources.getString(R.string.accessibility_data_saver_on)); mIconController.setIconVisibility(mSlotDataSaver, false); mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID, - mContext.getString(R.string.accessibility_location_active)); + mResources.getString(R.string.accessibility_location_active)); mIconController.setIconVisibility(mSlotLocation, false); // sensors off mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off, - mContext.getString(R.string.accessibility_sensors_off_active)); + mResources.getString(R.string.accessibility_sensors_off_active)); mIconController.setIconVisibility(mSlotSensorsOff, mSensorPrivacyController.isSensorPrivacyEnabled()); @@ -259,7 +290,7 @@ public class PhoneStatusBarPolicy mLocationController.addCallback(this); mRecordingController.addCallback(this); - commandQueue.addCallback(this); + mCommandQueue.addCallback(this); } @Override @@ -284,51 +315,17 @@ public class PhoneStatusBarPolicy private String buildAlarmContentDescription() { if (mNextAlarm == null) { - return mContext.getString(R.string.status_bar_alarm); + return mResources.getString(R.string.status_bar_alarm); } - return formatNextAlarm(mNextAlarm, mContext); - } - private static String formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context) { - if (info == null) { - return ""; - } - String skeleton = DateFormat.is24HourFormat( - context, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma"; + String skeleton = mDateFormatUtil.is24HourFormat() ? "EHm" : "Ehma"; String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); - String dateString = DateFormat.format(pattern, info.getTriggerTime()).toString(); + String dateString = DateFormat.format(pattern, mNextAlarm.getTriggerTime()).toString(); - return context.getString(R.string.accessibility_quick_settings_alarm, dateString); - } - - private final void updateSimState(Intent intent) { - String stateExtra = intent.getStringExtra(Intent.EXTRA_SIM_STATE); - if (Intent.SIM_STATE_ABSENT.equals(stateExtra)) { - mSimState = TelephonyManager.SIM_STATE_READY; - } else if (Intent.SIM_STATE_CARD_IO_ERROR.equals(stateExtra)) { - mSimState = TelephonyManager.SIM_STATE_CARD_IO_ERROR; - } else if (Intent.SIM_STATE_CARD_RESTRICTED.equals(stateExtra)) { - mSimState = TelephonyManager.SIM_STATE_CARD_RESTRICTED; - } else if (Intent.SIM_STATE_READY.equals(stateExtra)) { - mSimState = TelephonyManager.SIM_STATE_READY; - } else if (Intent.SIM_STATE_LOCKED.equals(stateExtra)) { - final String lockedReason = - intent.getStringExtra(Intent.EXTRA_SIM_LOCKED_REASON); - if (Intent.SIM_LOCKED_ON_PIN.equals(lockedReason)) { - mSimState = TelephonyManager.SIM_STATE_PIN_REQUIRED; - } else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) { - mSimState = TelephonyManager.SIM_STATE_PUK_REQUIRED; - } else { - mSimState = TelephonyManager.SIM_STATE_NETWORK_LOCKED; - } - } else { - mSimState = TelephonyManager.SIM_STATE_UNKNOWN; - } + return mResources.getString(R.string.accessibility_quick_settings_alarm, dateString); } private final void updateVolumeZen() { - AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - boolean zenVisible = false; int zenIconId = 0; String zenDescription = null; @@ -338,29 +335,29 @@ public class PhoneStatusBarPolicy String volumeDescription = null; int zen = mZenController.getZen(); - if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) { + if (DndTile.isVisible(mSharedPreferences) || DndTile.isCombinedIcon(mSharedPreferences)) { zenVisible = zen != Global.ZEN_MODE_OFF; zenIconId = R.drawable.stat_sys_dnd; - zenDescription = mContext.getString(R.string.quick_settings_dnd_label); + zenDescription = mResources.getString(R.string.quick_settings_dnd_label); } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) { zenVisible = true; zenIconId = R.drawable.stat_sys_dnd; - zenDescription = mContext.getString(R.string.interruption_level_none); + zenDescription = mResources.getString(R.string.interruption_level_none); } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { zenVisible = true; zenIconId = R.drawable.stat_sys_dnd; - zenDescription = mContext.getString(R.string.interruption_level_priority); + zenDescription = mResources.getString(R.string.interruption_level_priority); } if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) { - if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) { + if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) { volumeVisible = true; volumeIconId = R.drawable.stat_sys_ringer_vibrate; - volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate); - } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) { + volumeDescription = mResources.getString(R.string.accessibility_ringer_vibrate); + } else if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) { volumeVisible = true; volumeIconId = R.drawable.stat_sys_ringer_silent; - volumeDescription = mContext.getString(R.string.accessibility_ringer_silent); + volumeDescription = mResources.getString(R.string.accessibility_ringer_silent); } } @@ -395,13 +392,13 @@ public class PhoneStatusBarPolicy private final void updateBluetooth() { int iconId = R.drawable.stat_sys_data_bluetooth_connected; String contentDescription = - mContext.getString(R.string.accessibility_quick_settings_bluetooth_on); + mResources.getString(R.string.accessibility_quick_settings_bluetooth_on); boolean bluetoothVisible = false; if (mBluetooth != null) { if (mBluetooth.isBluetoothConnected() && (mBluetooth.isBluetoothAudioActive() || !mBluetooth.isBluetoothAudioProfileOnly())) { - contentDescription = mContext.getString( + contentDescription = mResources.getString( R.string.accessibility_bluetooth_connected); bluetoothVisible = mBluetooth.isBluetoothEnabled(); } @@ -412,12 +409,10 @@ public class PhoneStatusBarPolicy } private final void updateTTY() { - TelecomManager telecomManager = - (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); - if (telecomManager == null) { + if (mTelecomManager == null) { updateTTY(TelecomManager.TTY_MODE_OFF); } else { - updateTTY(telecomManager.getCurrentTtyMode()); + updateTTY(mTelecomManager.getCurrentTtyMode()); } } @@ -430,7 +425,7 @@ public class PhoneStatusBarPolicy // TTY is on if (DEBUG) Log.v(TAG, "updateTTY: set TTY on"); mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode, - mContext.getString(R.string.accessibility_tty_enabled)); + mResources.getString(R.string.accessibility_tty_enabled)); mIconController.setIconVisibility(mSlotTty, true); } else { // TTY is off @@ -452,7 +447,7 @@ public class PhoneStatusBarPolicy mHandler.removeCallbacks(mRemoveCastIconRunnable); if (isCasting && !mRecordingController.isRecording()) { // screen record has its own icon mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, - mContext.getString(R.string.accessibility_casting)); + mResources.getString(R.string.accessibility_casting)); mIconController.setIconVisibility(mSlotCast, true); } else { // don't turn off the screen-record icon for a few seconds, just to make sure the user @@ -478,7 +473,7 @@ public class PhoneStatusBarPolicy showIcon = true; mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, - mContext.getString(R.string.accessibility_managed_profile)); + mResources.getString(R.string.accessibility_managed_profile)); } else { showIcon = false; } @@ -545,7 +540,7 @@ public class PhoneStatusBarPolicy @Override public void appTransitionStarting(int displayId, long startTime, long duration, boolean forced) { - if (mContext.getDisplayId() == displayId) { + if (mDisplayId == displayId) { updateManagedProfile(); } } @@ -567,14 +562,14 @@ public class PhoneStatusBarPolicy @Override public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) { boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait( - mRotationLockController, mContext); + mRotationLockController, mResources); if (rotationLocked) { if (portrait) { mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait, - mContext.getString(R.string.accessibility_rotation_lock_on_portrait)); + mResources.getString(R.string.accessibility_rotation_lock_on_portrait)); } else { mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape, - mContext.getString(R.string.accessibility_rotation_lock_on_landscape)); + mResources.getString(R.string.accessibility_rotation_lock_on_landscape)); } mIconController.setIconVisibility(mSlotRotate, true); } else { @@ -586,7 +581,7 @@ public class PhoneStatusBarPolicy boolean connected = intent.getIntExtra("state", 0) != 0; boolean hasMic = intent.getIntExtra("microphone", 0) != 0; if (connected) { - String contentDescription = mContext.getString(hasMic + String contentDescription = mResources.getString(hasMic ? R.string.accessibility_status_bar_headset : R.string.accessibility_status_bar_headphones); mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.stat_sys_headset_mic @@ -630,7 +625,6 @@ public class PhoneStatusBarPolicy if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { break; } - updateSimState(intent); break; case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED: updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index e8bc2f58adb4..2052ee6cdac5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -29,23 +29,21 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private static final float ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK = 0.5f; private static final float ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK = 0; - private final PhoneStatusBarView mView; private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mBattery, mClock; + private View mLeftSide, mStatusIcons, mBattery; private Animator mCurrentAnimation; - public PhoneStatusBarTransitions(PhoneStatusBarView view) { - super(view, R.drawable.status_background); - mView = view; - final Resources res = mView.getContext().getResources(); + /** + * @param backgroundView view to apply the background drawable + */ + public PhoneStatusBarTransitions(PhoneStatusBarView statusBarView, View backgroundView) { + super(backgroundView, R.drawable.status_background); + final Resources res = statusBarView.getContext().getResources(); mIconAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); - } - - public void init() { - mLeftSide = mView.findViewById(R.id.status_bar_left_side); - mStatusIcons = mView.findViewById(R.id.statusIcons); - mBattery = mView.findViewById(R.id.battery); + mLeftSide = statusBarView.findViewById(R.id.status_bar_left_side); + mStatusIcons = statusBarView.findViewById(R.id.statusIcons); + mBattery = statusBarView.findViewById(R.id.battery); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index b949e3a5080c..1359f74d0b3a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -53,7 +53,6 @@ public class PhoneStatusBarView extends PanelBar { StatusBar mBar; boolean mIsFullyOpenedPanel = false; - private final PhoneStatusBarTransitions mBarTransitions; private ScrimController mScrimController; private float mMinFraction; private Runnable mHideExpandedRunnable = new Runnable() { @@ -83,15 +82,9 @@ public class PhoneStatusBarView extends PanelBar { public PhoneStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); - - mBarTransitions = new PhoneStatusBarTransitions(this); mCommandQueue = Dependency.get(CommandQueue.class); } - public BarTransitions getBarTransitions() { - return mBarTransitions; - } - public void setBar(StatusBar bar) { mBar = bar; } @@ -102,7 +95,6 @@ public class PhoneStatusBarView extends PanelBar { @Override public void onFinishInflate() { - mBarTransitions.init(); mBattery = findViewById(R.id.battery); mCutoutSpace = findViewById(R.id.cutout_space_view); mCenterIconSpace = findViewById(R.id.centered_icon_area); 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 0d3b09a634e4..b620d17541b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -676,6 +676,7 @@ public class StatusBar extends SystemUI implements DemoMode, KeyguardDismissUtil keyguardDismissUtil, ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, DismissCallbackRegistry dismissCallbackRegistry, StatusBarTouchableRegionManager statusBarTouchableRegionManager) { super(context); @@ -751,6 +752,7 @@ public class StatusBar extends SystemUI implements DemoMode, mKeyguardDismissUtil = keyguardDismissUtil; mExtensionController = extensionController; mUserInfoControllerImpl = userInfoControllerImpl; + mIconPolicy = phoneStatusBarPolicy; mDismissCallbackRegistry = dismissCallbackRegistry; mBubbleExpandListener = @@ -875,8 +877,7 @@ public class StatusBar extends SystemUI implements DemoMode, // end old BaseStatusBar.start(). // Lastly, call to the icon policy to install/update all the icons. - mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCommandQueue, - mBroadcastDispatcher, mUiBgExecutor); + mIconPolicy.init(); mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController); mKeyguardStateController.addCallback(this); @@ -2305,13 +2306,14 @@ public class StatusBar extends SystemUI implements DemoMode, } protected BarTransitions getStatusBarTransitions() { - return mStatusBarView.getBarTransitions(); + return mNotificationShadeWindowViewController.getBarTransitions(); } void checkBarModes() { if (mDemoMode) return; - if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState, - getStatusBarTransitions()); + if (mNotificationShadeWindowViewController != null) { + checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions()); + } mNavigationBarController.checkNavBarModes(mDisplayId); mNoAnimationOnNextBarModeChange = false; } @@ -2329,8 +2331,9 @@ public class StatusBar extends SystemUI implements DemoMode, } private void finishBarAnimations() { - if (mStatusBarView != null) { - mStatusBarView.getBarTransitions().finishAnimations(); + if (mNotificationShadeWindowController != null + && mNotificationShadeWindowViewController.getBarTransitions() != null) { + mNotificationShadeWindowViewController.getBarTransitions().finishAnimations(); } mNavigationBarController.finishBarAnimations(mDisplayId); } @@ -2396,12 +2399,11 @@ public class StatusBar extends SystemUI implements DemoMode, pw.print(" mDozing="); pw.println(mDozing); pw.print(" mWallpaperSupported= "); pw.println(mWallpaperSupported); - if (mStatusBarView != null) { - dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); - } pw.println(" StatusBarWindowView: "); if (mNotificationShadeWindowViewController != null) { mNotificationShadeWindowViewController.dump(fd, pw, args); + dumpBarTransitions(pw, "PhoneStatusBarTransitions", + mNotificationShadeWindowViewController.getBarTransitions()); } pw.println(" mMediaManager: "); @@ -3004,8 +3006,10 @@ public class StatusBar extends SystemUI implements DemoMode, -1; if (barMode != -1) { boolean animate = true; - if (mStatusBarView != null) { - mStatusBarView.getBarTransitions().transitionTo(barMode, animate); + if (mNotificationShadeWindowController != null + && mNotificationShadeWindowViewController.getBarTransitions() != null) { + mNotificationShadeWindowViewController.getBarTransitions().transitionTo( + barMode, animate); } mNavigationBarController.transitionTo(mDisplayId, barMode, animate); } 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 e64f8214bb71..0a4fdc9eb9bc 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 @@ -79,6 +79,7 @@ import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; +import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -193,6 +194,7 @@ public interface StatusBarPhoneModule { KeyguardDismissUtil keyguardDismissUtil, ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, + PhoneStatusBarPolicy phoneStatusBarPolicy, DismissCallbackRegistry dismissCallbackRegistry, StatusBarTouchableRegionManager statusBarTouchableRegionManager) { return new StatusBar( @@ -269,6 +271,7 @@ public interface StatusBarPhoneModule { keyguardDismissUtil, extensionController, userInfoControllerImpl, + phoneStatusBarPolicy, dismissCallbackRegistry, statusBarTouchableRegionManager); } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index b5bede4ad31c..13ba1a3cbf31 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -40,12 +40,11 @@ import javax.inject.Inject; */ public class ProximitySensor { private static final String TAG = "ProxSensor"; - private static final boolean DEBUG = false; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Sensor mSensor; private final AsyncSensorManager mSensorManager; - private final boolean mUsingBrightnessSensor; - private final float mMaxRange; + private final float mThreshold; private List<ProximitySensorListener> mListeners = new ArrayList<>(); private String mTag = null; @VisibleForTesting ProximityEvent mLastEvent; @@ -68,20 +67,27 @@ public class ProximitySensor { public ProximitySensor(@Main Resources resources, AsyncSensorManager sensorManager) { mSensorManager = sensorManager; - Sensor sensor = findBrightnessSensor(resources); + Sensor sensor = findCustomProxSensor(resources); + float threshold = 0; + if (sensor != null) { + try { + threshold = getCustomProxThreshold(resources); + } catch (IllegalStateException e) { + Log.e(TAG, "Can not load custom proximity sensor.", e); + sensor = null; + } + } if (sensor == null) { - mUsingBrightnessSensor = false; sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); - } else { - mUsingBrightnessSensor = true; + if (sensor != null) { + threshold = sensor.getMaximumRange(); + } } + + mThreshold = threshold; + mSensor = sensor; - if (mSensor != null) { - mMaxRange = mSensor.getMaximumRange(); - } else { - mMaxRange = 0; - } } public void setTag(String tag) { @@ -107,9 +113,15 @@ public class ProximitySensor { mPaused = false; registerInternal(); } + /** + * Returns a brightness sensor that can be used for proximity purposes. + */ + private Sensor findCustomProxSensor(Resources resources) { + String sensorType = resources.getString(R.string.proximity_sensor_type); + if (sensorType.isEmpty()) { + return null; + } - private Sensor findBrightnessSensor(Resources resources) { - String sensorType = resources.getString(R.string.doze_brightness_sensor_type); List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL); Sensor sensor = null; for (Sensor s : sensorList) { @@ -123,6 +135,17 @@ public class ProximitySensor { } /** + * Returns a threshold value that can be used along with {@link #findCustomProxSensor} + */ + private float getCustomProxThreshold(Resources resources) { + try { + return resources.getFloat(R.dimen.proximity_sensor_threshold); + } catch (Resources.NotFoundException e) { + throw new IllegalStateException("R.dimen.proximity_sensor_threshold must be set."); + } + } + + /** * Returns true if we are registered with the SensorManager. */ public boolean isRegistered() { @@ -157,7 +180,6 @@ public class ProximitySensor { if (mRegistered || mPaused || mListeners.isEmpty()) { return; } - logDebug("Using brightness sensor? " + mUsingBrightnessSensor); logDebug("Registering sensor listener"); mRegistered = true; mSensorManager.registerListener(mSensorEventListener, mSensor, mSensorDelay); @@ -196,10 +218,7 @@ public class ProximitySensor { } private void onSensorEvent(SensorEvent event) { - boolean near = event.values[0] < mMaxRange; - if (mUsingBrightnessSensor) { - near = event.values[0] == 0; - } + boolean near = event.values[0] < mThreshold; mLastEvent = new ProximityEvent(near, event.timestamp); alertListeners(); } diff --git a/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java b/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java new file mode 100644 index 000000000000..d7c4e93bb26e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/time/DateFormatUtil.java @@ -0,0 +1,40 @@ +/* + * 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.util.time; + +import android.app.ActivityManager; +import android.content.Context; +import android.text.format.DateFormat; + +import javax.inject.Inject; + +/** + * Instantiable wrapper around {@link DateFormat}. + */ +public class DateFormatUtil { + private final Context mContext; + + @Inject + public DateFormatUtil(Context context) { + mContext = context; + } + + /** Returns true if the phone is in 24 hour format. */ + public boolean is24HourFormat() { + return DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java index 689eed9e2a61..678cfd23e3a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java @@ -34,6 +34,7 @@ import android.graphics.Bitmap; import android.graphics.ColorSpace; import android.graphics.Rect; import android.hardware.display.DisplayManagerGlobal; +import android.os.Handler; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -72,6 +73,8 @@ public class ImageWallpaperTest extends SysuiTestCase { private Bitmap mWallpaperBitmap; @Mock private DozeParameters mDozeParam; + @Mock + private Handler mHandler; private CountDownLatch mEventCountdown; @@ -104,7 +107,7 @@ public class ImageWallpaperTest extends SysuiTestCase { return new ImageWallpaper(mDozeParam) { @Override public Engine onCreateEngine() { - return new GLEngine(mMockContext, mDozeParam) { + return new GLEngine(mDozeParam, mHandler) { @Override public Context getDisplayContext() { return mMockContext; @@ -196,5 +199,6 @@ public class ImageWallpaperTest extends SysuiTestCase { when(mSurfaceHolder.getSurfaceFrame()).thenReturn(frame); assertThat(engineSpy.checkIfShouldStopTransition()).isEqualTo(assertion); + // destroy } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 7ac5443d67d0..a36f2c754243 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -86,7 +86,9 @@ public abstract class SysuiTestCase { public void SysuiTeardown() { InstrumentationRegistry.registerInstance(mRealInstrumentation, InstrumentationRegistry.getArguments()); - // Reset the assert's testable looper to null. + if (TestableLooper.get(this) != null) { + TestableLooper.get(this).processAllMessages(); + } disallowTestableLooperAsMainThread(); SystemUIFactory.cleanup(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java index 545d2d4229b3..5b78067ef81a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java @@ -33,7 +33,9 @@ import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerFake; import com.android.systemui.dump.DumpManager; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.DeviceConfigProxyFake; import com.android.systemui.util.concurrency.FakeExecutor; @@ -63,6 +65,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); private DockManager mDockManager = new DockManagerFake(); + private StatusBarStateController mStatusBarStateController = new StatusBarStateControllerImpl(); @Before public void setup() { @@ -83,7 +86,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { public void test_brightLineFalsingManagerDisabled() { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - mDumpManager, mUiBgExecutor); + mDumpManager, mUiBgExecutor, mStatusBarStateController); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); } @@ -94,7 +97,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { mExecutor.runAllReady(); mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - mDumpManager, mUiBgExecutor); + mDumpManager, mUiBgExecutor, mStatusBarStateController); assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); } @@ -102,7 +105,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { public void test_brightLineFalsingManagerToggled() throws InterruptedException { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - mDumpManager, mUiBgExecutor); + mDumpManager, mUiBgExecutor, mStatusBarStateController); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java index 0aaa3b6ad329..8b5cc9abb777 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/BrightLineFalsingManagerTest.java @@ -22,12 +22,16 @@ import static org.mockito.Mockito.verify; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import android.util.DisplayMetrics; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.StatusBarStateControllerImpl; +import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.DeviceConfigProxyFake; import com.android.systemui.util.sensors.ProximitySensor; @@ -40,6 +44,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper public class BrightLineFalsingManagerTest extends SysuiTestCase { @@ -47,6 +52,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private ProximitySensor mProximitySensor; + private SysuiStatusBarStateController mStatusBarStateController; private BrightLineFalsingManager mFalsingManager; @@ -61,8 +67,11 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { FalsingDataProvider falsingDataProvider = new FalsingDataProvider(dm); DeviceConfigProxy deviceConfigProxy = new DeviceConfigProxyFake(); DockManager dockManager = new DockManagerFake(); + mStatusBarStateController = new StatusBarStateControllerImpl(); + mStatusBarStateController.setState(StatusBarState.KEYGUARD); mFalsingManager = new BrightLineFalsingManager(falsingDataProvider, - mKeyguardUpdateMonitor, mProximitySensor, deviceConfigProxy, dockManager); + mKeyguardUpdateMonitor, mProximitySensor, deviceConfigProxy, dockManager, + mStatusBarStateController); } @Test @@ -98,4 +107,12 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase { mFalsingManager.onBouncerHidden(); verify(mProximitySensor).register(any(ProximitySensor.ProximitySensorListener.class)); } + + @Test + public void testUnregisterSensor_StateTransition() { + mFalsingManager.onScreenTurningOn(); + reset(mProximitySensor); + mStatusBarStateController.setState(StatusBarState.SHADE); + verify(mProximitySensor).unregister(any(ProximitySensor.ProximitySensorListener.class)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt new file mode 100644 index 000000000000..68e1ec1d9f1d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt @@ -0,0 +1,192 @@ +/* + * 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.controls.management + +import android.app.PendingIntent +import android.service.controls.Control +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.controls.ControlStatus +import com.android.systemui.controls.controller.ControlInfo +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class AllModelTest : SysuiTestCase() { + + companion object { + private const val EMPTY_STRING = "Other" + } + + @Mock + lateinit var pendingIntent: PendingIntent + + val idPrefix = "controlId" + val favoritesIndices = listOf(7, 3, 1, 9) + val favoritesList = favoritesIndices.map { "controlId$it" } + lateinit var controls: List<ControlStatus> + + lateinit var model: AllModel + + private fun zoneMap(id: Int): String? { + return when (id) { + 10 -> "" + 11 -> null + else -> ((id + 1) % 3).toString() + } + } + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + // controlId0 --> zone = 1 + // controlId1 --> zone = 2, favorite + // controlId2 --> zone = 0 + // controlId3 --> zone = 1, favorite + // controlId4 --> zone = 2 + // controlId5 --> zone = 0 + // controlId6 --> zone = 1 + // controlId7 --> zone = 2, favorite + // controlId8 --> zone = 0 + // controlId9 --> zone = 1, favorite + // controlId10 --> zone = "" + // controlId11 --> zone = null + controls = (0..11).map { + ControlStatus( + Control.StatelessBuilder("$idPrefix$it", pendingIntent) + .setZone(zoneMap(it)) + .build(), + it in favoritesIndices + ) + } + model = AllModel(controls, favoritesList, EMPTY_STRING) + } + + @Test + fun testElements() { + + // Zones are sorted by order of appearance, with empty at the end with special header. + val expected = listOf( + ZoneNameWrapper("1"), + ControlWrapper(controls[0]), + ControlWrapper(controls[3]), + ControlWrapper(controls[6]), + ControlWrapper(controls[9]), + ZoneNameWrapper("2"), + ControlWrapper(controls[1]), + ControlWrapper(controls[4]), + ControlWrapper(controls[7]), + ZoneNameWrapper("0"), + ControlWrapper(controls[2]), + ControlWrapper(controls[5]), + ControlWrapper(controls[8]), + ZoneNameWrapper(EMPTY_STRING), + ControlWrapper(controls[10]), + ControlWrapper(controls[11]) + ) + expected.zip(model.elements).forEachIndexed { index, it -> + assertEquals("Error in item at index $index", it.first, it.second) + } + } + + private fun sameControl(controlInfo: ControlInfo.Builder, control: Control): Boolean { + return controlInfo.controlId == control.controlId && + controlInfo.controlTitle == control.title && + controlInfo.deviceType == control.deviceType + } + + @Test + fun testAllEmpty_noHeader() { + val selected_controls = listOf(controls[10], controls[11]) + val new_model = AllModel(selected_controls, emptyList(), EMPTY_STRING) + val expected = listOf( + ControlWrapper(controls[10]), + ControlWrapper(controls[11]) + ) + + expected.zip(new_model.elements).forEachIndexed { index, it -> + assertEquals("Error in item at index $index", it.first, it.second) + } + } + + @Test + fun testFavorites() { + val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + model.favorites.zip(expectedFavorites).forEach { + assertTrue(sameControl(it.first, it.second)) + } + } + + @Test + fun testAddFavorite() { + val indexToAdd = 6 + model.changeFavoriteStatus("$idPrefix$indexToAdd", true) + + val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + + controls[indexToAdd].control + + model.favorites.zip(expectedFavorites).forEach { + assertTrue(sameControl(it.first, it.second)) + } + } + + @Test + fun testAddFavorite_alreadyThere() { + val indexToAdd = 7 + model.changeFavoriteStatus("$idPrefix$indexToAdd", true) + + val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + + model.favorites.zip(expectedFavorites).forEach { + assertTrue(sameControl(it.first, it.second)) + } + } + + @Test + fun testRemoveFavorite() { + val indexToRemove = 3 + model.changeFavoriteStatus("$idPrefix$indexToRemove", false) + + val expectedFavorites = (favoritesIndices.filterNot { it == indexToRemove }) + .map(controls::get) + .map(ControlStatus::control) + + model.favorites.zip(expectedFavorites).forEach { + assertTrue(sameControl(it.first, it.second)) + } + } + + @Test + fun testRemoveFavorite_notThere() { + val indexToRemove = 4 + model.changeFavoriteStatus("$idPrefix$indexToRemove", false) + + val expectedFavorites = favoritesIndices.map(controls::get).map(ControlStatus::control) + + model.favorites.zip(expectedFavorites).forEach { + assertTrue(sameControl(it.first, it.second)) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java index e917c93597ee..c5b69694bdfa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java @@ -37,8 +37,9 @@ import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.NotificationShadeWindowBlurController; +import com.android.systemui.statusbar.PulseExpansionHandler; +import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -81,6 +82,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { @Mock private NotificationPanelViewController mNotificationPanelViewController; @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private NotificationShadeWindowBlurController mNotificationShadeWindowBlurController; + @Mock private SuperStatusBarViewFactory mStatusBarViewFactory; @Before public void setUp() { @@ -116,7 +118,8 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase { mDockManager, mNotificationShadeWindowBlurController, mView, - mNotificationPanelViewController); + mNotificationPanelViewController, + mStatusBarViewFactory); mController.setupExpandedStatusBar(); mController.setService(mStatusBar); mController.setDragDownHelper(mDragDownHelper); 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 d81b8c2af246..5253e2ca9e42 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 @@ -247,6 +247,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private KeyguardDismissUtil mKeyguardDismissUtil; @Mock private ExtensionController mExtensionController; @Mock private UserInfoControllerImpl mUserInfoControllerImpl; + @Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy; private ShadeController mShadeController; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); private InitController mInitController = new InitController(); @@ -400,6 +401,7 @@ public class StatusBarTest extends SysuiTestCase { mKeyguardDismissUtil, mExtensionController, mUserInfoControllerImpl, + mPhoneStatusBarPolicy, mDismissCallbackRegistry, mStatusBarTouchableRegionManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java index 54cb0b83fc8f..31d884c38f58 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java @@ -20,11 +20,9 @@ import android.content.res.Resources; public class FakeProximitySensor extends ProximitySensor { private boolean mAvailable; - private boolean mPaused; public FakeProximitySensor(Resources resources, AsyncSensorManager sensorManager) { super(resources, sensorManager); - mAvailable = true; } diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java index 7ccb28474604..7aaf9be1fdd2 100644 --- a/services/core/java/com/android/server/adb/AdbService.java +++ b/services/core/java/com/android/server/adb/AdbService.java @@ -144,6 +144,18 @@ public class AdbService extends IAdbManager.Stub { public File getAdbTempKeysFile() { return mDebuggingManager.getAdbTempKeysFile(); } + + @Override + public void startAdbdForTransport(byte transportType) { + FgThread.getHandler().sendMessage(obtainMessage( + AdbService::setAdbdEnabledForTransport, AdbService.this, true, transportType)); + } + + @Override + public void stopAdbdForTransport(byte transportType) { + FgThread.getHandler().sendMessage(obtainMessage( + AdbService::setAdbdEnabledForTransport, AdbService.this, false, transportType)); + } } private void initAdbState() { @@ -437,6 +449,19 @@ public class AdbService extends IAdbManager.Stub { } } + private void setAdbdEnabledForTransport(boolean enable, byte transportType) { + if (transportType == AdbTransportType.USB) { + mIsAdbUsbEnabled = enable; + } else if (transportType == AdbTransportType.WIFI) { + mIsAdbWifiEnabled = enable; + } + if (enable) { + startAdbd(); + } else { + stopAdbd(); + } + } + private void setAdbEnabled(boolean enable, byte transportType) { if (DEBUG) { Slog.d(TAG, "setAdbEnabled(" + enable + "), mIsAdbUsbEnabled=" + mIsAdbUsbEnabled diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 211da0a3e9dc..f408fe749eb4 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -4869,6 +4869,19 @@ public final class ActiveServices { return true; } + if (r.app != null) { + ActiveInstrumentation instr = r.app.getActiveInstrumentation(); + if (instr != null && instr.mHasBackgroundActivityStartsPermission) { + return true; + } + } + + final boolean hasAllowBackgroundActivityStartsToken = r.app != null + ? !r.app.mAllowBackgroundActivityStartsTokens.isEmpty() : false; + if (hasAllowBackgroundActivityStartsToken) { + return true; + } + if (mAm.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid) == PERMISSION_GRANTED) { return true; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index cea3bb83deb0..b2fb53071539 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6515,14 +6515,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds, - Rect tempDockedTaskInsetBounds, - Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) { - mActivityTaskManager.resizeDockedStack(dockedBounds, tempDockedTaskBounds, - tempDockedTaskInsetBounds, tempOtherTaskBounds, tempOtherTaskInsetBounds); - } - - @Override public void positionTaskInStack(int taskId, int stackId, int position) { mActivityTaskManager.positionTaskInStack(taskId, stackId, position); } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index bf797291380a..2941e77fbb67 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2570,8 +2570,6 @@ final class ActivityManagerShellCommand extends ShellCommand { switch (op) { case "move-task": return runStackMoveTask(pw); - case "resize-docked-stack": - return runStackResizeDocked(pw); case "positiontask": return runStackPositionTask(pw); case "list": @@ -2646,17 +2644,6 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - int runStackResizeDocked(PrintWriter pw) throws RemoteException { - final Rect bounds = getBounds(); - final Rect taskBounds = getBounds(); - if (bounds == null || taskBounds == null) { - getErrPrintWriter().println("Error: invalid input bounds"); - return -1; - } - mTaskInterface.resizeDockedStack(bounds, taskBounds, null, null, null); - return 0; - } - int runStackPositionTask(PrintWriter pw) throws RemoteException { String taskIdStr = getNextArgRequired(); int taskId = Integer.parseInt(taskIdStr); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e5b8403d2d8d..76bc36620c85 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4178,13 +4178,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final DisplayContent displayContent = getDisplayContent(); if (!displayContent.mClosingApps.contains(this) && !displayContent.mOpeningApps.contains(this)) { - // The token is not closing nor opening, so even if there is an animation set, that - // doesn't mean that it goes through the normal app transition cycle so we have - // to inform the docked controller about visibility change. - // TODO(multi-display): notify docked divider on all displays where visibility was - // affected. - displayContent.getDockedDividerController().notifyAppVisibilityChanged(); - // Take the screenshot before possibly hiding the WSA, otherwise the screenshot // will not be taken. mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index ff890ff13ee3..598389b1ba2b 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -17,8 +17,6 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; -import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT; -import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; @@ -39,16 +37,10 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; -import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.INVALID_DISPLAY; -import static android.view.WindowManager.DOCKED_BOTTOM; -import static android.view.WindowManager.DOCKED_INVALID; -import static android.view.WindowManager.DOCKED_LEFT; -import static android.view.WindowManager.DOCKED_RIGHT; -import static android.view.WindowManager.DOCKED_TOP; import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; @@ -98,13 +90,8 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; -import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.TaskProto.ACTIVITIES; import static com.android.server.wm.TaskProto.ACTIVITY_TYPE; -import static com.android.server.wm.TaskProto.ADJUSTED_BOUNDS; -import static com.android.server.wm.TaskProto.ADJUSTED_FOR_IME; -import static com.android.server.wm.TaskProto.ADJUST_DIVIDER_AMOUNT; -import static com.android.server.wm.TaskProto.ADJUST_IME_AMOUNT; import static com.android.server.wm.TaskProto.ANIMATING_BOUNDS; import static com.android.server.wm.TaskProto.BOUNDS; import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER; @@ -113,7 +100,6 @@ import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS; import static com.android.server.wm.TaskProto.DISPLAY_ID; import static com.android.server.wm.TaskProto.FILLS_PARENT; import static com.android.server.wm.TaskProto.LAST_NON_FULLSCREEN_BOUNDS; -import static com.android.server.wm.TaskProto.MINIMIZE_AMOUNT; import static com.android.server.wm.TaskProto.MIN_HEIGHT; import static com.android.server.wm.TaskProto.MIN_WIDTH; import static com.android.server.wm.TaskProto.ORIG_ACTIVITY; @@ -168,7 +154,6 @@ import android.util.Log; import android.util.Slog; import android.util.proto.ProtoOutputStream; import android.view.Display; -import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.ITaskOrganizer; import android.view.SurfaceControl; @@ -177,8 +162,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.logging.MetricsLoggerWrapper; -import com.android.internal.policy.DividerSnapAlgorithm; -import com.android.internal.policy.DockedDividerUtils; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; @@ -238,13 +221,6 @@ class ActivityStack extends Task { /** Stack is completely invisible. */ static final int STACK_VISIBILITY_INVISIBLE = 2; - /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to - * restrict IME adjustment so that a min portion of top stack remains visible.*/ - private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f; - - /** Dimming amount for non-focused stack when stacks are IME-adjusted. */ - private static final float IME_ADJUST_DIM_AMOUNT = 0.25f; - enum ActivityState { INITIALIZING, STARTED, @@ -294,28 +270,10 @@ class ActivityStack extends Task { /** For Pinned stack controlling. */ private Rect mTmpToBounds = new Rect(); - /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */ - private final Rect mAdjustedBounds = new Rect(); - - /** - * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they - * represent the state when the animation has ended. - */ - private final Rect mFullyAdjustedImeBounds = new Rect(); - /** Detach this stack from its display when animation completes. */ // TODO: maybe tie this to WindowContainer#removeChild some how... private boolean mDeferRemoval; - private final Rect mTmpAdjustedBounds = new Rect(); - private boolean mAdjustedForIme; - private boolean mImeGoingAway; - private WindowState mImeWin; - private float mMinimizeAmount; - private float mAdjustImeAmount; - private float mAdjustDividerAmount; - private final int mDockedStackMinimizeThickness; - // If this is true, we are in the bounds animating mode. The task will be down or upscaled to // perfectly fit the region it would have been cropped to. We may also avoid certain logic we // would otherwise apply while resizing, while resizing in the bounds animating mode. @@ -643,8 +601,6 @@ class ActivityStack extends Task { _realActivitySuspended, userSetupComplete, minWidth, minHeight, info, _voiceSession, _voiceInteractor, stack); - mDockedStackMinimizeThickness = mWmService.mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_minimize_thickness); EventLogTags.writeWmStackCreated(id); mHandler = new ActivityStackHandler(mStackSupervisor.mLooper); mCurrentUser = mAtmService.mAmInternal.getCurrentUserId(); @@ -1202,8 +1158,8 @@ class ActivityStack extends Task { @Override boolean isFocusable() { - return super.isFocusable() && !(inSplitScreenPrimaryWindowingMode() - && mRootWindowContainer.mIsDockMinimized); + // Special check for tile which isn't really in the hierarchy + return mTile != null ? mTile.isFocusable() : super.isFocusable(); } boolean isTopActivityFocusable() { @@ -3497,43 +3453,6 @@ class ActivityStack extends Task { forAllLeafTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */); } - /** - * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from - * the normal task bounds. - * - * @param bounds The adjusted bounds. - */ - private void setAdjustedBounds(Rect bounds) { - if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) { - return; - } - - mAdjustedBounds.set(bounds); - final boolean adjusted = !mAdjustedBounds.isEmpty(); - Rect insetBounds = null; - if (adjusted && isAdjustedForMinimizedDockedStack()) { - insetBounds = getRawBounds(); - } else if (adjusted && mAdjustedForIme) { - if (mImeGoingAway) { - insetBounds = getRawBounds(); - } else { - insetBounds = mFullyAdjustedImeBounds; - } - } - - if (!matchParentBounds()) { - final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP; - final PooledConsumer c = PooledLambda.obtainConsumer(Task::alignToAdjustedBounds, - PooledLambda.__(Task.class), adjusted ? mAdjustedBounds : getRawBounds(), - insetBounds, alignBottom); - forAllLeafTasks(c, true /* traverseTopToBottom */); - c.recycle(); - } - - mDisplayContent.setLayoutNeeded(); - updateSurfaceBounds(); - } - @Override public int setBounds(Rect bounds) { // Calling Task#setBounds() for leaf task since this is the a specialization of @@ -3552,8 +3471,6 @@ class ActivityStack extends Task { final int result = super.setBounds(!inMultiWindowMode() ? null : bounds); - updateAdjustedBounds(); - updateSurfaceBounds(); return result; } @@ -3575,19 +3492,6 @@ class ActivityStack extends Task { bounds.set(getBounds()); } - @Override - public Rect getBounds() { - // If we're currently adjusting for IME or minimized docked stack, we use the adjusted - // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked - // stack is visible since it is already what we want to represent to the rest of the - // system. - if (!mAdjustedBounds.isEmpty()) { - return mAdjustedBounds; - } else { - return super.getBounds(); - } - } - /** * @return the final bounds for the bounds animation. */ @@ -3620,113 +3524,6 @@ class ActivityStack extends Task { } /** - * Updates the passed-in {@code inOutBounds} based on the current state of the - * docked controller. This gets run *after* the override configuration is updated, so it's - * safe to rely on the controller's state in here (though eventually this dependence should - * be removed). - * - * This does NOT modify this TaskStack's configuration. However, it does, for the time-being, - * update docked controller state. - * - * @param parentConfig the parent configuration for reference. - * @param inOutBounds the bounds to update (both input and output). - */ - void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) { - final boolean primary = - getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; - repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds); - final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout; - snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds); - if (primary) { - final int newDockSide = getDockSide(parentConfig, inOutBounds); - // Update the dock create mode and clear the dock create bounds, these - // might change after a rotation and the original values will be invalid. - mWmService.setDockedStackCreateStateLocked( - (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP) - ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT - : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, - null); - mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide); - } - } - - /** - * Some primary split screen sides are not allowed by the policy. This method queries the policy - * and moves the primary stack around if needed. - * - * @param parentConfig the configuration of the stack's parent. - * @param primary true if adjusting the primary docked stack, false for secondary. - * @param inOutBounds the bounds of the stack to adjust. - */ - void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary, - Rect inOutBounds) { - final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds); - final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide); - final int primaryDockSide = primary ? dockSide : otherDockSide; - if (mDisplayContent.getDockedDividerController() - .canPrimaryStackDockTo(primaryDockSide, - parentConfig.windowConfiguration.getBounds(), - parentConfig.windowConfiguration.getRotation())) { - return; - } - final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); - switch (otherDockSide) { - case DOCKED_LEFT: - int movement = inOutBounds.left; - inOutBounds.left -= movement; - inOutBounds.right -= movement; - break; - case DOCKED_RIGHT: - movement = parentBounds.right - inOutBounds.right; - inOutBounds.left += movement; - inOutBounds.right += movement; - break; - case DOCKED_TOP: - movement = inOutBounds.top; - inOutBounds.top -= movement; - inOutBounds.bottom -= movement; - break; - case DOCKED_BOTTOM: - movement = parentBounds.bottom - inOutBounds.bottom; - inOutBounds.top += movement; - inOutBounds.bottom += movement; - break; - } - } - - /** - * Snaps the bounds after rotation to the closest snap target for the docked stack. - */ - void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout, - Rect outBounds) { - - // Calculate the current position. - final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth(); - final int dockSide = getDockSide(parentConfig, outBounds); - final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds, - dockSide, dividerSize); - final int displayWidth = parentConfig.windowConfiguration.getBounds().width(); - final int displayHeight = parentConfig.windowConfiguration.getBounds().height(); - - // Snap the position to a target. - final int rotation = parentConfig.windowConfiguration.getRotation(); - final int orientation = parentConfig.orientation; - mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, displayWidth, displayHeight, - displayCutout, outBounds); - final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm( - mWmService.mContext.getResources(), displayWidth, displayHeight, - dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds, - getDockSide(), isMinimizedDockAndHomeStackResizable()); - final DividerSnapAlgorithm.SnapTarget target = - algorithm.calculateNonDismissingSnapTarget(dividerPosition); - - // Recalculate the bounds based on the position of the target. - DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide, - outBounds, displayWidth, displayHeight, - dividerSize); - } - - /** * Put a Task in this stack. Used for adding only. * When task is added to top of the stack, the entire branch of the hierarchy (including stack * and display) will be brought to top. @@ -3916,445 +3713,8 @@ class ActivityStack extends Task { } } - /** - * Determines the stack and task bounds of the other stack when in docked mode. The current task - * bounds is passed in but depending on the stack, the task and stack must match. Only in - * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds - * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds - * is calculated and is also used for its task bounds. - * If any of the out bounds are empty, it represents default bounds - * - * @param currentTempTaskBounds the current task bounds of the other stack - * @param outStackBounds the calculated stack bounds of the other stack - * @param outTempTaskBounds the calculated task bounds of the other stack - */ - void getStackDockedModeBounds(Rect dockedBounds, - Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) { - final Configuration parentConfig = getParent().getConfiguration(); - outTempTaskBounds.setEmpty(); - - if (dockedBounds == null || dockedBounds.isEmpty()) { - // Calculate the primary docked bounds. - final boolean dockedOnTopOrLeft = mWmService.mDockedStackCreateMode - == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; - getStackDockedModeBounds(parentConfig, - true /* primary */, outStackBounds, dockedBounds, - mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft); - return; - } - final int dockedSide = getDockSide(parentConfig, dockedBounds); - - // When the home stack is resizable, should always have the same stack and task bounds - if (isActivityTypeHome()) { - final Task homeTask = getTopMostTask(); - if (homeTask == null || homeTask.isResizeable()) { - // Calculate the home stack bounds when in docked mode and the home stack is - // resizeable. - getDisplayContent().mDividerControllerLocked - .getHomeStackBoundsInDockedMode(parentConfig, - dockedSide, outStackBounds); - } else { - // Home stack isn't resizeable, so don't specify stack bounds. - outStackBounds.setEmpty(); - } - - outTempTaskBounds.set(outStackBounds); - return; - } - - // When minimized state, the stack bounds for all non-home and docked stack bounds should - // match the passed task bounds - if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) { - outStackBounds.set(currentTempTaskBounds); - return; - } - - if (dockedSide == DOCKED_INVALID) { - // Not sure how you got here...Only thing we can do is return current bounds. - Slog.e(TAG_WM, "Failed to get valid docked side for docked stack"); - outStackBounds.set(getRawBounds()); - return; - } - - final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT; - getStackDockedModeBounds(parentConfig, - false /* primary */, outStackBounds, dockedBounds, - mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft); - } - - /** - * Outputs the bounds a stack should be given the presence of a docked stack on the display. - * @param parentConfig The parent configuration. - * @param primary {@code true} if getting the primary stack bounds. - * @param outBounds Output bounds that should be used for the stack. - * @param dockedBounds Bounds of the docked stack. - * @param dockDividerWidth We need to know the width of the divider make to the output bounds - * close to the side of the dock. - * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen. - */ - private void getStackDockedModeBounds(Configuration parentConfig, boolean primary, - Rect outBounds, Rect dockedBounds, int dockDividerWidth, - boolean dockOnTopOrLeft) { - final Rect displayRect = parentConfig.windowConfiguration.getBounds(); - final boolean splitHorizontally = displayRect.width() > displayRect.height(); - - outBounds.set(displayRect); - if (primary) { - if (mWmService.mDockedStackCreateBounds != null) { - outBounds.set(mWmService.mDockedStackCreateBounds); - return; - } - - // The initial bounds of the docked stack when it is created about half the screen space - // and its bounds can be adjusted after that. The bounds of all other stacks are - // adjusted to occupy whatever screen space the docked stack isn't occupying. - final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout; - mDisplayContent.getDisplayPolicy().getStableInsetsLw( - parentConfig.windowConfiguration.getRotation(), - displayRect.width(), displayRect.height(), displayCutout, mTmpRect2); - final int position = new DividerSnapAlgorithm(mWmService.mContext.getResources(), - displayRect.width(), - displayRect.height(), - dockDividerWidth, - parentConfig.orientation == ORIENTATION_PORTRAIT, - mTmpRect2).getMiddleTarget().position; - - if (dockOnTopOrLeft) { - if (splitHorizontally) { - outBounds.right = position; - } else { - outBounds.bottom = position; - } - } else { - if (splitHorizontally) { - outBounds.left = position + dockDividerWidth; - } else { - outBounds.top = position + dockDividerWidth; - } - } - return; - } - - // Other stacks occupy whatever space is left by the docked stack. - if (!dockOnTopOrLeft) { - if (splitHorizontally) { - outBounds.right = dockedBounds.left - dockDividerWidth; - } else { - outBounds.bottom = dockedBounds.top - dockDividerWidth; - } - } else { - if (splitHorizontally) { - outBounds.left = dockedBounds.right + dockDividerWidth; - } else { - outBounds.top = dockedBounds.bottom + dockDividerWidth; - } - } - DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft); - } - - void resetDockedStackToMiddle() { - if (!inSplitScreenPrimaryWindowingMode()) { - throw new IllegalStateException("Not a docked stack=" + this); - } - - mWmService.mDockedStackCreateBounds = null; - - final Rect bounds = new Rect(); - final Rect tempBounds = new Rect(); - getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */, - bounds, tempBounds); - mStackSupervisor.resizeDockedStackLocked(bounds, null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, null /* tempOtherTaskBounds */, - null /* tempOtherTaskInsetBounds */, false /* preserveWindows */, - false /* deferResume */); - } - - /** - * Adjusts the stack bounds if the IME is visible. - * - * @param imeWin The IME window. - * @param keepLastAmount Use {@code true} to keep the last adjusted amount from - * {@link DockedStackDividerController} for adjusting the stack bounds, - * Use {@code false} to reset adjusted amount as 0. - * @see #updateAdjustForIme(float, float, boolean) - */ - void setAdjustedForIme(WindowState imeWin, boolean keepLastAmount) { - mImeWin = imeWin; - mImeGoingAway = false; - if (!mAdjustedForIme || keepLastAmount) { - mAdjustedForIme = true; - DockedStackDividerController controller = getDisplayContent().mDividerControllerLocked; - final float adjustImeAmount = keepLastAmount ? controller.mLastAnimationProgress : 0f; - final float adjustDividerAmount = keepLastAmount ? controller.mLastDividerProgress : 0f; - updateAdjustForIme(adjustImeAmount, adjustDividerAmount, true /* force */); - } - } - - boolean isAdjustedForIme() { - return mAdjustedForIme; - } - - boolean isAnimatingForIme() { - return mImeWin != null && mImeWin.isAnimatingLw(); - } - - /** - * Update the stack's bounds (crop or position) according to the IME window's - * current position. When IME window is animated, the bottom stack is animated - * together to track the IME window's current position, and the top stack is - * cropped as necessary. - * - * @return true if a traversal should be performed after the adjustment. - */ - boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) { - if (adjustAmount != mAdjustImeAmount - || adjustDividerAmount != mAdjustDividerAmount || force) { - mAdjustImeAmount = adjustAmount; - mAdjustDividerAmount = adjustDividerAmount; - updateAdjustedBounds(); - return isVisible(); - } else { - return false; - } - } - - /** - * Resets the adjustment after it got adjusted for the IME. - * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about - * animations; otherwise, set flag and animates the window away together - * with IME window. - */ - void resetAdjustedForIme(boolean adjustBoundsNow) { - if (adjustBoundsNow) { - mImeWin = null; - mImeGoingAway = false; - mAdjustImeAmount = 0f; - mAdjustDividerAmount = 0f; - if (!mAdjustedForIme) { - return; - } - mAdjustedForIme = false; - updateAdjustedBounds(); - mWmService.setResizeDimLayer(false, getWindowingMode(), 1.0f); - } else { - mImeGoingAway |= mAdjustedForIme; - } - } - - /** - * Sets the amount how much we currently minimize our stack. - * - * @param minimizeAmount The amount, between 0 and 1. - * @return Whether the amount has changed and a layout is needed. - */ - boolean setAdjustedForMinimizedDock(float minimizeAmount) { - if (minimizeAmount != mMinimizeAmount) { - mMinimizeAmount = minimizeAmount; - updateAdjustedBounds(); - return isVisible(); - } else { - return false; - } - } - boolean shouldIgnoreInput() { - return isAdjustedForMinimizedDockedStack() - || (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable()); - } - - /** - * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows - * to the list of to be drawn windows the service is waiting for. - */ - void beginImeAdjustAnimation() { - forAllLeafTasks((t) -> { - if (t.hasContentToDisplay()) { - t.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER); - t.setWaitingForDrawnIfResizingChanged(); - } - }, true /* traverseTopToBottom */); - } - - /** Resets the resizing state of all windows. */ - void endImeAdjustAnimation() { - forAllLeafTasks((t) -> { - t.setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER); - }, true /* traverseTopToBottom */); - } - - private int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) { - return displayContentRect.top + (int) - ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN); - } - - private boolean adjustForIME(final WindowState imeWin) { - // To prevent task stack resize animation may flicking when playing app transition - // animation & IME window enter animation in parallel, we need to make sure app - // transition is done and then adjust task size for IME, skip the new adjusted frame when - // app transition is still running. - if (getDisplayContent().mAppTransition.isRunning()) { - return false; - } - - final int dockedSide = getDockSide(); - final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM; - if (imeWin == null || !dockedTopOrBottom) { - return false; - } - - final Rect displayStableRect = mTmpRect; - final Rect contentBounds = mTmpRect2; - - // Calculate the content bounds excluding the area occupied by IME - getDisplayContent().getStableRect(displayStableRect); - contentBounds.set(displayStableRect); - int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top); - - imeTop += imeWin.getGivenContentInsetsLw().top; - if (contentBounds.bottom > imeTop) { - contentBounds.bottom = imeTop; - } - - final int yOffset = displayStableRect.bottom - contentBounds.bottom; - - final int dividerWidth = - getDisplayContent().mDividerControllerLocked.getContentWidth(); - final int dividerWidthInactive = - getDisplayContent().mDividerControllerLocked.getContentWidthInactive(); - - if (dockedSide == DOCKED_TOP) { - // If this stack is docked on top, we make it smaller so the bottom stack is not - // occluded by IME. We shift its bottom up by the height of the IME, but - // leaves at least 30% of the top stack visible. - final int minTopStackBottom = - getMinTopStackBottom(displayStableRect, getRawBounds().bottom); - final int bottom = Math.max( - getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive, - minTopStackBottom); - mTmpAdjustedBounds.set(getRawBounds()); - mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) - * getRawBounds().bottom); - mFullyAdjustedImeBounds.set(getRawBounds()); - } else { - // When the stack is on bottom and has no focus, it's only adjusted for divider width. - final int dividerWidthDelta = dividerWidthInactive - dividerWidth; - - // When the stack is on bottom and has focus, it needs to be moved up so as to - // not occluded by IME, and at the same time adjusted for divider width. - // We try to move it up by the height of the IME window, but only to the extent - // that leaves at least 30% of the top stack visible. - // 'top' is where the top of bottom stack will move to in this case. - final int topBeforeImeAdjust = - getRawBounds().top - dividerWidth + dividerWidthInactive; - final int minTopStackBottom = - getMinTopStackBottom(displayStableRect, - getRawBounds().top - dividerWidth); - final int top = Math.max( - getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive); - - mTmpAdjustedBounds.set(getRawBounds()); - // Account for the adjustment for IME and divider width separately. - // (top - topBeforeImeAdjust) is the amount of movement due to IME only, - // and dividerWidthDelta is due to divider width change only. - mTmpAdjustedBounds.top = - getRawBounds().top + (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) - + mAdjustDividerAmount * dividerWidthDelta); - mFullyAdjustedImeBounds.set(getRawBounds()); - mFullyAdjustedImeBounds.top = top; - mFullyAdjustedImeBounds.bottom = top + getRawBounds().height(); - } - return true; - } - - private boolean adjustForMinimizedDockedStack(float minimizeAmount) { - final int dockSide = getDockSide(); - if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) { - return false; - } - - if (dockSide == DOCKED_TOP) { - mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect); - int topInset = mTmpRect.top; - mTmpAdjustedBounds.set(getRawBounds()); - mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount) - * getRawBounds().bottom); - } else if (dockSide == DOCKED_LEFT) { - mTmpAdjustedBounds.set(getRawBounds()); - final int width = getRawBounds().width(); - mTmpAdjustedBounds.right = - (int) (minimizeAmount * mDockedStackMinimizeThickness - + (1 - minimizeAmount) * getRawBounds().right); - mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width; - } else if (dockSide == DOCKED_RIGHT) { - mTmpAdjustedBounds.set(getRawBounds()); - mTmpAdjustedBounds.left = - (int) (minimizeAmount * (getRawBounds().right - mDockedStackMinimizeThickness) - + (1 - minimizeAmount) * getRawBounds().left); - } - return true; - } - - boolean isMinimizedDockAndHomeStackResizable() { - return mDisplayContent.mDividerControllerLocked.isMinimizedDock() - && mDisplayContent.mDividerControllerLocked.isHomeStackResizable(); - } - - /** - * @return the distance in pixels how much the stack gets minimized from it's original size - */ - int getMinimizeDistance() { - final int dockSide = getDockSide(); - if (dockSide == DOCKED_INVALID) { - return 0; - } - - if (dockSide == DOCKED_TOP) { - mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect); - int topInset = mTmpRect.top; - return getRawBounds().bottom - topInset; - } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) { - return getRawBounds().width() - mDockedStackMinimizeThickness; - } else { - return 0; - } - } - - /** - * Updates the adjustment depending on it's current state. - */ - private void updateAdjustedBounds() { - boolean adjust = false; - if (mMinimizeAmount != 0f) { - adjust = adjustForMinimizedDockedStack(mMinimizeAmount); - } else if (mAdjustedForIme) { - adjust = adjustForIME(mImeWin); - } - if (!adjust) { - mTmpAdjustedBounds.setEmpty(); - } - setAdjustedBounds(mTmpAdjustedBounds); - - final boolean isImeTarget = (mWmService.getImeFocusStackLocked() == this); - if (mAdjustedForIme && adjust && !isImeTarget) { - final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount) - * IME_ADJUST_DIM_AMOUNT; - mWmService.setResizeDimLayer(true, getWindowingMode(), alpha); - } - } - - void applyAdjustForImeIfNeeded(Task task) { - if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) { - return; - } - - final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds; - task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP); - mDisplayContent.setLayoutNeeded(); - } - - - boolean isAdjustedForMinimizedDockedStack() { - return mMinimizeAmount != 0f; + return inSplitScreenPrimaryWindowingMode() && !isFocusable(); } @Override @@ -4362,17 +3722,6 @@ class ActivityStack extends Task { pw.println(prefix + "mStackId=" + getRootTaskId()); pw.println(prefix + "mDeferRemoval=" + mDeferRemoval); pw.println(prefix + "mBounds=" + getRawBounds().toShortString()); - if (mMinimizeAmount != 0f) { - pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount); - } - if (mAdjustedForIme) { - pw.println(prefix + "mAdjustedForIme=true"); - pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount); - pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount); - } - if (!mAdjustedBounds.isEmpty()) { - pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString()); - } for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) { mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll); } @@ -4391,39 +3740,6 @@ class ActivityStack extends Task { } /** - * For docked workspace (or workspace that's side-by-side to the docked), provides - * information which side of the screen was the dock anchored. - */ - int getDockSide() { - return getDockSide(mDisplayContent.getConfiguration(), getRawBounds()); - } - - int getDockSideForDisplay(DisplayContent dc) { - return getDockSide(dc, dc.getConfiguration(), getRawBounds()); - } - - int getDockSide(Configuration parentConfig, Rect bounds) { - if (mDisplayContent == null) { - return DOCKED_INVALID; - } - return getDockSide(mDisplayContent, parentConfig, bounds); - } - - private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) { - return dc.getDockedDividerController().getDockSide(bounds, - parentConfig.windowConfiguration.getBounds(), - parentConfig.orientation, parentConfig.windowConfiguration.getRotation()); - } - - boolean hasTaskForUser(int userId) { - final PooledPredicate p = PooledLambda.obtainPredicate( - Task::isTaskForUser, PooledLambda.__(Task.class), userId); - final Task task = getTask(p); - p.recycle(); - return task != null; - } - - /** * Sets the current picture-in-picture aspect ratio. */ void setPictureInPictureAspectRatio(float aspectRatio) { @@ -4639,16 +3955,11 @@ class ActivityStack extends Task { bounds.dumpDebug(proto, BOUNDS); } getOverrideDisplayedBounds().dumpDebug(proto, DISPLAYED_BOUNDS); - mAdjustedBounds.dumpDebug(proto, ADJUSTED_BOUNDS); if (mLastNonFullscreenBounds != null) { mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS); } proto.write(DEFER_REMOVAL, mDeferRemoval); - proto.write(MINIMIZE_AMOUNT, mMinimizeAmount); - proto.write(ADJUSTED_FOR_IME, mAdjustedForIme); - proto.write(ADJUST_IME_AMOUNT, mAdjustImeAmount); - proto.write(ADJUST_DIVIDER_AMOUNT, mAdjustDividerAmount); proto.write(ANIMATING_BOUNDS, mBoundsAnimating); if (mSurfaceControl != null) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index b2d2f624e458..6d7f8fb6adde 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -35,12 +35,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.graphics.Rect.copyOrNull; import static android.os.PowerManager.PARTIAL_WAKE_LOCK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; @@ -210,17 +208,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { /** True if the docked stack is currently being resized. */ private boolean mDockedStackResizing; - /** - * True if there are pending docked bounds that need to be applied after - * {@link #mDockedStackResizing} is reset to false. - */ - private boolean mHasPendingDockedBounds; - private Rect mPendingDockedBounds; - private Rect mPendingTempDockedTaskBounds; - private Rect mPendingTempDockedTaskInsetBounds; - private Rect mPendingTempOtherTaskBounds; - private Rect mPendingTempOtherTaskInsetBounds; - // Activity actions an app cannot start if it uses a permission which is not granted. private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION = new ArrayMap<>(); @@ -387,15 +374,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { */ private final ArraySet<Integer> mResizingTasksDuringAnimation = new ArraySet<>(); - - /** - * If set to {@code false} all calls to resize the docked stack {@link #resizeDockedStackLocked} - * will be ignored. Useful for the case where the caller is handling resizing of other stack and - * moving tasks around and doesn't want dock stack to be resized due to an automatic trigger - * like the docked stack going empty. - */ - private boolean mAllowDockedStackResize = true; - private KeyguardController mKeyguardController; private PowerManager mPowerManager; @@ -1541,12 +1519,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED); } - - // Also disable docked stack resizing since we have manually adjusted the - // size of other stacks above and we don't want to trigger a docked stack - // resize when we remove task from it below and it is detached from the - // display because it no longer contains any tasks. - mAllowDockedStackResize = false; } // If we are moving from the pinned stack, then the animation takes care of updating @@ -1563,7 +1535,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); mRootWindowContainer.resumeFocusedStacksTopActivities(); } finally { - mAllowDockedStackResize = true; mService.continueWindowLayout(); } } @@ -1580,120 +1551,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mDockedStackResizing = resizing; mWindowManager.setDockedStackResizing(resizing); - - if (!resizing && mHasPendingDockedBounds) { - resizeDockedStackLocked(mPendingDockedBounds, mPendingTempDockedTaskBounds, - mPendingTempDockedTaskInsetBounds, mPendingTempOtherTaskBounds, - mPendingTempOtherTaskInsetBounds, PRESERVE_WINDOWS); - - mHasPendingDockedBounds = false; - mPendingDockedBounds = null; - mPendingTempDockedTaskBounds = null; - mPendingTempDockedTaskInsetBounds = null; - mPendingTempOtherTaskBounds = null; - mPendingTempOtherTaskInsetBounds = null; - } - } - - void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds, - Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds, - boolean preserveWindows) { - resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds, - tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows, - false /* deferResume */); - } - - void resizeDockedStackLocked(Rect displayedBounds, Rect tempDockedTaskBounds, - Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds, - boolean preserveWindows, boolean deferResume) { - - if (!mAllowDockedStackResize) { - // Docked stack resize currently disabled. - return; - } - - final ActivityStack stack = - mRootWindowContainer.getDefaultDisplay().getRootSplitScreenPrimaryTask(); - if (stack == null) { - Slog.w(TAG, "resizeDockedStackLocked: docked stack not found"); - return; - } - - if (mDockedStackResizing) { - mHasPendingDockedBounds = true; - mPendingDockedBounds = copyOrNull(displayedBounds); - mPendingTempDockedTaskBounds = copyOrNull(tempDockedTaskBounds); - mPendingTempDockedTaskInsetBounds = copyOrNull(tempDockedTaskInsetBounds); - mPendingTempOtherTaskBounds = copyOrNull(tempOtherTaskBounds); - mPendingTempOtherTaskInsetBounds = copyOrNull(tempOtherTaskInsetBounds); - } - - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeDockedStack"); - mService.deferWindowLayout(); - try { - // Don't allow re-entry while resizing. E.g. due to docked stack detaching. - mAllowDockedStackResize = false; - ActivityRecord r = stack.topRunningActivity(); - stack.resize(displayedBounds, tempDockedTaskBounds, - !PRESERVE_WINDOWS, DEFER_RESUME); - - // TODO: Checking for isAttached might not be needed as if the user passes in null - // dockedBounds then they want the docked stack to be dismissed. - if (stack.getWindowingMode() == WINDOWING_MODE_FULLSCREEN - || (displayedBounds == null && !stack.isAttached())) { - // The dock stack either was dismissed or went fullscreen, which is kinda the same. - // In this case we make all other static stacks fullscreen and move all - // docked stack tasks to the fullscreen stack. - moveTasksToFullscreenStackLocked(stack, ON_TOP); - - // stack shouldn't contain anymore activities, so nothing to resume. - r = null; - } else { - // Docked stacks occupy a dedicated region on screen so the size of all other - // static stacks need to be adjusted so they don't overlap with the docked stack. - // We get the bounds to use from window manager which has been adjusted for any - // screen controls and is also the same for all stacks. - final DisplayContent display = mRootWindowContainer.getDefaultDisplay(); - final Rect otherTaskRect = new Rect(); - for (int i = display.getStackCount() - 1; i >= 0; --i) { - final ActivityStack current = display.getStackAt(i); - if (!current.inSplitScreenSecondaryWindowingMode()) { - continue; - } - if (!current.affectedBySplitScreenResize()) { - continue; - } - if (mDockedStackResizing && !current.isTopActivityVisible()) { - // Non-visible stacks get resized once we're done with the resize - // interaction. - continue; - } - current.getStackDockedModeBounds(displayedBounds, - tempOtherTaskBounds /* currentTempTaskBounds */, - tempRect /* outStackBounds */, - otherTaskRect /* outTempTaskBounds */); - - if (tempRect.isEmpty()) { - // If this scenario is hit, it means something is not working right. - // Empty/null bounds implies fullscreen. In the event that this stack - // *should* be fullscreen, its mode should be set explicitly in a form - // of setWindowingMode so that other parts of the system are updated - // properly. - throw new IllegalArgumentException("Trying to set null bounds on a" - + " non-fullscreen stack"); - } - - current.resize(tempRect, tempOtherTaskBounds, preserveWindows, deferResume); - } - } - if (!deferResume) { - stack.ensureVisibleActivitiesConfiguration(r, preserveWindows); - } - } finally { - mAllowDockedStackResize = true; - mService.continueWindowLayout(); - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - } } private void removeStackInSurfaceTransaction(ActivityStack stack) { @@ -2723,9 +2580,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mService.deferWindowLayout(); try { if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { - mWindowManager.setDockedStackCreateStateLocked( - activityOptions.getSplitScreenCreateMode(), null /* initialBounds */); - // Defer updating the stack in which recents is until the app transition is done, to // not run into issues where we still need to draw the task in recents but the // docked stack is already created. @@ -2801,24 +2655,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // the window renders full-screen with the background filling the void. Also only // call this at the end to make sure that tasks exists on the window manager side. setResizingDuringAnimation(task); - - final DisplayContent display = task.getStack().getDisplay(); - final ActivityStack topSecondaryStack = - display.getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - if (topSecondaryStack != null && topSecondaryStack.isActivityTypeHome()) { - // If the home activity is the top split-screen secondary stack, then the - // primary split-screen stack is in the minimized mode which means it can't - // receive input keys, so we should move the focused app to the home app so that - // window manager can correctly calculate the focus window that can receive - // input keys. - display.moveHomeActivityToTop( - "startActivityFromRecents: homeVisibleInSplitScreen"); - - // Immediately update the minimized docked stack mode, the upcoming animation - // for the docked activity (WMS.overridePendingAppTransitionMultiThumbFuture) - // will do the animation to the target bounds - mWindowManager.checkSplitScreenMinimizedChanged(false /* animate */); - } } mService.continueWindowLayout(); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 510072d3831b..ca856ca7c1e6 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -169,12 +169,6 @@ public abstract class ActivityTaskManagerInternal { public abstract List<IBinder> getTopVisibleActivities(); /** - * Callback for window manager to let activity manager know that docked stack changes its - * minimized state. - */ - public abstract void notifyDockedStackMinimizedChanged(boolean minimized); - - /** * Notify listeners that contents are drawn for the first time on a single task display. * * @param displayId An ID of the display on which contents are drawn. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index d2d7ad304fc2..770dabf4f5ca 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -31,12 +31,12 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW; -import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; @@ -2309,9 +2309,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public boolean setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) { if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { - return setTaskWindowingModeSplitScreenPrimary(taskId, - SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, - toTop, ANIMATE, null /* initialBounds */, true /* showRecents */); + return setTaskWindowingModeSplitScreenPrimary(taskId, toTop); } enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()"); synchronized (mGlobalLock) { @@ -2681,10 +2679,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { throw new IllegalArgumentException("moveTaskToStack: Attempt to move task " + taskId + " to stack " + stackId); } - if (stack.inSplitScreenPrimaryWindowingMode()) { - mWindowManager.setDockedStackCreateStateLocked( - SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */); - } task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "moveTaskToStack"); } finally { @@ -2697,22 +2691,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * Moves the specified task to the primary-split-screen stack. * * @param taskId Id of task to move. - * @param createMode The mode the primary split screen stack should be created in if it doesn't - * exist already. See - * {@link android.app.ActivityTaskManager#SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT} - * and - * {@link android.app.ActivityTaskManager#SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT} * @param toTop If the task and stack should be moved to the top. - * @param animate Whether we should play an animation for the moving the task. - * @param initialBounds If the primary stack gets created, it will use these bounds for the - * stack. Pass {@code null} to use default bounds. - * @param showRecents If the recents activity should be shown on the other side of the task - * going into split-screen mode. * @return Whether the task was successfully put into splitscreen. */ @Override - public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, - boolean toTop, boolean animate, Rect initialBounds, boolean showRecents) { + public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, boolean toTop) { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingModeSplitScreenPrimary()"); synchronized (mGlobalLock) { @@ -4273,6 +4256,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + // TODO(b/149338177): remove when CTS no-longer requires it @Override public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds, Rect tempDockedTaskInsetBounds, @@ -4281,9 +4265,42 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - mStackSupervisor.resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds, - tempDockedTaskInsetBounds, tempOtherTaskBounds, tempOtherTaskInsetBounds, - PRESERVE_WINDOWS); + final DisplayContent dc = mRootWindowContainer.getDefaultDisplay(); + TaskTile primary = null; + TaskTile secondary = null; + for (int i = dc.getStackCount() - 1; i >= 0; --i) { + final TaskTile t = dc.getStackAt(i).asTile(); + if (t == null) { + continue; + } + if (t.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { + primary = t; + } else if (t.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { + secondary = t; + } + } + if (primary == null || secondary == null) { + return; + } + final WindowContainerTransaction wct = new WindowContainerTransaction(); + final Rect primaryRect = + tempDockedTaskInsetBounds != null ? tempDockedTaskInsetBounds + : (tempDockedTaskBounds != null ? tempDockedTaskBounds + : dockedBounds); + wct.setBounds(primary.mRemoteToken, primaryRect); + Rect otherRect = tempOtherTaskInsetBounds != null ? tempOtherTaskInsetBounds + : tempOtherTaskBounds; + if (otherRect == null) { + // Temporary estimation... again this is just for tests. + otherRect = new Rect(secondary.getBounds()); + if (dc.getBounds().width() > dc.getBounds().height()) { + otherRect.left = primaryRect.right + 6; + } else { + otherRect.top = primaryRect.bottom + 6; + } + } + wct.setBounds(secondary.mRemoteToken, otherRect); + mTaskOrganizerController.applyContainerTransaction(wct, null /* organizer */); } } finally { Binder.restoreCallingIdentity(ident); @@ -6136,13 +6153,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void notifyDockedStackMinimizedChanged(boolean minimized) { - synchronized (mGlobalLock) { - mRootWindowContainer.setDockedStackMinimized(minimized); - } - } - - @Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) { Objects.requireNonNull(intents, "intents"); diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index ca09537f6ad0..4916c31f2878 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -446,8 +446,6 @@ public class AppTransition implements Dump { ? topOpeningAnim.getStatusBarTransitionsStartTime() : SystemClock.uptimeMillis(), AnimationAdapter.STATUS_BAR_TRANSITION_DURATION); - mDisplayContent.getDockedDividerController() - .notifyAppTransitionStarting(openingApps, transit); if (mRemoteAnimationController != null) { mRemoteAnimationController.goodToGo(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 30e8da2c23f7..5cd29301c733 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -94,7 +94,6 @@ import static com.android.server.wm.DisplayContentProto.APP_TRANSITION; import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES; import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO; -import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER; import static com.android.server.wm.DisplayContentProto.DPI; import static com.android.server.wm.DisplayContentProto.FOCUSED_APP; import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID; @@ -131,7 +130,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS; -import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER; +import static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_STACKS; import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION; @@ -1005,7 +1004,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mDisplayPolicy.systemReady(); } mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius(); - mDividerControllerLocked = new DockedStackDividerController(mWmService, this); + mDividerControllerLocked = new DockedStackDividerController(this); mPinnedStackControllerLocked = new PinnedStackController(mWmService, this); final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession) @@ -2232,12 +2231,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * for bounds calculations. */ void preOnConfigurationChanged() { - final DockedStackDividerController dividerController = getDockedDividerController(); - - if (dividerController != null) { - getDockedDividerController().onConfigurationChanged(); - } - final PinnedStackController pinnedStackController = getPinnedStackController(); if (pinnedStackController != null) { @@ -2621,10 +2614,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // We also remove the outside touch area for resizing for all freeform // tasks (including the focused). // We save the focused task region once we find it, and add it back at the end. - // If the task is home stack and it is resizable in the minimized state, we want to - // exclude the docked stack from touch so we need the entire screen area and not just a + // If the task is home stack and it is resizable and visible (top of its root task), we want + // to exclude the docked stack from touch so we need the entire screen area and not just a // small portion which the home stack currently is resized to. - if (task.isActivityTypeHome() && task.getStack().isMinimizedDockAndHomeStackResizable()) { + if (task.isActivityTypeHome() && task.isVisible() && task.getStack().getTile() != null + && task.isResizeable()) { mDisplayContent.getBounds(mTmpRect); } else { task.getDimBounds(mTmpRect); @@ -2633,6 +2627,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (task == focusedTask) { // Add the focused task rect back into the exclude region once we are done // processing stacks. + // NOTE: this *looks* like a no-op, but this usage of mTmpRect2 is expected by + // updateTouchExcludeRegion. mTmpRect2.set(mTmpRect); } @@ -2746,58 +2742,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mDeferredRemoval; } - boolean animateForIme(float interpolatedValue, float animationTarget, - float dividerAnimationTarget) { - boolean updated = false; - - for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) { - final ActivityStack stack = mTaskContainers.getChildAt(i); - if (stack == null || !stack.isAdjustedForIme()) { - continue; - } - - if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) { - stack.resetAdjustedForIme(true /* adjustBoundsNow */); - updated = true; - } else { - mDividerControllerLocked.mLastAnimationProgress = - mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue); - mDividerControllerLocked.mLastDividerProgress = - mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue); - updated |= stack.updateAdjustForIme( - mDividerControllerLocked.mLastAnimationProgress, - mDividerControllerLocked.mLastDividerProgress, - false /* force */); - } - if (interpolatedValue >= 1f) { - stack.endImeAdjustAnimation(); - } - } - - return updated; - } - - boolean clearImeAdjustAnimation() { - boolean changed = false; - for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) { - final ActivityStack stack = mTaskContainers.getChildAt(i); - if (stack != null && stack.isAdjustedForIme()) { - stack.resetAdjustedForIme(true /* adjustBoundsNow */); - changed = true; - } - } - return changed; - } - - void beginImeAdjustAnimation() { - for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) { - final ActivityStack stack = mTaskContainers.getChildAt(i); - if (stack.isVisible() && stack.isAdjustedForIme()) { - stack.beginImeAdjustAnimation(); - } - } - } - void adjustForImeIfNeeded() { final WindowState imeWin = mInputMethodWindow; final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() @@ -2892,7 +2836,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final ActivityStack stack = mTaskContainers.getChildAt(i); stack.dumpDebug(proto, TASKS, logLevel); } - mDividerControllerLocked.dumpDebug(proto, DOCKED_STACK_DIVIDER_CONTROLLER); for (int i = mOverlayContainers.getChildCount() - 1; i >= 0; --i) { final WindowToken windowToken = mOverlayContainers.getChildAt(i); windowToken.dumpDebug(proto, OVERLAY_WINDOWS, logLevel); @@ -3062,8 +3005,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } pw.println(); - mDividerControllerLocked.dump(prefix, pw); - pw.println(); mPinnedStackControllerLocked.dump(prefix, pw); pw.println(); @@ -4084,7 +4025,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mInputMonitor.updateInputWindowsLw(false /*force*/); } - mWmService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); + mWmService.mH.sendEmptyMessage(UPDATE_MULTI_WINDOW_STACKS); } /** @@ -4692,17 +4633,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo @Override int getOrientation(int candidate) { if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) { - // Apps and their containers are not allowed to specify an orientation while the - // docked stack is visible...except for the home stack if the docked stack is - // minimized and it actually set something and the bounds is different from the - // display. + // Apps and their containers are not allowed to specify an orientation while using + // root tasks...except for the home stack if it is not resizable and currently + // visible (top of) its root task. if (mRootHomeTask != null && mRootHomeTask.isVisible() - && mDividerControllerLocked.isMinimizedDock() - && !(mDividerControllerLocked.isHomeStackResizable() - && mRootHomeTask.matchParentBounds())) { - final int orientation = mRootHomeTask.getOrientation(); - if (orientation != SCREEN_ORIENTATION_UNSET) { - return orientation; + && mRootHomeTask.getTile() != null) { + final Task topMost = mRootHomeTask.getTopMostTask(); + final boolean resizable = topMost == null && topMost.isResizeable(); + if (!(resizable && mRootHomeTask.matchParentBounds())) { + final int orientation = mRootHomeTask.getOrientation(); + if (orientation != SCREEN_ORIENTATION_UNSET) { + return orientation; + } } } return SCREEN_ORIENTATION_UNSPECIFIED; @@ -6167,8 +6109,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo t.removeAllChildren(); } } - mDividerControllerLocked.setMinimizedDockedStack(false /* minimized */, - false /* animate */); } finally { final ActivityStack topFullscreenStack = getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f02a9dd61107..497c4733ab58 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1178,8 +1178,6 @@ public class DisplayPolicy { return R.anim.dock_left_enter; } } - } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) { - return selectDockedDividerAnimation(win, transit); } if (transit == TRANSIT_PREVIEW_DONE) { @@ -1204,36 +1202,6 @@ public class DisplayPolicy { return ANIMATION_STYLEABLE; } - private int selectDockedDividerAnimation(WindowState win, int transit) { - int insets = mDisplayContent.getDockedDividerController().getContentInsets(); - - // If the divider is behind the navigation bar, don't animate. - final Rect frame = win.getFrameLw(); - final boolean behindNavBar = mNavigationBar != null - && ((mNavigationBarPosition == NAV_BAR_BOTTOM - && frame.top + insets >= mNavigationBar.getFrameLw().top) - || (mNavigationBarPosition == NAV_BAR_RIGHT - && frame.left + insets >= mNavigationBar.getFrameLw().left) - || (mNavigationBarPosition == NAV_BAR_LEFT - && frame.right - insets <= mNavigationBar.getFrameLw().right)); - final boolean landscape = frame.height() > frame.width(); - final boolean offscreenLandscape = landscape && (frame.right - insets <= 0 - || frame.left + insets >= win.getDisplayFrameLw().right); - final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0 - || frame.bottom + insets >= win.getDisplayFrameLw().bottom); - final boolean offscreen = offscreenLandscape || offscreenPortrait; - if (behindNavBar || offscreen) { - return ANIMATION_STYLEABLE; - } - if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { - return R.anim.fade_in; - } else if (transit == TRANSIT_EXIT) { - return R.anim.fade_out; - } else { - return ANIMATION_STYLEABLE; - } - } - /** * Called when a new system UI visibility is being reported, allowing * the policy to adjust what is actually reported. diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 958c8ae94e47..20738ed29470 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -16,330 +16,26 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; -import static android.content.res.Configuration.ORIENTATION_PORTRAIT; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; -import static android.view.WindowManager.DOCKED_BOTTOM; -import static android.view.WindowManager.DOCKED_INVALID; -import static android.view.WindowManager.DOCKED_LEFT; -import static android.view.WindowManager.DOCKED_RIGHT; -import static android.view.WindowManager.DOCKED_TOP; -import static android.view.WindowManager.TRANSIT_NONE; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; - -import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION; -import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR; -import static com.android.server.wm.DockedStackDividerControllerProto.MINIMIZED_DOCK; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; - -import android.content.Context; -import android.content.res.Configuration; import android.graphics.Rect; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.util.ArraySet; -import android.util.Slog; -import android.util.proto.ProtoOutputStream; -import android.view.DisplayCutout; -import android.view.DisplayInfo; -import android.view.IDockedStackListener; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; -import android.view.animation.PathInterpolator; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.inputmethod.SoftInputShowHideReason; -import com.android.internal.policy.DividerSnapAlgorithm; -import com.android.internal.policy.DockedDividerUtils; -import com.android.server.LocalServices; -import com.android.server.inputmethod.InputMethodManagerInternal; -import com.android.server.wm.WindowManagerService.H; - -import java.io.PrintWriter; /** * Keeps information about the docked stack divider. */ public class DockedStackDividerController { - private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM; - - /** - * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip - * revealing surface at the earliest. - */ - private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f; - - /** - * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip - * revealing surface at the latest. - */ - private static final float CLIP_REVEAL_MEET_LAST = 1f; - - /** - * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start - * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}. - */ - private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f; - - /** - * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, - * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}. - */ - private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f; - - private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR = - new PathInterpolator(0.2f, 0f, 0.1f, 1f); - - private static final long IME_ADJUST_ANIM_DURATION = 280; - - private static final long IME_ADJUST_DRAWN_TIMEOUT = 200; - - private static final int DIVIDER_WIDTH_INACTIVE_DP = 4; - - private final WindowManagerService mService; private final DisplayContent mDisplayContent; - private int mDividerWindowWidth; - private int mDividerWindowWidthInactive; - private int mDividerInsets; - private int mTaskHeightInMinimizedMode; private boolean mResizing; - private WindowState mWindow; - private final Rect mTmpRect = new Rect(); - private final Rect mTmpRect2 = new Rect(); - private final Rect mTmpRect3 = new Rect(); - private final Rect mLastRect = new Rect(); - private boolean mLastVisibility = false; - private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners - = new RemoteCallbackList<>(); - private boolean mMinimizedDock; - private int mOriginalDockedSide = DOCKED_INVALID; - private boolean mAnimatingForMinimizedDockedStack; - private boolean mAnimationStarted; - private long mAnimationStartTime; - private float mAnimationStart; - private float mAnimationTarget; - private long mAnimationDuration; - private boolean mAnimationStartDelayed; - private final Interpolator mMinimizedDockInterpolator; - private float mMaximizeMeetFraction; private final Rect mTouchRegion = new Rect(); - private boolean mAnimatingForIme; - private boolean mAdjustedForIme; - private int mImeHeight; - private WindowState mDelayedImeWin; - private boolean mAdjustedForDivider; - private float mDividerAnimationStart; - private float mDividerAnimationTarget; - float mLastAnimationProgress; - float mLastDividerProgress; - private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4]; - private boolean mImeHideRequested; - private ActivityStack mDimmedStack; - DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) { - mService = service; + DockedStackDividerController(DisplayContent displayContent) { mDisplayContent = displayContent; - final Context context = service.mContext; - mMinimizedDockInterpolator = AnimationUtils.loadInterpolator( - context, android.R.interpolator.fast_out_slow_in); - loadDimens(); - } - - int getSmallestWidthDpForBounds(Rect bounds) { - final DisplayInfo di = mDisplayContent.getDisplayInfo(); - - final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth; - final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight; - int minWidth = Integer.MAX_VALUE; - - // Go through all screen orientations and find the orientation in which the task has the - // smallest width. - for (int rotation = 0; rotation < 4; rotation++) { - mTmpRect.set(bounds); - mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect); - final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); - mTmpRect2.set(0, 0, - rotated ? baseDisplayHeight : baseDisplayWidth, - rotated ? baseDisplayWidth : baseDisplayHeight); - final int orientation = mTmpRect2.width() <= mTmpRect2.height() - ? ORIENTATION_PORTRAIT - : ORIENTATION_LANDSCAPE; - final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation, rotation); - final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide, - getContentWidth()); - - final DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation( - rotation).getDisplayCutout(); - - // Since we only care about feasible states, snap to the closest snap target, like it - // would happen when actually rotating the screen. - final int snappedPosition = mSnapAlgorithmForRotation[rotation] - .calculateNonDismissingSnapTarget(position).position; - DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect, - mTmpRect2.width(), mTmpRect2.height(), getContentWidth()); - mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, mTmpRect2.width(), - mTmpRect2.height(), displayCutout, mTmpRect3); - mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect); - minWidth = Math.min(mTmpRect.width(), minWidth); - } - return (int) (minWidth / mDisplayContent.getDisplayMetrics().density); - } - - /** - * Get the current docked side. Determined by its location of {@param bounds} within - * {@param displayRect} but if both are the same, it will try to dock to each side and determine - * if allowed in its respected {@param orientation}. - * - * @param bounds bounds of the docked task to get which side is docked - * @param displayRect bounds of the display that contains the docked task - * @param orientation the origination of device - * @return current docked side - */ - int getDockSide(Rect bounds, Rect displayRect, int orientation, int rotation) { - if (orientation == Configuration.ORIENTATION_PORTRAIT) { - // Portrait mode, docked either at the top or the bottom. - final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top); - if (diff > 0) { - return DOCKED_TOP; - } else if (diff < 0) { - return DOCKED_BOTTOM; - } - return canPrimaryStackDockTo(DOCKED_TOP, displayRect, rotation) - ? DOCKED_TOP : DOCKED_BOTTOM; - } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - // Landscape mode, docked either on the left or on the right. - final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left); - if (diff > 0) { - return DOCKED_LEFT; - } else if (diff < 0) { - return DOCKED_RIGHT; - } - return canPrimaryStackDockTo(DOCKED_LEFT, displayRect, rotation) - ? DOCKED_LEFT : DOCKED_RIGHT; - } - return DOCKED_INVALID; - } - - void getHomeStackBoundsInDockedMode(Configuration parentConfig, int dockSide, Rect outBounds) { - final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout; - final int displayWidth = parentConfig.windowConfiguration.getBounds().width(); - final int displayHeight = parentConfig.windowConfiguration.getBounds().height(); - mDisplayContent.getDisplayPolicy().getStableInsetsLw( - parentConfig.windowConfiguration.getRotation(), displayWidth, displayHeight, - displayCutout, mTmpRect); - int dividerSize = mDividerWindowWidth - 2 * mDividerInsets; - // The offset in the left (landscape)/top (portrait) is calculated with the minimized - // offset value with the divider size and any system insets in that direction. - if (parentConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { - outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top, - displayWidth, displayHeight); - } else { - // In landscape also inset the left/right side with the status bar height to match the - // minimized size height in portrait mode. - final int primaryTaskWidth = mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top; - int left = mTmpRect.left; - int right = displayWidth - mTmpRect.right; - if (dockSide == DOCKED_LEFT) { - left += primaryTaskWidth; - } else if (dockSide == DOCKED_RIGHT) { - right -= primaryTaskWidth; - } - outBounds.set(left, 0, right, displayHeight); - } - } - - boolean isHomeStackResizable() { - final ActivityStack homeStack = mDisplayContent.getRootHomeTask(); - if (homeStack == null) { - return false; - } - final Task homeTask = homeStack.getTopMostTask(); - return homeTask != null && homeTask.isResizeable(); - } - - private void initSnapAlgorithmForRotations() { - final Configuration baseConfig = mDisplayContent.getConfiguration(); - - // Initialize the snap algorithms for all 4 screen orientations. - final Configuration config = new Configuration(); - for (int rotation = 0; rotation < 4; rotation++) { - final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); - final int dw = rotated - ? mDisplayContent.mBaseDisplayHeight - : mDisplayContent.mBaseDisplayWidth; - final int dh = rotated - ? mDisplayContent.mBaseDisplayWidth - : mDisplayContent.mBaseDisplayHeight; - final DisplayCutout displayCutout = - mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); - final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); - displayPolicy.getStableInsetsLw(rotation, dw, dh, displayCutout, mTmpRect); - config.unset(); - config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; - - final int appWidth = displayPolicy.getNonDecorDisplayWidth(dw, dh, rotation, - baseConfig.uiMode, displayCutout); - final int appHeight = displayPolicy.getNonDecorDisplayHeight(dw, dh, rotation, - baseConfig.uiMode, displayCutout); - displayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect); - final int leftInset = mTmpRect.left; - final int topInset = mTmpRect.top; - - config.windowConfiguration.setAppBounds(leftInset /*left*/, topInset /*top*/, - leftInset + appWidth /*right*/, topInset + appHeight /*bottom*/); - - final float density = mDisplayContent.getDisplayMetrics().density; - config.screenWidthDp = (int) (displayPolicy.getConfigDisplayWidth(dw, dh, rotation, - baseConfig.uiMode, displayCutout) / density); - config.screenHeightDp = (int) (displayPolicy.getConfigDisplayHeight(dw, dh, rotation, - baseConfig.uiMode, displayCutout) / density); - final Context rotationContext = mService.mContext.createConfigurationContext(config); - mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm( - rotationContext.getResources(), dw, dh, getContentWidth(), - config.orientation == ORIENTATION_PORTRAIT, mTmpRect); - } - } - - private void loadDimens() { - final Context context = mService.mContext; - mDividerWindowWidth = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_divider_thickness); - mDividerInsets = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_divider_insets); - mDividerWindowWidthInactive = WindowManagerService.dipToPixel( - DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics()); - mTaskHeightInMinimizedMode = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.task_height_of_minimized_mode); - initSnapAlgorithmForRotations(); - } - - void onConfigurationChanged() { - loadDimens(); } boolean isResizing() { return mResizing; } - int getContentWidth() { - return mDividerWindowWidth - 2 * mDividerInsets; - } - - int getContentInsets() { - return mDividerInsets; - } - - int getContentWidthInactive() { - return mDividerWindowWidthInactive; - } - void setResizing(boolean resizing) { if (mResizing != resizing) { mResizing = resizing; @@ -353,676 +49,10 @@ public class DockedStackDividerController { void getTouchRegion(Rect outRegion) { outRegion.set(mTouchRegion); - if (mWindow != null) { - outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top); - } } private void resetDragResizingChangeReported() { mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported, true /* traverseTopToBottom */ ); } - - void setWindow(WindowState window) { - mWindow = window; - reevaluateVisibility(false); - } - - void reevaluateVisibility(boolean force) { - if (mWindow == null) { - return; - } - ActivityStack stack = mDisplayContent.getRootSplitScreenPrimaryTask(); - - // If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide - final boolean visible = stack != null; - if (mLastVisibility == visible && !force) { - return; - } - mLastVisibility = visible; - notifyDockedDividerVisibilityChanged(visible); - if (!visible) { - setResizeDimLayer(false, WINDOWING_MODE_UNDEFINED, 0f); - } - } - - private boolean wasVisible() { - return mLastVisibility; - } - - void setAdjustedForIme( - boolean adjustedForIme, boolean adjustedForDivider, - boolean animate, WindowState imeWin, int imeHeight) { - if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight) - || mAdjustedForDivider != adjustedForDivider) { - if (animate && !mAnimatingForMinimizedDockedStack) { - // Notify SystemUI to set the target docked stack size according current docked - // state without animation when calling startImeAdjustAnimation. - notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */, - isHomeStackResizable()); - startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin); - } else { - // Animation might be delayed, so only notify if we don't run an animation. - notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */); - } - mAdjustedForIme = adjustedForIme; - mImeHeight = imeHeight; - mAdjustedForDivider = adjustedForDivider; - } - } - - int getImeHeightAdjustedFor() { - return mImeHeight; - } - - void positionDockedStackedDivider(Rect frame) { - ActivityStack stack = mDisplayContent.getRootSplitScreenPrimaryTask(); - if (stack == null) { - // Unfortunately we might end up with still having a divider, even though the underlying - // stack was already removed. This is because we are on AM thread and the removal of the - // divider was deferred to WM thread and hasn't happened yet. In that case let's just - // keep putting it in the same place it was before the stack was removed to have - // continuity and prevent it from jumping to the center. It will get hidden soon. - frame.set(mLastRect); - return; - } else { - stack.getDimBounds(mTmpRect); - } - int side = stack.getDockSide(); - switch (side) { - case DOCKED_LEFT: - frame.set(mTmpRect.right - mDividerInsets, frame.top, - mTmpRect.right + frame.width() - mDividerInsets, frame.bottom); - break; - case DOCKED_TOP: - frame.set(frame.left, mTmpRect.bottom - mDividerInsets, - mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets); - break; - case DOCKED_RIGHT: - frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top, - mTmpRect.left + mDividerInsets, frame.bottom); - break; - case DOCKED_BOTTOM: - frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets, - frame.right, mTmpRect.top + mDividerInsets); - break; - } - mLastRect.set(frame); - } - - private void notifyDockedDividerVisibilityChanged(boolean visible) { - final int size = mDockedStackListeners.beginBroadcast(); - for (int i = 0; i < size; ++i) { - final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); - try { - listener.onDividerVisibilityChanged(visible); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e); - } - } - mDockedStackListeners.finishBroadcast(); - } - - /** - * Checks if the primary stack is allowed to dock to a specific side based on its original dock - * side. - * - * @param dockSide the side to see if it is valid - * @return true if the side provided is valid - */ - boolean canPrimaryStackDockTo(int dockSide, Rect parentRect, int rotation) { - final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); - return isDockSideAllowed(dockSide, mOriginalDockedSide, - policy.navigationBarPosition(parentRect.width(), parentRect.height(), rotation), - policy.navigationBarCanMove()); - } - - @VisibleForTesting - static boolean isDockSideAllowed(int dockSide, int originalDockSide, int navBarPosition, - boolean navigationBarCanMove) { - if (dockSide == DOCKED_TOP) { - return true; - } - - if (navigationBarCanMove) { - // Only allow the dockside opposite to the nav bar position in landscape - return dockSide == DOCKED_LEFT && navBarPosition == NAV_BAR_RIGHT - || dockSide == DOCKED_RIGHT && navBarPosition == NAV_BAR_LEFT; - } - - // Side is the same as original side - if (dockSide == originalDockSide) { - return true; - } - - // Only if original docked side was top in portrait will allow left for landscape - return dockSide == DOCKED_LEFT && originalDockSide == DOCKED_TOP; - } - - void notifyDockedStackExistsChanged(boolean exists) { - // TODO(multi-display): Perform all actions only for current display. - final int size = mDockedStackListeners.beginBroadcast(); - for (int i = 0; i < size; ++i) { - final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); - try { - listener.onDockedStackExistsChanged(exists); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e); - } - } - mDockedStackListeners.finishBroadcast(); - if (exists) { - InputMethodManagerInternal inputMethodManagerInternal = - LocalServices.getService(InputMethodManagerInternal.class); - if (inputMethodManagerInternal != null) { - - // Hide the current IME to avoid problems with animations from IME adjustment when - // attaching the docked stack. - inputMethodManagerInternal.hideCurrentInputMethod( - SoftInputShowHideReason.HIDE_DOCKED_STACK_ATTACHED); - mImeHideRequested = true; - } - - // If a primary stack was just created, it will not have access to display content at - // this point so pass it from here to get a valid dock side. - final ActivityStack stack = - mDisplayContent.getRootSplitScreenPrimaryTask(); - mOriginalDockedSide = stack.getDockSideForDisplay(mDisplayContent); - return; - } - mOriginalDockedSide = DOCKED_INVALID; - setMinimizedDockedStack(false /* minimizedDock */, false /* animate */); - - if (mDimmedStack != null) { - mDimmedStack.stopDimming(); - mDimmedStack = null; - } - } - - /** - * Resets the state that IME hide has been requested. See {@link #isImeHideRequested}. - */ - void resetImeHideRequested() { - mImeHideRequested = false; - } - - /** - * The docked stack divider controller makes sure the IME gets hidden when attaching the docked - * stack, to avoid animation problems. This flag indicates whether the request to hide the IME - * has been sent in an asynchronous manner, and the IME should be treated as hidden already. - * - * @return whether IME hide request has been sent - */ - boolean isImeHideRequested() { - return mImeHideRequested; - } - - private void notifyDockedStackMinimizedChanged(boolean minimizedDock, boolean animate, - boolean isHomeStackResizable) { - long animDuration = 0; - if (animate) { - final ActivityStack stack = - mDisplayContent.getRootSplitScreenPrimaryTask(); - final long transitionDuration = isAnimationMaximizing() - ? mDisplayContent.mAppTransition.getLastClipRevealTransitionDuration() - : DEFAULT_APP_TRANSITION_DURATION; - mAnimationDuration = (long) - (transitionDuration * mService.getTransitionAnimationScaleLocked()); - mMaximizeMeetFraction = getClipRevealMeetFraction(stack); - animDuration = (long) (mAnimationDuration * mMaximizeMeetFraction); - } - final int size = mDockedStackListeners.beginBroadcast(); - for (int i = 0; i < size; ++i) { - final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); - try { - listener.onDockedStackMinimizedChanged(minimizedDock, animDuration, - isHomeStackResizable); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e); - } - } - mDockedStackListeners.finishBroadcast(); - // Only notify ATM after we update the remote listeners, otherwise it may trigger another - // minimize change, which would lead to an inversion of states send to the listeners - mService.mAtmInternal.notifyDockedStackMinimizedChanged(minimizedDock); - } - - void notifyDockSideChanged(int newDockSide) { - final int size = mDockedStackListeners.beginBroadcast(); - for (int i = 0; i < size; ++i) { - final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); - try { - listener.onDockSideChanged(newDockSide); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering dock side changed event.", e); - } - } - mDockedStackListeners.finishBroadcast(); - } - - private void notifyAdjustedForImeChanged(boolean adjustedForIme, long animDuration) { - final int size = mDockedStackListeners.beginBroadcast(); - for (int i = 0; i < size; ++i) { - final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i); - try { - listener.onAdjustedForImeChanged(adjustedForIme, animDuration); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering adjusted for ime changed event.", e); - } - } - mDockedStackListeners.finishBroadcast(); - } - - void registerDockedStackListener(IDockedStackListener listener) { - mDockedStackListeners.register(listener); - notifyDockedDividerVisibilityChanged(wasVisible()); - notifyDockedStackExistsChanged( - mDisplayContent.getRootSplitScreenPrimaryTask() != null); - notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */, - isHomeStackResizable()); - notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */); - - } - - /** - * Shows a dim layer with {@param alpha} if {@param visible} is true and - * {@param targetWindowingMode} isn't - * {@link android.app.WindowConfiguration#WINDOWING_MODE_UNDEFINED} and there is a stack on the - * display in that windowing mode. - */ - void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) { - // TODO: Maybe only allow split-screen windowing modes? - final ActivityStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED - ? mDisplayContent.getTopStackInWindowingMode(targetWindowingMode) - : null; - final ActivityStack dockedStack = mDisplayContent.getRootSplitScreenPrimaryTask(); - boolean visibleAndValid = visible && stack != null && dockedStack != null; - - // Ensure an old dim that was shown for the docked stack divider is removed so we don't end - // up with dim layers that can no longer be removed. - if (mDimmedStack != null && mDimmedStack != stack) { - mDimmedStack.stopDimming(); - mDimmedStack = null; - } - - if (visibleAndValid) { - mDimmedStack = stack; - stack.dim(alpha); - } - if (!visibleAndValid && stack != null) { - mDimmedStack = null; - stack.stopDimming(); - } - } - - /** - * Notifies the docked stack divider controller of a visibility change that happens without - * an animation. - */ - void notifyAppVisibilityChanged() { - checkMinimizeChanged(false /* animate */); - } - - void notifyAppTransitionStarting(ArraySet<ActivityRecord> openingApps, int appTransition) { - final boolean wasMinimized = mMinimizedDock; - checkMinimizeChanged(true /* animate */); - - // We were minimized, and now we are still minimized, but somebody is trying to launch an - // app in docked stack, better show recent apps so we actually get unminimized! However do - // not do this if keyguard is dismissed such as when the device is unlocking. This catches - // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because - // we couldn't retrace the launch of the app in the docked stack to the launch from - // homescreen. - if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps) - && appTransition != TRANSIT_NONE && - !AppTransition.isKeyguardGoingAwayTransit(appTransition)) { - if (mService.mAtmInternal.isRecentsComponentHomeActivity(mService.mCurrentUserId)) { - // When the home activity is the recents component and we are already minimized, - // then there is nothing to do here since home is already visible - } else { - mService.showRecentApps(); - } - } - } - - /** - * @return true if {@param apps} contains an activity in the docked stack, false otherwise. - */ - private boolean containsAppInDockedStack(ArraySet<ActivityRecord> apps) { - for (int i = apps.size() - 1; i >= 0; i--) { - final ActivityRecord activity = apps.valueAt(i); - if (activity.getTask() != null && activity.inSplitScreenPrimaryWindowingMode()) { - return true; - } - } - return false; - } - - boolean isMinimizedDock() { - return mMinimizedDock; - } - - void checkMinimizeChanged(boolean animate) { - if (mDisplayContent.getRootSplitScreenPrimaryTask() == null) { - return; - } - final ActivityStack homeStack = mDisplayContent.getRootHomeTask(); - if (homeStack == null) { - return; - } - final Task homeTask = homeStack.getTopMostTask(); - if (homeTask == null || !isWithinDisplay(homeTask)) { - return; - } - - // Do not minimize when dock is already minimized while keyguard is showing and not - // occluded such as unlocking the screen - if (mMinimizedDock && mService.mKeyguardOrAodShowingOnDefaultDisplay) { - return; - } - final ActivityStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode( - WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController(); - final boolean minimizedForRecentsAnimation = recentsAnim != null && - recentsAnim.isSplitScreenMinimized(); - boolean homeVisible = homeTask.getTopVisibleActivity() != null; - if (homeVisible && topSecondaryStack != null) { - // Home should only be considered visible if it is greater or equal to the top secondary - // stack in terms of z-order. - homeVisible = homeStack.compareTo(topSecondaryStack) >= 0; - } - setMinimizedDockedStack(homeVisible || minimizedForRecentsAnimation, animate); - } - - private boolean isWithinDisplay(Task task) { - task.getBounds(mTmpRect); - mDisplayContent.getBounds(mTmpRect2); - return mTmpRect.intersect(mTmpRect2); - } - - /** - * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the - * docked stack are heavily clipped so you can only see a minimal peek state. - * - * @param minimizedDock Whether the docked stack is currently minimized. - * @param animate Whether to animate the change. - */ - void setMinimizedDockedStack(boolean minimizedDock, boolean animate) { - final boolean wasMinimized = mMinimizedDock; - mMinimizedDock = minimizedDock; - if (minimizedDock == wasMinimized) { - return; - } - - final boolean imeChanged = clearImeAdjustAnimation(); - boolean minimizedChange = false; - if (isHomeStackResizable()) { - notifyDockedStackMinimizedChanged(minimizedDock, animate, - true /* isHomeStackResizable */); - minimizedChange = true; - } else { - if (minimizedDock) { - if (animate) { - startAdjustAnimation(0f, 1f); - } else { - minimizedChange |= setMinimizedDockedStack(true); - } - } else { - if (animate) { - startAdjustAnimation(1f, 0f); - } else { - minimizedChange |= setMinimizedDockedStack(false); - } - } - } - if (imeChanged || minimizedChange) { - if (imeChanged && !minimizedChange) { - Slog.d(TAG, "setMinimizedDockedStack: IME adjust changed due to minimizing," - + " minimizedDock=" + minimizedDock - + " minimizedChange=" + minimizedChange); - } - mService.mWindowPlacerLocked.performSurfacePlacement(); - } - } - - private boolean clearImeAdjustAnimation() { - final boolean changed = mDisplayContent.clearImeAdjustAnimation(); - mAnimatingForIme = false; - return changed; - } - - private void startAdjustAnimation(float from, float to) { - mAnimatingForMinimizedDockedStack = true; - mAnimationStarted = false; - mAnimationStart = from; - mAnimationTarget = to; - } - - private void startImeAdjustAnimation( - boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) { - - // If we're not in an animation, the starting point depends on whether we're adjusted - // or not. If we're already in an animation, we start from where the current animation - // left off, so that the motion doesn't look discontinuous. - if (!mAnimatingForIme) { - mAnimationStart = mAdjustedForIme ? 1 : 0; - mDividerAnimationStart = mAdjustedForDivider ? 1 : 0; - mLastAnimationProgress = mAnimationStart; - mLastDividerProgress = mDividerAnimationStart; - } else { - mAnimationStart = mLastAnimationProgress; - mDividerAnimationStart = mLastDividerProgress; - } - mAnimatingForIme = true; - mAnimationStarted = false; - mAnimationTarget = adjustedForIme ? 1 : 0; - mDividerAnimationTarget = adjustedForDivider ? 1 : 0; - - mDisplayContent.beginImeAdjustAnimation(); - - // We put all tasks into drag resizing mode - wait until all of them have completed the - // drag resizing switch. - final Runnable existingWaitingForDrwanCallback = - mService.mWaitingForDrawnCallbacks.get(mService.mRoot); - if (existingWaitingForDrwanCallback != null) { - mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, mService.mRoot); - mService.mH.sendMessageDelayed(mService.mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, - mService.mRoot), - IME_ADJUST_DRAWN_TIMEOUT); - mAnimationStartDelayed = true; - if (imeWin != null) { - - // There might be an old window delaying the animation start - clear it. - if (mDelayedImeWin != null) { - mDelayedImeWin.endDelayingAnimationStart(); - } - mDelayedImeWin = imeWin; - imeWin.startDelayingAnimationStart(); - } - - // If we are already waiting for something to be drawn, clear out the old one so it - // still gets executed. - // TODO: Have a real system where we can wait on different windows to be drawn with - // different callbacks. - existingWaitingForDrwanCallback.run(); - mService.mWaitingForDrawnCallbacks.put(mService.mRoot, () -> { - synchronized (mService.mGlobalLock) { - mAnimationStartDelayed = false; - if (mDelayedImeWin != null) { - mDelayedImeWin.endDelayingAnimationStart(); - } - // If the adjust status changed since this was posted, only notify - // the new states and don't animate. - long duration = 0; - if (mAdjustedForIme == adjustedForIme - && mAdjustedForDivider == adjustedForDivider) { - duration = IME_ADJUST_ANIM_DURATION; - } else { - Slog.w(TAG, "IME adjust changed while waiting for drawn:" - + " adjustedForIme=" + adjustedForIme - + " adjustedForDivider=" + adjustedForDivider - + " mAdjustedForIme=" + mAdjustedForIme - + " mAdjustedForDivider=" + mAdjustedForDivider); - } - notifyAdjustedForImeChanged( - mAdjustedForIme || mAdjustedForDivider, duration); - } - }); - } else { - notifyAdjustedForImeChanged( - adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION); - } - } - - private boolean setMinimizedDockedStack(boolean minimized) { - final ActivityStack stack = mDisplayContent.getRootSplitScreenPrimaryTask(); - notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable()); - return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f); - } - - private boolean isAnimationMaximizing() { - return mAnimationTarget == 0f; - } - - public boolean animate(long now) { - if (mWindow == null) { - return false; - } - if (mAnimatingForMinimizedDockedStack) { - return animateForMinimizedDockedStack(now); - } else if (mAnimatingForIme && !mDisplayContent.mAppTransition.isRunning()) { - // To prevent task stack resize animation may flicking when playing app transition - // animation & IME window enter animation in parallel, make sure app transition is done - // and then start to animate for IME. - return animateForIme(now); - } - return false; - } - - private boolean animateForIme(long now) { - if (!mAnimationStarted || mAnimationStartDelayed) { - mAnimationStarted = true; - mAnimationStartTime = now; - mAnimationDuration = (long) - (IME_ADJUST_ANIM_DURATION * mService.getWindowAnimationScaleLocked()); - } - float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration); - t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR) - .getInterpolation(t); - final boolean updated = - mDisplayContent.animateForIme(t, mAnimationTarget, mDividerAnimationTarget); - if (updated) { - mService.mWindowPlacerLocked.performSurfacePlacement(); - } - if (t >= 1.0f) { - mLastAnimationProgress = mAnimationTarget; - mLastDividerProgress = mDividerAnimationTarget; - mAnimatingForIme = false; - return false; - } else { - return true; - } - } - - private boolean animateForMinimizedDockedStack(long now) { - final ActivityStack stack = mDisplayContent.getRootSplitScreenPrimaryTask(); - if (!mAnimationStarted) { - mAnimationStarted = true; - mAnimationStartTime = now; - notifyDockedStackMinimizedChanged(mMinimizedDock, true /* animate */, - isHomeStackResizable() /* isHomeStackResizable */); - } - float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration); - t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator) - .getInterpolation(t); - if (stack != null) { - if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) { - mService.mWindowPlacerLocked.performSurfacePlacement(); - } - } - if (t >= 1.0f) { - mAnimatingForMinimizedDockedStack = false; - return false; - } else { - return true; - } - } - - float getInterpolatedAnimationValue(float t) { - return t * mAnimationTarget + (1 - t) * mAnimationStart; - } - - float getInterpolatedDividerValue(float t) { - return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart; - } - - /** - * Gets the amount how much to minimize a stack depending on the interpolated fraction t. - */ - private float getMinimizeAmount(ActivityStack stack, float t) { - final float naturalAmount = getInterpolatedAnimationValue(t); - if (isAnimationMaximizing()) { - return adjustMaximizeAmount(stack, t, naturalAmount); - } else { - return naturalAmount; - } - } - - /** - * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount - * during the transition such that the edge of the clip reveal rect is met earlier in the - * transition so we don't create a visible "hole", but only if both the clip reveal and the - * docked stack divider start from about the same portion on the screen. - */ - private float adjustMaximizeAmount(ActivityStack stack, float t, float naturalAmount) { - if (mMaximizeMeetFraction == 1f) { - return naturalAmount; - } - final int minimizeDistance = stack.getMinimizeDistance(); - final float startPrime = mDisplayContent.mAppTransition.getLastClipRevealMaxTranslation() - / (float) minimizeDistance; - final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime; - final float t2 = Math.min(t / mMaximizeMeetFraction, 1); - return amountPrime * t2 + naturalAmount * (1 - t2); - } - - /** - * Retrieves the animation fraction at which the docked stack has to meet the clip reveal - * edge. See {@link #adjustMaximizeAmount}. - */ - private float getClipRevealMeetFraction(ActivityStack stack) { - if (!isAnimationMaximizing() || stack == null || - !mDisplayContent.mAppTransition.hadClipRevealAnimation()) { - return 1f; - } - final int minimizeDistance = stack.getMinimizeDistance(); - final float fraction = Math.abs(mDisplayContent.mAppTransition - .getLastClipRevealMaxTranslation()) / (float) minimizeDistance; - final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN) - / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN))); - return CLIP_REVEAL_MEET_EARLIEST - + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST); - } - - public String toShortString() { - return TAG; - } - - WindowState getWindow() { - return mWindow; - } - - void dump(String prefix, PrintWriter pw) { - pw.println(prefix + "DockedStackDividerController"); - pw.println(prefix + " mLastVisibility=" + mLastVisibility); - pw.println(prefix + " mMinimizedDock=" + mMinimizedDock); - pw.println(prefix + " mAdjustedForIme=" + mAdjustedForIme); - pw.println(prefix + " mAdjustedForDivider=" + mAdjustedForDivider); - } - - void dumpDebug(ProtoOutputStream proto, long fieldId) { - final long token = proto.start(fieldId); - proto.write(MINIMIZED_DOCK, mMinimizedDock); - proto.end(token); - } } diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 9468bff7dff3..54cea938b57b 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -125,10 +125,6 @@ public class RecentsAnimationController implements DeathRecipient { // enabled for it to start intercepting touch events. private boolean mInputConsumerEnabled; - // Whether or not the recents animation should cause the primary split-screen stack to be - // minimized - private boolean mSplitScreenMinimized; - private final Rect mTmpRect = new Rect(); private boolean mLinkedToDeathOfRunner; @@ -277,23 +273,6 @@ public class RecentsAnimationController implements DeathRecipient { } @Override - public void setSplitScreenMinimized(boolean minimized) { - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mService.getWindowManagerLock()) { - if (mCanceled) { - return; - } - - mSplitScreenMinimized = minimized; - mService.checkSplitScreenMinimizedChanged(true /* animate */); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override public void hideCurrentInputMethod() { final long token = Binder.clearCallingIdentity(); try { @@ -738,10 +717,6 @@ public class RecentsAnimationController implements DeathRecipient { } } - boolean isSplitScreenMinimized() { - return mSplitScreenMinimized; - } - boolean isWallpaperVisible(WindowState w) { return w != null && w.mAttrs.type == TYPE_BASE_APPLICATION && ((w.mActivityRecord != null && mTargetActivityRecord == w.mActivityRecord) @@ -944,7 +919,6 @@ public class RecentsAnimationController implements DeathRecipient { pw.print(innerPrefix); pw.println("mPendingAnimations=" + mPendingAnimations.size()); pw.print(innerPrefix); pw.println("mCanceled=" + mCanceled); pw.print(innerPrefix); pw.println("mInputConsumerEnabled=" + mInputConsumerEnabled); - pw.print(innerPrefix); pw.println("mSplitScreenMinimized=" + mSplitScreenMinimized); pw.print(innerPrefix); pw.println("mTargetActivityRecord=" + mTargetActivityRecord); pw.print(innerPrefix); pw.println("isTargetOverWallpaper=" + isTargetOverWallpaper()); pw.print(innerPrefix); pw.println("mRequestDeferCancelUntilNextTransition=" diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 64d7db26cd7e..ada5685e6817 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -258,9 +258,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> */ final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>(); - /** Is dock currently minimized. */ - boolean mIsDockMinimized; - /** Set when a power hint has started, but not ended. */ private boolean mPowerHintSent; @@ -1011,9 +1008,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Send any pending task-info changes that were queued-up during a layout deferment mWmService.mAtmService.mTaskOrganizerController.dispatchPendingTaskInfoChanges(); - if (DEBUG_WINDOW_TRACE) Slog.e(TAG, - "performSurfacePlacementInner exit: animating=" - + mWmService.mAnimator.isAnimating()); + if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit"); } private void checkAppTransitionReady(WindowSurfacePlacer surfacePlacer) { @@ -1989,8 +1984,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // We dismiss the docked stack whenever we switch users. final ActivityStack dockedStack = getDefaultDisplay().getRootSplitScreenPrimaryTask(); if (dockedStack != null) { - mStackSupervisor.moveTasksToFullscreenStackLocked( - dockedStack, dockedStack.isFocusedStackOnDisplay()); + getDefaultDisplay().onSplitScreenModeDismissed(); } // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will // also cause all tasks to be moved to the fullscreen stack at a position that is @@ -2167,21 +2161,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } } - void setDockedStackMinimized(boolean minimized) { - // Get currently focused stack before setting mIsDockMinimized. We do this because if - // split-screen is active, primary stack will not be focusable (see #isFocusable) while - // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null. - final ActivityStack current = getTopDisplayFocusedStack(); - mIsDockMinimized = minimized; - if (mIsDockMinimized) { - if (current.inSplitScreenPrimaryWindowingMode()) { - // The primary split-screen stack can't be focused while it is minimize, so move - // focus to something else. - current.adjustFocusToNextFocusableStack("setDockedStackMinimized"); - } - } - } - ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) { if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r); mTmpFindTaskResult.clear(); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 07e17e8f4048..27acb2356585 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2108,18 +2108,6 @@ class Task extends WindowContainer<WindowContainer> { intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets); } - /** - * Asks docked-divider controller for the smallestwidthdp given bounds. - * @param bounds bounds to calculate smallestwidthdp for. - */ - private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) { - DisplayContent dc = getDisplayContent(); - if (dc != null) { - return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds); - } - return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; - } - void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Configuration parentConfig) { computeConfigResourceOverrides(inOutConfig, parentConfig, null /* compatInsets */); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index fd91bc549f07..b6be386fa181 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -50,7 +50,6 @@ public class WindowAnimator { final WindowManagerPolicy mPolicy; /** Is any window animating? */ - private boolean mAnimating; private boolean mLastRootAnimating; final Choreographer.FrameCallback mAnimationFrameCallback; @@ -135,7 +134,6 @@ public class WindowAnimator { synchronized (mService.mGlobalLock) { mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS; mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; - mAnimating = false; if (DEBUG_WINDOW_TRACE) { Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); } @@ -160,17 +158,12 @@ public class WindowAnimator { final DisplayContent dc = mService.mRoot.getDisplayContent(displayId); dc.checkAppWindowsReadyToShow(); - orAnimating(dc.getDockedDividerController().animate(mCurrentTime)); if (accessibilityController != null) { accessibilityController.drawMagnifiedRegionBorderIfNeededLocked(displayId, mTransaction); } } - if (!mAnimating) { - cancelAnimation(); - } - if (mService.mWatermark != null) { mService.mWatermark.drawIfNeeded(); } @@ -220,7 +213,7 @@ public class WindowAnimator { executeAfterPrepareSurfacesRunnables(); if (DEBUG_WINDOW_TRACE) { - Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating + Slog.i(TAG, "!!! animate: exit" + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams) + " hasPendingLayoutChanges=" + hasPendingLayoutChanges); } @@ -302,10 +295,6 @@ public class WindowAnimator { private class DisplayContentsAnimator { } - boolean isAnimating() { - return mAnimating; - } - boolean isAnimationScheduled() { return mAnimationFrameCallbackScheduled; } @@ -314,14 +303,6 @@ public class WindowAnimator { return mChoreographer; } - void setAnimating(boolean animating) { - mAnimating = animating; - } - - void orAnimating(boolean animating) { - mAnimating |= animating; - } - /** * Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and * the corresponding transaction is closed and applied. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e0f8f0e9aee9..a59eab5959b3 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -42,7 +42,6 @@ import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIV import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static android.view.WindowManager.DOCKED_INVALID; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; @@ -59,7 +58,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; -import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; @@ -214,7 +212,6 @@ import android.view.IDisplayFoldListener; import android.view.IDisplayWindowInsetsController; import android.view.IDisplayWindowListener; import android.view.IDisplayWindowRotationController; -import android.view.IDockedStackListener; import android.view.IInputFilter; import android.view.IOnKeyguardExitResult; import android.view.IPinnedStackListener; @@ -1636,14 +1633,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - // If the window is being added to a stack that's currently adjusted for IME, - // make sure to apply the same adjust to this new window. - win.applyAdjustForImeIfNeeded(); - - if (type == TYPE_DOCK_DIVIDER) { - mRoot.getDisplayContent(displayId).getDockedDividerController().setWindow(win); - } - final WindowStateAnimator winAnimator = win.mWinAnimator; winAnimator.mEnterAnimationPending = true; winAnimator.mEnteringAnimation = true; @@ -2816,16 +2805,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - void setDockedStackCreateStateLocked(int mode, Rect bounds) { - mDockedStackCreateMode = mode; - mDockedStackCreateBounds = bounds; - } - - void checkSplitScreenMinimizedChanged(boolean animate) { - final DisplayContent displayContent = getDefaultDisplayContentLocked(); - displayContent.getDockedDividerController().checkMinimizeChanged(animate); - } - boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) { return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio( aspectRatio); @@ -3295,10 +3274,6 @@ public class WindowManagerService extends IWindowManager.Stub // Notify whether the docked stack exists for the current user final DisplayContent displayContent = getDefaultDisplayContentLocked(); - final ActivityStack stack = - displayContent.getRootSplitScreenPrimaryTask(); - displayContent.mDividerControllerLocked.notifyDockedStackExistsChanged( - stack != null && stack.hasTaskForUser(newUserId)); mRoot.forAllDisplays(dc -> dc.mAppTransition.setCurrentUser(newUserId)); @@ -4687,7 +4662,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int RESET_ANR_MESSAGE = 38; public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39; - public static final int UPDATE_DOCKED_STACK_DIVIDER = 41; + public static final int UPDATE_MULTI_WINDOW_STACKS = 41; public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; @@ -4832,7 +4807,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mGlobalLock) { // Since we're holding both mWindowMap and mAnimator we don't need to // hold mAnimator.mLayoutToAnim. - if (mAnimator.isAnimating() || mAnimator.isAnimationScheduled()) { + if (mAnimator.isAnimationScheduled()) { // If we are animating, don't do the gc now but // delay a bit so we don't interrupt the animation. sendEmptyMessageDelayed(H.FORCE_GC, 2000); @@ -4994,11 +4969,10 @@ public class WindowManagerService extends IWindowManager.Stub } break; } - case UPDATE_DOCKED_STACK_DIVIDER: { + case UPDATE_MULTI_WINDOW_STACKS: { synchronized (mGlobalLock) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); if (displayContent != null) { - displayContent.getDockedDividerController().reevaluateVisibility(false); displayContent.adjustForImeIfNeeded(); } } @@ -6551,11 +6525,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public int getDockedStackSide() { - synchronized (mGlobalLock) { - final ActivityStack dockedStack = getDefaultDisplayContentLocked() - .getRootSplitScreenPrimaryTask(); - return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(); - } + return 0; } void setDockedStackResizing(boolean resizing) { @@ -6572,14 +6542,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - @Override - public void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) { - synchronized (mGlobalLock) { - getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer( - visible, targetWindowingMode, alpha); - } - } - void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) { synchronized (mGlobalLock) { mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays; @@ -6598,17 +6560,6 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void registerDockedStackListener(IDockedStackListener listener) { - mAtmInternal.enforceCallerIsRecentsOrHasPermission(REGISTER_WINDOW_MANAGER_LISTENERS, - "registerDockedStackListener()"); - synchronized (mGlobalLock) { - // TODO(multi-display): The listener is registered on the default display only. - getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener( - listener); - } - } - - @Override public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) { if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerPinnedStackListener()")) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 37597fbc7c45..e452c4a87f50 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1128,7 +1128,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } } else if (mAttrs.type == TYPE_DOCK_DIVIDER) { - dc.getDockedDividerController().positionDockedStackedDivider(windowFrames.mFrame); windowFrames.mContentFrame.set(windowFrames.mFrame); if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) { mMovedByResize = true; @@ -1937,13 +1936,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // animating... let's do something. final int left = mWindowFrames.mFrame.left; final int top = mWindowFrames.mFrame.top; - final Task task = getTask(); - final boolean adjustedForMinimizedDockOrIme = task != null - && (task.getStack().isAdjustedForMinimizedDockedStack() - || task.getStack().isAdjustedForIme()); if (mToken.okToAnimate() && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 - && !isDragResizing() && !adjustedForMinimizedDockOrIme + && !isDragResizing() && getWindowConfiguration().hasMovementAnimations() && !mWinAnimator.mLastHidden && !mSeamlesslyRotated) { @@ -2250,15 +2245,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } final ActivityStack stack = getRootTask(); - if (stack != null && stack.shouldIgnoreInput()) { + if (stack != null && !stack.isFocusable()) { // Ignore when the stack shouldn't receive input event. // (i.e. the minimized stack in split screen mode.) return false; } - if (PixelFormat.formatHasAlpha(mAttrs.format)) { - // Support legacy use cases where transparent windows can still be ime target with - // FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. + if (PixelFormat.formatHasAlpha(mAttrs.format) && mAttrs.alpha == 0) { + // Support legacy use cases where completely transparent windows can still be ime target + // with FLAG_NOT_FOCUSABLE and ALT_FOCUSABLE_IM set. // Certain apps listen for IME insets using transparent windows and ADJUST_NOTHING to // manually synchronize app content to IME animation b/144619551. // TODO(b/145812508): remove this once new focus management is complete b/141738570 @@ -2412,13 +2407,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - void applyAdjustForImeIfNeeded() { - final Task task = getTask(); - if (task != null && task.getStack() != null && task.getStack().isAdjustedForIme()) { - task.getStack().applyAdjustForImeIfNeeded(task); - } - } - @Override void switchUser(int userId) { super.switchUser(userId); @@ -4308,10 +4296,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - if (mAttrs.type == TYPE_INPUT_METHOD) { - getDisplayContent().mDividerControllerLocked.resetImeHideRequested(); - } - return true; } diff --git a/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java b/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java index 1629ef00b65a..6e7df05e8afe 100644 --- a/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java +++ b/services/tests/uiservicestests/src/com/android/internal/logging/InstanceIdSequenceFake.java @@ -17,7 +17,7 @@ package com.android.internal.logging; /** - * A fake implementation of InstanceIdSequence that returns 0, 1, 2, ... + * A fake implementation of InstanceIdSequence that returns 1, 2, ... */ public class InstanceIdSequenceFake extends InstanceIdSequence { @@ -25,13 +25,13 @@ public class InstanceIdSequenceFake extends InstanceIdSequence { super(instanceIdMax); } - private int mNextId = 0; + private int mNextId = 1; @Override public InstanceId newInstanceId() { synchronized (this) { if (mNextId >= mInstanceIdMax) { - mNextId = 0; + mNextId = 1; } return newInstanceIdInternal(mNextId++); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 29b0df5ff258..b6cdbfb42c2d 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -1163,7 +1163,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(PKG, call.r.getSbn().getPackageName()); assertEquals(0, call.r.getSbn().getId()); assertEquals(tag, call.r.getSbn().getTag()); - assertEquals(0, call.getInstanceId()); // Fake instance IDs are assigned in order + assertEquals(1, call.getInstanceId()); // Fake instance IDs are assigned in order } @Test @@ -1185,14 +1185,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals( NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, mNotificationRecordLogger.get(0).event); - assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); assertTrue(mNotificationRecordLogger.get(1).shouldLogReported); assertEquals( NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED, mNotificationRecordLogger.get(1).event); // Instance ID doesn't change on update of an active notification - assertEquals(0, mNotificationRecordLogger.get(1).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); } @Test @@ -1247,19 +1247,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, mNotificationRecordLogger.get(0).event); assertTrue(mNotificationRecordLogger.get(0).shouldLogReported); - assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); assertEquals( NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL, mNotificationRecordLogger.get(1).event); - assertEquals(0, mNotificationRecordLogger.get(1).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); assertEquals( NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED, mNotificationRecordLogger.get(2).event); assertTrue(mNotificationRecordLogger.get(2).shouldLogReported); // New instance ID because notification was canceled before re-post - assertEquals(1, mNotificationRecordLogger.get(2).getInstanceId()); + assertEquals(2, mNotificationRecordLogger.get(2).getInstanceId()); } @Test @@ -3452,6 +3452,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testStats_dismissalSurface() throws Exception { final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addNotification(r); final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true); @@ -3469,7 +3470,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals( NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD, mNotificationRecordLogger.get(0).event); - assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); } @Test @@ -4343,6 +4344,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord r = generateNotificationRecord( mTestNotificationChannel, 1, null, true); r.setTextChanged(true); + r.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addNotification(r); mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[] @@ -4352,7 +4354,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mNotificationRecordLogger.getCalls().size()); assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_OPEN, mNotificationRecordLogger.get(0).event); - assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(0).getInstanceId()); mService.mNotificationDelegate.onNotificationVisibilityChanged( new NotificationVisibility[]{}, @@ -4363,7 +4365,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(2, mNotificationRecordLogger.getCalls().size()); assertEquals(NotificationRecordLogger.NotificationEvent.NOTIFICATION_CLOSE, mNotificationRecordLogger.get(1).event); - assertEquals(0, mNotificationRecordLogger.get(1).getInstanceId()); + assertEquals(1, mNotificationRecordLogger.get(1).getInstanceId()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java deleted file mode 100644 index 32062080a22c..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.view.WindowManager.DOCKED_BOTTOM; -import static android.view.WindowManager.DOCKED_LEFT; -import static android.view.WindowManager.DOCKED_RIGHT; -import static android.view.WindowManager.DOCKED_TOP; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -@SmallTest -@Presubmit -public class DockedStackDividerControllerTests { - - @Test - public void testIsDockSideAllowedDockTop() { - // Docked top is always allowed - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_TOP, DOCKED_LEFT, - NAV_BAR_BOTTOM, true /* navigationBarCanMove */)); - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_TOP, DOCKED_LEFT, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - } - - @Test - public void testIsDockSideAllowedDockBottom() { - // Cannot dock bottom - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_BOTTOM, DOCKED_LEFT, - NAV_BAR_BOTTOM, true /* navigationBarCanMove */)); - } - - @Test - public void testIsDockSideAllowedNavigationBarMovable() { - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, - NAV_BAR_BOTTOM, true /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, - NAV_BAR_LEFT, true /* navigationBarCanMove */)); - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, - NAV_BAR_RIGHT, true /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, - NAV_BAR_BOTTOM, true /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, - NAV_BAR_RIGHT, true /* navigationBarCanMove */)); - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, - NAV_BAR_LEFT, true /* navigationBarCanMove */)); - } - - @Test - public void testIsDockSideAllowedNavigationBarNotMovable() { - // Navigation bar is not movable such as tablets - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_LEFT, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_TOP, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_LEFT, DOCKED_RIGHT, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_LEFT, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - assertFalse(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_TOP, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - assertTrue(DockedStackDividerController.isDockSideAllowed(DOCKED_RIGHT, DOCKED_RIGHT, - NAV_BAR_BOTTOM, false /* navigationBarCanMove */)); - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index d9c5c4c7dffc..9a898fda4ef3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -17,7 +17,6 @@ package com.android.server.wm; import static android.app.ActivityManager.RECENT_WITH_EXCLUDED; -import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; @@ -978,10 +977,7 @@ public class RecentTasksTest extends ActivityTestsBase { () -> mService.setTaskWindowingMode(taskId, WINDOWING_MODE_FULLSCREEN, false/* toTop */)); assertNotRestoreTask( - () -> mService.setTaskWindowingModeSplitScreenPrimary(taskId, - SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, - false /* toTop */, false /* animate */, null /* initialBounds */, - true /* showRecents */)); + () -> mService.setTaskWindowingModeSplitScreenPrimary(taskId, false /* toTop */)); } @Test @@ -1096,14 +1092,10 @@ public class RecentTasksTest extends ActivityTestsBase { assertSecurityException(expectCallable, () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true)); assertSecurityException(expectCallable, - () -> mService.setTaskWindowingModeSplitScreenPrimary(0, - SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, true, true, new Rect(), true)); + () -> mService.setTaskWindowingModeSplitScreenPrimary(0, true)); assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0)); assertSecurityException(expectCallable, () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect())); - assertSecurityException(expectCallable, - () -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(), - new Rect())); assertSecurityException(expectCallable, () -> mService.getAllStackInfos()); assertSecurityException(expectCallable, () -> mService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED)); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index 71d3194ab0d3..0ef25824df2a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -250,13 +250,12 @@ public class RootActivityContainerTests extends ActivityTestsBase { final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true) .setStack(stack).build(); - // Under split screen primary we should be focusable when not minimized - mRootWindowContainer.setDockedStackMinimized(false); + // Created stacks are focusable by default. assertTrue(stack.isTopActivityFocusable()); assertTrue(activity.isFocusable()); - // Under split screen primary we should not be focusable when minimized - mRootWindowContainer.setDockedStackMinimized(true); + // If the stack is made unfocusable, its activities should inherit that. + stack.setFocusable(false); assertFalse(stack.isTopActivityFocusable()); assertFalse(activity.isFocusable()); @@ -307,33 +306,6 @@ public class RootActivityContainerTests extends ActivityTestsBase { } /** - * Verify split-screen primary stack & task can resized by - * {@link android.app.IActivityTaskManager#resizeDockedStack} as expect. - */ - @Test - public void testResizeDockedStackForSplitScreenPrimary() { - final Rect configSize = new Rect(0, 0, 1000, 1000); - final Rect displayedSize = new Rect(0, 0, 300, 300); - - // Create primary split-screen stack with a task. - final ActivityStack primaryStack = new StackBuilder(mRootWindowContainer) - .setActivityType(ACTIVITY_TYPE_STANDARD) - .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) - .setOnTop(true) - .build(); - final Task task = primaryStack.getTopMostTask(); - - // Resize dock stack. - mService.resizeDockedStack(displayedSize, configSize, null, null, null); - - // Verify dock stack & its task bounds if is equal as resized result. - assertEquals(displayedSize, primaryStack.getDisplayedBounds()); - assertEquals(displayedSize, primaryStack.getDisplayedBounds()); - assertEquals(configSize, primaryStack.getBounds()); - assertEquals(configSize, task.getBounds()); - } - - /** * Verify that home stack would be moved to front when the top activity is Recents. */ @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 2c68cc7a19bf..85e4a1668a35 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -251,9 +251,11 @@ public class WindowStateTests extends WindowTestsBase { // b/145812508: special legacy use-case for transparent/translucent windows. appWindow.mAttrs.format = PixelFormat.TRANSPARENT; + appWindow.mAttrs.alpha = 0; assertTrue(appWindow.canBeImeTarget()); appWindow.mAttrs.format = PixelFormat.OPAQUE; + appWindow.mAttrs.alpha = 1; appWindow.mAttrs.flags &= ~FLAG_ALT_FOCUSABLE_IM; assertFalse(appWindow.canBeImeTarget()); appWindow.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE; @@ -276,8 +278,7 @@ public class WindowStateTests extends WindowTestsBase { spyOn(appWindow); spyOn(controller); spyOn(stack); - doReturn(true).when(controller).isMinimizedDock(); - doReturn(true).when(controller).isHomeStackResizable(); + stack.setFocusable(false); doReturn(stack).when(appWindow).getRootTask(); // Make sure canBeImeTarget is false due to shouldIgnoreInput is true; @@ -619,9 +620,10 @@ public class WindowStateTests extends WindowTestsBase { } @Test - public void testCantReceiveTouchWhenShouldIgnoreInput() { + public void testCantReceiveTouchWhenNotFocusable() { final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0"); - win0.mActivityRecord.getStack().setAdjustedForMinimizedDock(1 /* Any non 0 value works */); + win0.mActivityRecord.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + win0.mActivityRecord.getStack().setFocusable(false); assertTrue(win0.cantReceiveTouchInput()); } } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 07cc2d49d9e5..8e85bb23b5c7 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -1917,7 +1917,19 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser return; } try { - // Adbd will be started by AdbService once Global.ADB_ENABLED is set. + if ((config & UsbManager.FUNCTION_ADB) != 0) { + /** + * Start adbd if ADB function is included in the configuration. + */ + LocalServices.getService(AdbManagerInternal.class) + .startAdbdForTransport(AdbTransportType.USB); + } else { + /** + * Stop adbd otherwise + */ + LocalServices.getService(AdbManagerInternal.class) + .stopAdbdForTransport(AdbTransportType.USB); + } UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest, config, chargingFunctions); mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback, diff --git a/startop/scripts/app_startup/parse_metrics b/startop/scripts/app_startup/parse_metrics index 036609ff02be..3fa1462bc56e 100755 --- a/startop/scripts/app_startup/parse_metrics +++ b/startop/scripts/app_startup/parse_metrics @@ -42,12 +42,14 @@ Usage: launch_application package activity | parse_metrics --package <name> --ti -h, --help usage information (this) -v, --verbose enable extra verbose printing -t, --timeout <sec> how many seconds to timeout when trying to wait for logcat to change + -rfd, --reportfullydrawn wait for report fully drawn (default: off) EOF } DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$DIR/lib/common" +report_fully_drawn="n" package="" activity="" timeout=5 @@ -81,6 +83,11 @@ parse_arguments() { -s|--simulate) simulate="y" ;; + -rfd|--reportfullydrawn) + report_fully_drawn="y" + ;; + + *) echo "Invalid argument: $1" >&2 exit 1 @@ -190,12 +197,15 @@ re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\ parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern" -# 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms -pattern="ActivityTaskManager: Fully drawn ${package}" -#re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*' -re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' +# Only track ReportFullyDrawn with --reportfullydrawn/-rfd flags +if [[ $report_fully_drawn == y ]]; then + # 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms + pattern="ActivityTaskManager: Fully drawn ${package}" + #re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*' + re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' -parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern" + parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern" +fi # also call into package-specific scripts if there are additional metrics if [[ -x "$DIR/metrics/$package" ]]; then diff --git a/startop/scripts/app_startup/run_app_with_prefetch b/startop/scripts/app_startup/run_app_with_prefetch index 92a31c30a12d..31f625334b1e 100755 --- a/startop/scripts/app_startup/run_app_with_prefetch +++ b/startop/scripts/app_startup/run_app_with_prefetch @@ -35,6 +35,7 @@ EOF DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "$DIR/../iorap/common" +report_fully_drawn="n" needs_trace_file="n" input_file="" package="" @@ -70,6 +71,10 @@ parse_arguments() { mode="$2" shift ;; + -rfd|--reportfullydrawn) + report_fully_drawn="y" + shift + ;; -c|--count) count="$2" ((count+=1)) @@ -403,7 +408,11 @@ parse_metrics_header() { join_by ',' "${all_metrics[@]}" } -metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate | parse_metrics_header)" +if [[ $report_fully_drawn == y ]]; then + metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate --reportfullydrawn | parse_metrics_header)" +else + metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate | parse_metrics_header)" +fi # TODO: This loop logic could probably be moved into app_startup_runner.py for ((i=0;i<count;++i)) do @@ -411,6 +420,9 @@ for ((i=0;i<count;++i)) do verbose_print "==== ITERATION $i ====" verbose_print "==========================================" if [[ $mode != "warm" ]]; then + # The package must be killed **before** we drop caches, otherwise pages will stay resident. + verbose_print "Kill package for non-warm start." + remote_pkill "$package" verbose_print "Drop caches for non-warm start." # Drop all caches to get cold starts. adb shell "echo 3 > /proc/sys/vm/drop_caches" @@ -423,7 +435,12 @@ for ((i=0;i<count;++i)) do pre_launch_timestamp="$(logcat_save_timestamp)" # TODO: multiple metrics output. + +if [[ $report_fully_drawn == y ]]; then + total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" --reportfullydrawn | parse_metrics_output)" +else total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" | parse_metrics_output)" +fi if [[ $? -ne 0 ]]; then echo "WARNING: Skip bad result, try iteration again." >&2 diff --git a/startop/scripts/app_startup/run_app_with_prefetch.py b/startop/scripts/app_startup/run_app_with_prefetch.py index 2f1eff2c41f6..2f1eff2c41f6 100644..100755 --- a/startop/scripts/app_startup/run_app_with_prefetch.py +++ b/startop/scripts/app_startup/run_app_with_prefetch.py diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a36df49064d2..31d965463a7e 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -11071,7 +11071,6 @@ public class TelephonyManager { * @param enabled True if enabling the data, otherwise disabling. * @hide */ - @SystemApi @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) public void setPolicyDataEnabled(boolean enabled) { try { @@ -11174,7 +11173,6 @@ public class TelephonyManager { * @param isEnabled {@code true} for enabling; {@code false} for disabling. * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAlwaysReportSignalStrength(boolean isEnabled) { try { diff --git a/wifi/Android.bp b/wifi/Android.bp index e253d6d4f6cb..91174d3c3be2 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -47,7 +47,7 @@ filegroup { // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache // to a separate package. "java/android/net/wifi/WifiNetworkScoreCache.java", - "java/android/net/wifi/WifiOemMigrationHook.java", + "java/android/net/wifi/WifiMigration.java", "java/android/net/wifi/nl80211/*.java", ":libwificond_ipc_aidl", ], diff --git a/wifi/java/android/net/wifi/IScoreChangeCallback.aidl b/wifi/java/android/net/wifi/IScoreChangeCallback.aidl index 462a97844d76..d691f41b2858 100644 --- a/wifi/java/android/net/wifi/IScoreChangeCallback.aidl +++ b/wifi/java/android/net/wifi/IScoreChangeCallback.aidl @@ -16,16 +16,14 @@ package android.net.wifi; -import android.net.NetworkScore; - /** - * Interface for Wi-Fi network score callback. + * Interface for Wi-Fi score callback. * * @hide */ oneway interface IScoreChangeCallback { - void onScoreChange(int sessionId, in NetworkScore score); + void onScoreChange(int sessionId, int score); void onTriggerUpdateOfWifiUsabilityStats(int sessionId); } diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 51927af17888..9256c57ab4b9 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -24,8 +24,6 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.annotations.VisibleForTesting; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; @@ -861,19 +859,7 @@ public class ScanResult implements Parcelable { } } - /** - * Construct an empty scan result. - * - * Test code has a need to construct a ScanResult in a specific state. - * (Note that mocking using Mockito does not work if the object needs to be parceled and - * unparceled.) - * Export a @SystemApi default constructor to allow tests to construct an empty ScanResult - * object. The test can then directly set the fields it cares about. - * - * @hide - */ - @SystemApi - @VisibleForTesting + /** Construct an empty scan result. */ public ScanResult() { } diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index c48e89526ae0..0229b846bc6d 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -1713,7 +1713,7 @@ public class WifiConfiguration implements Parcelable { * @return network disable reason string, or null if the reason is invalid. */ @Nullable - public static String getNetworkDisableReasonString( + public static String getNetworkSelectionDisableReasonString( @NetworkSelectionDisableReason int reason) { DisableReasonInfo info = DISABLE_REASON_INFOS.get(reason); if (info == null) { @@ -1727,8 +1727,8 @@ public class WifiConfiguration implements Parcelable { * @return current network disable reason in String (for debug purpose) * @hide */ - public String getNetworkDisableReasonString() { - return getNetworkDisableReasonString(mNetworkSelectionDisableReason); + public String getNetworkSelectionDisableReasonString() { + return getNetworkSelectionDisableReasonString(mNetworkSelectionDisableReason); } /** @@ -2189,17 +2189,21 @@ public class WifiConfiguration implements Parcelable { sbuf.append(" NetworkSelectionStatus ") - .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n"); + .append(mNetworkSelectionStatus.getNetworkStatusString()) + .append("\n"); if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { sbuf.append(" mNetworkSelectionDisableReason ") - .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n"); + .append(mNetworkSelectionStatus.getNetworkSelectionDisableReasonString()) + .append("\n"); for (int index = NetworkSelectionStatus.DISABLED_NONE; index < NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { - sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index) - + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index) - + "\n"); + sbuf.append( + NetworkSelectionStatus.getNetworkSelectionDisableReasonString(index)) + .append(" counter:") + .append(mNetworkSelectionStatus.getDisableReasonCounter(index)) + .append("\n"); } } } diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 0c306b4fb8cc..142854a9e41b 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -28,8 +28,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import com.android.internal.annotations.VisibleForTesting; - import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; @@ -380,20 +378,7 @@ public class WifiInfo implements Parcelable { } } - /** - * WifiInfo exports an immutable public API. - * However, test code has a need to construct a WifiInfo in a specific state. - * (Note that mocking using Mockito does not work if the object needs to be parceled and - * unparceled.) - * Export a @SystemApi Builder to allow tests to construct a WifiInfo object - * in the desired state, without sacrificing WifiInfo's immutability. - * - * @hide - */ - // This builder was not made public to reduce confusion for external developers as there are - // no legitimate uses for this builder except for testing. - @SystemApi - @VisibleForTesting + /** Builder for WifiInfo */ public static final class Builder { private final WifiInfo mWifiInfo = new WifiInfo(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index b1a4cac5864a..dece8559d70c 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -39,7 +39,6 @@ import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.MacAddress; import android.net.Network; -import android.net.NetworkScore; import android.net.NetworkStack; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; @@ -5994,11 +5993,10 @@ public class WifiManager { * * @param sessionId The ID to indicate current Wi-Fi network connection obtained from * {@link WifiConnectedNetworkScorer#start(int)}. - * @param score The {@link android.net.NetworkScore} object representing the - * characteristics of current Wi-Fi network. Populated by connected network - * scorer in applications. + * @param score The score representing link quality of current Wi-Fi network connection. + * Populated by connected network scorer in applications.. */ - void onScoreChange(int sessionId, @NonNull NetworkScore score); + void onScoreChange(int sessionId, int score); /** * Called by applications to trigger an update of {@link WifiUsabilityStatsEntry}. @@ -6024,7 +6022,7 @@ public class WifiManager { } @Override - public void onScoreChange(int sessionId, @NonNull NetworkScore score) { + public void onScoreChange(int sessionId, int score) { try { mScoreChangeCallback.onScoreChange(sessionId, score); } catch (RemoteException e) { diff --git a/wifi/java/android/net/wifi/WifiOemMigrationHook.java b/wifi/java/android/net/wifi/WifiMigration.java index 5301dd013363..a3482d732a1b 100755 --- a/wifi/java/android/net/wifi/WifiOemMigrationHook.java +++ b/wifi/java/android/net/wifi/WifiMigration.java @@ -34,9 +34,9 @@ import java.util.List; * @hide */ @SystemApi -public final class WifiOemMigrationHook { +public final class WifiMigration { - private WifiOemMigrationHook() { } + private WifiMigration() { } /** * Container for all the wifi config data to migrate. @@ -161,16 +161,16 @@ public final class WifiOemMigrationHook { * Load data from OEM's config store. * <p> * Note: - * <li> OEM's need to implement {@link #loadFromConfigStore()} ()} only if their - * existing config store format or file locations differs from the vanilla AOSP implementation ( - * which is what the wifi mainline module understands). + * <li>OEMs need to implement {@link #loadFromConfigStore()} ()} only if their + * existing config store format or file locations differs from the vanilla AOSP implementation. * </li> - * <li> The wifi mainline module will invoke {@link #loadFromConfigStore()} method on every + * <li>The wifi mainline module will invoke {@link #loadFromConfigStore()} method on every * bootup, its the responsibility of the OEM implementation to ensure that this method returns * non-null data only on the first bootup. Once the migration is done, the OEM can safely delete - * their config store files and then return null on any subsequent reboots. The first & only - * relevant invocation of {@link #loadFromConfigStore()} occurs when a previously released - * device upgrades to the wifi mainline module from an OEM implementation of the wifi stack. + * their config store files when {@link #removeConfigStore()} is invoked. + * <li>The first & only relevant invocation of {@link #loadFromConfigStore()} occurs when a + * previously released device upgrades to the wifi mainline module from an OEM implementation + * of the wifi stack. * </li> * * @return Instance of {@link ConfigStoreMigrationData} for migrating data, null if no @@ -178,11 +178,27 @@ public final class WifiOemMigrationHook { */ @Nullable public static ConfigStoreMigrationData loadFromConfigStore() { - // Note: OEM's should add code to parse data from their config store format here! + // Note: OEMs should add code to parse data from their config store format here! return null; } /** + * Remove OEM's config store. + * <p> + * Note: + * <li>OEMs need to implement {@link #removeConfigStore()} only if their + * existing config store format or file locations differs from the vanilla AOSP implementation ( + * which is what the wifi mainline module understands). + * </li> + * <li> The wifi mainline module will invoke {@link #removeConfigStore()} after it migrates + * all the existing data retrieved from {@link #loadFromConfigStore()}. + * </li> + */ + public static void removeConfigStore() { + // Note: OEMs should remove their custom config store files here! + } + + /** * Container for all the wifi settings data to migrate. */ public static final class SettingsMigrationData implements Parcelable { diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index a854a4ba3ae5..6dbb0bd757d8 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -753,7 +753,7 @@ public final class WifiNetworkSuggestion implements Parcelable { boolean isUserInteractionRequired, boolean isUserAllowedToManuallyConnect, boolean isInitialAutoJoinEnabled, - boolean isNetworkUntrusted) { + boolean isNetworkUntrusted) { checkNotNull(networkConfiguration); this.wifiConfiguration = networkConfiguration; this.passpointConfiguration = passpointConfiguration; @@ -858,13 +858,106 @@ public final class WifiNetworkSuggestion implements Parcelable { } /** + * Get the BSSID, or null if unset. + * @see Builder#setBssid(MacAddress) + */ + @Nullable + public MacAddress getBssid() { + if (wifiConfiguration.BSSID == null) { + return null; + } + return MacAddress.fromString(wifiConfiguration.BSSID); + } + + /** @see Builder#setCredentialSharedWithUser(boolean) */ + public boolean isCredentialSharedWithUser() { + return isUserAllowedToManuallyConnect; + } + + /** @see Builder#setIsAppInteractionRequired(boolean) */ + public boolean isAppInteractionRequired() { + return isAppInteractionRequired; + } + + /** @see Builder#setIsEnhancedOpen(boolean) */ + public boolean isEnhancedOpen() { + return wifiConfiguration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE); + } + + /** @see Builder#setIsHiddenSsid(boolean) */ + public boolean isHiddenSsid() { + return wifiConfiguration.hiddenSSID; + } + + /** @see Builder#setIsInitialAutojoinEnabled(boolean) */ + public boolean isInitialAutojoinEnabled() { + return isInitialAutoJoinEnabled; + } + + /** @see Builder#setIsMetered(boolean) */ + public boolean isMetered() { + return wifiConfiguration.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED; + } + + /** @see Builder#setIsUserInteractionRequired(boolean) */ + public boolean isUserInteractionRequired() { + return isUserInteractionRequired; + } + + /** * Get the {@link PasspointConfiguration} associated with this Suggestion, or null if this * Suggestion is not for a Passpoint network. - * @hide */ - @SystemApi @Nullable - public PasspointConfiguration getPasspointConfiguration() { + public PasspointConfiguration getPasspointConfig() { return passpointConfiguration; } + + /** @see Builder#setPriority(int) */ + @IntRange(from = 0) + public int getPriority() { + return wifiConfiguration.priority; + } + + /** + * Return the SSID of the network, or null if this is a Passpoint network. + * @see Builder#setSsid(String) + */ + @Nullable + public String getSsid() { + if (wifiConfiguration.SSID == null) { + return null; + } + return WifiInfo.sanitizeSsid(wifiConfiguration.SSID); + } + + /** @see Builder#setUntrusted(boolean) */ + public boolean isUntrusted() { + return isNetworkUntrusted; + } + + /** + * Get the WifiEnterpriseConfig, or null if unset. + * @see Builder#setWapiEnterpriseConfig(WifiEnterpriseConfig) + * @see Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig) + * @see Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig) + */ + @Nullable + public WifiEnterpriseConfig getEnterpriseConfig() { + return wifiConfiguration.enterpriseConfig; + } + + /** + * Get the passphrase, or null if unset. + * @see Builder#setWapiPassphrase(String) + * @see Builder#setWpa2Passphrase(String) + * @see Builder#setWpa3Passphrase(String) + */ + @Nullable + public String getPassphrase() { + if (wifiConfiguration.preSharedKey == null) { + return null; + } + return WifiInfo.removeDoubleQuotes(wifiConfiguration.preSharedKey); + } } |