diff options
33 files changed, 818 insertions, 336 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 213ea3125c69..9a24181d18f5 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4755,6 +4755,21 @@ package android.net.wifi { method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String); } + public final class SoftApInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getBandwidth(); + method public int getFrequency(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6 + field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2 + field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1 + field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3 + field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4 + field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5 + field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR; + } + public final class WifiClient implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.net.MacAddress getMacAddress(); diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index b1fd4e5e699e..af1a51f68d71 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -47,8 +47,6 @@ public class FeatureFlagUtils { static { DEFAULT_FLAGS = new HashMap<>(); DEFAULT_FLAGS.put("settings_audio_switcher", "true"); - DEFAULT_FLAGS.put("settings_mobile_network_v2", "true"); - DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true"); DEFAULT_FLAGS.put("settings_systemui_theme", "true"); DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false"); DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false"); diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 317469e58245..73f549a31bac 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -38,25 +38,6 @@ oneway interface IStatusBar void showWirelessChargingAnimation(int batteryLevel); - /** - * Notifies System UI side of a visibility flag change on the specified display. - * - * @param displayId the id of the display to notify - * @param vis the visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will be reported - * separately in fullscreenStackVis and dockedStackVis - * @param fullscreenStackVis the flags which only apply in the region of the fullscreen stack, - * which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR - * @param dockedStackVis the flags that only apply in the region of the docked stack, which is - * currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR - * @param mask which flags to change - * @param fullscreenBounds the current bounds of the fullscreen stack, in screen coordinates - * @param dockedBounds the current bounds of the docked stack, in screen coordinates - * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME. - */ - void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis, - int mask, in Rect fullscreenBounds, in Rect dockedBounds, - boolean navbarColorManagedByIme); - void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive); void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition, boolean showImeSwitcher, boolean isMultiClientImeEnabled); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index d703b86d6c8d..3f08710bb17f 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -77,7 +77,6 @@ interface IStatusBarService void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply, in int notificationLocation, boolean modifiedBeforeSending); void onNotificationSettingsViewed(String key); - void setSystemUiVisibility(int displayId, int vis, int mask, String cause); void onNotificationBubbleChanged(String key, boolean isBubble); void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName); void clearInlineReplyUriPermissions(String key); diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java index 4c3f04b10892..9095f05543da 100644 --- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java +++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java @@ -16,53 +16,50 @@ package com.android.internal.statusbar; -import android.graphics.Rect; +import android.annotation.NonNull; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; +import com.android.internal.view.AppearanceRegion; + /** * An immutable data object to return a set of values from StatusBarManagerService to its clients. */ public final class RegisterStatusBarResult implements Parcelable { public final ArrayMap<String, StatusBarIcon> mIcons; - public final int mDisabledFlags1; // switch[0] - public final int mSystemUiVisibility; // switch[1] - public final int mImeWindowVis; // switch[3] - public final int mImeBackDisposition; // switch[4] - public final boolean mShowImeSwitcher; // switch[5] - public final int mDisabledFlags2; // switch[6] - public final int mFullscreenStackSysUiVisibility; // switch[7] - public final int mDockedStackSysUiVisibility; // switch[8] + public final int mDisabledFlags1; // switch[0] + public final int mAppearance; // switch[1] + public final AppearanceRegion[] mAppearanceRegions; // switch[2] + public final int mImeWindowVis; // switch[3] + public final int mImeBackDisposition; // switch[4] + public final boolean mShowImeSwitcher; // switch[5] + public final int mDisabledFlags2; // switch[6] public final IBinder mImeToken; - public final Rect mFullscreenStackBounds; - public final Rect mDockedStackBounds; public final boolean mNavbarColorManagedByIme; public final boolean mAppFullscreen; public final boolean mAppImmersive; + public final int[] mTransientBarTypes; public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1, - int systemUiVisibility, int imeWindowVis, int imeBackDisposition, - boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility, - int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds, - Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen, - boolean appImmersive) { + int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis, + int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken, + boolean navbarColorManagedByIme, boolean appFullscreen, boolean appImmersive, + @NonNull int[] transientBarTypes) { mIcons = new ArrayMap<>(icons); mDisabledFlags1 = disabledFlags1; - mSystemUiVisibility = systemUiVisibility; + mAppearance = appearance; + mAppearanceRegions = appearanceRegions; mImeWindowVis = imeWindowVis; mImeBackDisposition = imeBackDisposition; mShowImeSwitcher = showImeSwitcher; mDisabledFlags2 = disabledFlags2; - mFullscreenStackSysUiVisibility = fullscreenStackSysUiVisibility; - mDockedStackSysUiVisibility = dockedStackSysUiVisibility; mImeToken = imeToken; - mFullscreenStackBounds = fullscreenStackBounds; - mDockedStackBounds = dockedStackBounds; mNavbarColorManagedByIme = navbarColorManagedByIme; mAppFullscreen = appFullscreen; mAppImmersive = appImmersive; + mTransientBarTypes = transientBarTypes; } @Override @@ -74,19 +71,17 @@ public final class RegisterStatusBarResult implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeTypedArrayMap(mIcons, flags); dest.writeInt(mDisabledFlags1); - dest.writeInt(mSystemUiVisibility); + dest.writeInt(mAppearance); + dest.writeParcelableArray(mAppearanceRegions, 0); dest.writeInt(mImeWindowVis); dest.writeInt(mImeBackDisposition); dest.writeBoolean(mShowImeSwitcher); dest.writeInt(mDisabledFlags2); - dest.writeInt(mFullscreenStackSysUiVisibility); - dest.writeInt(mDockedStackSysUiVisibility); dest.writeStrongBinder(mImeToken); - dest.writeTypedObject(mFullscreenStackBounds, flags); - dest.writeTypedObject(mDockedStackBounds, flags); dest.writeBoolean(mNavbarColorManagedByIme); dest.writeBoolean(mAppFullscreen); dest.writeBoolean(mAppImmersive); + dest.writeIntArray(mTransientBarTypes); } /** @@ -99,24 +94,22 @@ public final class RegisterStatusBarResult implements Parcelable { final ArrayMap<String, StatusBarIcon> icons = source.createTypedArrayMap(StatusBarIcon.CREATOR); final int disabledFlags1 = source.readInt(); - final int systemUiVisibility = source.readInt(); + final int appearance = source.readInt(); + final AppearanceRegion[] appearanceRegions = + source.readParcelableArray(null, AppearanceRegion.class); final int imeWindowVis = source.readInt(); final int imeBackDisposition = source.readInt(); final boolean showImeSwitcher = source.readBoolean(); final int disabledFlags2 = source.readInt(); - final int fullscreenStackSysUiVisibility = source.readInt(); - final int dockedStackSysUiVisibility = source.readInt(); final IBinder imeToken = source.readStrongBinder(); - final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR); - final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR); final boolean navbarColorManagedByIme = source.readBoolean(); final boolean appFullscreen = source.readBoolean(); final boolean appImmersive = source.readBoolean(); - return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility, - imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2, - fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken, - fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme, - appFullscreen, appImmersive); + final int[] transientBarTypes = source.createIntArray(); + return new RegisterStatusBarResult(icons, disabledFlags1, appearance, + appearanceRegions, imeWindowVis, imeBackDisposition, showImeSwitcher, + disabledFlags2, imeToken, navbarColorManagedByIme, appFullscreen, + appImmersive, transientBarTypes); } @Override diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java index 0be5009f85f0..9f68ef31c166 100644 --- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java +++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java @@ -18,7 +18,6 @@ package com.android.internal.statusbar; import static com.google.common.truth.Truth.assertThat; -import android.graphics.Rect; import android.os.Binder; import android.os.Parcel; import android.os.UserHandle; @@ -27,6 +26,8 @@ import android.util.ArrayMap; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.internal.view.AppearanceRegion; + import org.junit.Test; import org.junit.runner.RunWith; @@ -47,19 +48,17 @@ public class RegisterStatusBarResultTest { final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap, 0x2 /* disabledFlags1 */, - 0x4 /* systemUiVisibility */, + 0x4 /* appearance */, + new AppearanceRegion[0] /* appearanceRegions */, 0x8 /* imeWindowVis */, 0x10 /* imeBackDisposition */, false /* showImeSwitcher */, 0x20 /* disabledFlags2 */, - 0x40 /* fullscreenStackSysUiVisibility */, - 0x80 /* dockedStackSysUiVisibility */, new Binder() /* imeToken */, - new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */, - new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */, true /* navbarColorManagedByIme */, true /* appFullscreen */, - true /* appImmersive */); + true /* appImmersive */, + new int[0] /* transientBarTypes */); final RegisterStatusBarResult copy = clone(original); @@ -69,21 +68,17 @@ public class RegisterStatusBarResultTest { .isEqualTo(original.mIcons.get(dumyIconKey).user); assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1); - assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility); + assertThat(copy.mAppearance).isEqualTo(original.mAppearance); + assertThat(copy.mAppearanceRegions).isEqualTo(original.mAppearanceRegions); assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis); assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition); assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher); assertThat(copy.mDisabledFlags2).isEqualTo(original.mDisabledFlags2); - assertThat(copy.mFullscreenStackSysUiVisibility) - .isEqualTo(original.mFullscreenStackSysUiVisibility); - assertThat(copy.mDockedStackSysUiVisibility) - .isEqualTo(original.mDockedStackSysUiVisibility); assertThat(copy.mImeToken).isSameAs(original.mImeToken); - assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds); - assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds); assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme); assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen); assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive); + assertThat(copy.mTransientBarTypes).isEqualTo(original.mTransientBarTypes); } private RegisterStatusBarResult clone(RegisterStatusBarResult original) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index b723b752548b..621f101cd8af 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -22,8 +22,6 @@ import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEF import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; -import static android.view.InsetsState.TYPE_NAVIGATION_BAR; -import static android.view.InsetsState.TYPE_TOP_BAR; import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS; @@ -34,7 +32,6 @@ import android.app.StatusBarManager.WindowType; import android.app.StatusBarManager.WindowVisibleState; import android.content.ComponentName; import android.content.Context; -import android.graphics.Rect; import android.hardware.biometrics.IBiometricServiceReceiverInternal; import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService.BackDispositionMode; @@ -45,9 +42,7 @@ import android.os.Looper; import android.os.Message; import android.util.Pair; import android.util.SparseArray; -import android.view.InsetsFlags; import android.view.InsetsState.InternalInsetType; -import android.view.View; import android.view.WindowInsetsController.Appearance; import com.android.internal.os.SomeArgs; @@ -462,42 +457,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } } - // TODO(b/118118435): Remove this function after migration - @Override - public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, - int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, - boolean navbarColorManagedByIme) { - synchronized (mLock) { - final boolean hasDockedStack = !dockedStackBounds.isEmpty(); - final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0; - final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0; - if (transientStatus && transientNavigation) { - showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR}); - } else if (transientStatus) { - showTransient(displayId, new int[]{TYPE_TOP_BAR}); - abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR}); - } else if (transientNavigation) { - showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR}); - abortTransient(displayId, new int[]{TYPE_TOP_BAR}); - } else { - abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR}); - } - SomeArgs args = SomeArgs.obtain(); - args.argi1 = displayId; - args.argi2 = InsetsFlags.getAppearance(vis); - args.argi3 = navbarColorManagedByIme ? 1 : 0; - final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis); - final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis); - args.arg1 = hasDockedStack - ? new AppearanceRegion[]{ - new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds), - new AppearanceRegion(dockedAppearance, dockedStackBounds)} - : new AppearanceRegion[]{ - new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)}; - mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget(); - } - } - @Override public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) { synchronized (mLock) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java index 2e776e39b54c..1532c4f977e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java @@ -247,7 +247,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("LightBarController: "); - pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString( + pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString( InsetsFlags.class, "appearance", mAppearance)); final int numStacks = mAppearanceRegions.length; for (int i = 0; i < numStacks; i++) { 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 b0104d65a278..cff282472074 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -24,7 +24,6 @@ import static android.app.StatusBarManager.WindowType; import static android.app.StatusBarManager.WindowVisibleState; import static android.app.StatusBarManager.windowStateToString; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; -import static android.view.InsetsFlags.getAppearance; import static android.view.InsetsState.TYPE_TOP_BAR; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; @@ -856,19 +855,11 @@ public class StatusBar extends SystemUI implements DemoMode, // Set up the initial notification state. This needs to happen before CommandQueue.disable() setUpPresenter(); - if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) { + if (containsType(result.mTransientBarTypes, TYPE_TOP_BAR)) { showTransientUnchecked(); } - final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility); - final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility); - final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty() - ? new AppearanceRegion[]{ - new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)} - : new AppearanceRegion[]{ - new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds), - new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)}; - onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility), - appearanceRegions, result.mNavbarColorManagedByIme); + onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions, + result.mNavbarColorManagedByIme); mAppFullscreen = result.mAppFullscreen; mAppImmersive = result.mAppImmersive; @@ -888,7 +879,7 @@ public class StatusBar extends SystemUI implements DemoMode, "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x", numIcons, result.mDisabledFlags1, - result.mSystemUiVisibility, + result.mAppearance, result.mImeWindowVis)); } diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 193e0afc529e..c25e206d9104 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1316,7 +1316,6 @@ public class MediaSessionService extends SystemService implements Monitor { * pressed. * * @param packageName The caller's package name, obtained by Context#getPackageName() - * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName() * @param sessionToken token for the session that the controller is pointing to * @param keyEvent media key event * @see #dispatchVolumeKeyEvent @@ -1330,15 +1329,15 @@ public class MediaSessionService extends SystemService implements Monitor { try { synchronized (mLock) { MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken); - if (record == null) { - Log.w(TAG, "Failed to find session to dispatch key event."); - return false; - } - if (DEBUG) { + if (DEBUG_KEY_EVENT) { Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg=" + packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event=" + keyEvent + ", session=" + record); } + if (record == null) { + Log.w(TAG, "Failed to find session to dispatch key event."); + return false; + } return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */, keyEvent, 0, null); } @@ -1688,6 +1687,12 @@ public class MediaSessionService extends SystemService implements Monitor { try { synchronized (mLock) { MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken); + if (DEBUG_KEY_EVENT) { + Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg=" + + packageName + ", opPkg=" + opPackageName + ", pid=" + pid + + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event=" + + keyEvent + ", session=" + record); + } if (record == null) { Log.w(TAG, "Failed to find session to dispatch key event, token=" + sessionToken + ". Fallbacks to the default handling."); @@ -1695,12 +1700,6 @@ public class MediaSessionService extends SystemService implements Monitor { keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE, false); return; } - if (DEBUG) { - Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg=" - + packageName + ", opPkg=" + opPackageName + ", pid=" + pid - + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event=" - + keyEvent + ", session=" + record); - } switch (keyEvent.getAction()) { case KeyEvent.ACTION_DOWN: { int direction = 0; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index ec64ee6d52de..b6934c9ce604 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -16,7 +16,6 @@ package com.android.server.statusbar; -import android.graphics.Rect; import android.os.Bundle; import android.view.InsetsState.InternalInsetType; import android.view.WindowInsetsController.Appearance; @@ -79,9 +78,7 @@ public interface StatusBarManagerInternal { void startAssist(Bundle args); void onCameraLaunchGestureDetected(int source); void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive); - void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis, - int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme, - String cause); + void setDisableFlags(int displayId, int flags, String cause); void toggleSplitScreen(); void appTransitionFinished(int displayId); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index effeb80298b8..25c41f5cdd6b 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -25,7 +25,6 @@ import android.app.Notification; import android.app.StatusBarManager; import android.content.ComponentName; import android.content.Context; -import android.graphics.Rect; import android.hardware.biometrics.IBiometricServiceReceiverInternal; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; @@ -43,10 +42,11 @@ import android.os.UserHandle; import android.service.notification.NotificationStats; import android.text.TextUtils; import android.util.ArrayMap; -import android.util.Log; +import android.util.ArraySet; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; +import android.view.InsetsState.InternalInsetType; import android.view.WindowInsetsController.Appearance; import com.android.internal.R; @@ -263,12 +263,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, - int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds, - boolean isNavbarColorManagedByIme, String cause) { - StatusBarManagerService.this.setSystemUiVisibility(displayId, vis, fullscreenStackVis, - dockedStackVis, mask, fullscreenBounds, dockedBounds, isNavbarColorManagedByIme, - cause); + public void setDisableFlags(int displayId, int flags, String cause) { + StatusBarManagerService.this.setDisableFlags(displayId, flags, cause); } @Override @@ -473,7 +469,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @Override public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { - // TODO (b/118118435): save the information to UiState + final UiState state = getUiState(displayId); + if (!state.appearanceEquals(appearance, appearanceRegions, navbarColorManagedByIme)) { + state.setAppearance(appearance, appearanceRegions, navbarColorManagedByIme); + } if (mBar != null) { try { mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions, @@ -483,7 +482,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void showTransient(int displayId, int[] types) { + public void showTransient(int displayId, @InternalInsetType int[] types) { + getUiState(displayId).showTransient(types); if (mBar != null) { try { mBar.showTransient(displayId, types); @@ -492,7 +492,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void abortTransient(int displayId, int[] types) { + public void abortTransient(int displayId, @InternalInsetType int[] types) { + getUiState(displayId).clearTransient(types); if (mBar != null) { try { mBar.abortTransient(displayId, types); @@ -896,54 +897,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } } - @Override - public void setSystemUiVisibility(int displayId, int vis, int mask, String cause) { - final UiState state = getUiState(displayId); - setSystemUiVisibility(displayId, vis, 0, 0, mask, - state.mFullscreenStackBounds, state.mDockedStackBounds, - state.mNavbarColorManagedByIme, cause); - } - - private void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, - int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds, - boolean isNavbarColorManagedByIme, String cause) { + private void setDisableFlags(int displayId, int flags, String cause) { // also allows calls from window manager which is in this process. enforceStatusBarService(); - if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")"); - - synchronized (mLock) { - updateUiVisibilityLocked(displayId, vis, fullscreenStackVis, dockedStackVis, mask, - fullscreenBounds, dockedBounds, isNavbarColorManagedByIme); - disableLocked( - displayId, - mCurrentUserId, - vis & StatusBarManager.DISABLE_MASK, - mSysUiVisToken, - cause, 1); + final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK; + if (unknownFlags != 0) { + Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags), + new RuntimeException()); } - } - private void updateUiVisibilityLocked(final int displayId, final int vis, - final int fullscreenStackVis, final int dockedStackVis, final int mask, - final Rect fullscreenBounds, final Rect dockedBounds, - final boolean isNavbarColorManagedByIme) { - final UiState state = getUiState(displayId); - if (!state.systemUiStateEquals(vis, fullscreenStackVis, dockedStackVis, - fullscreenBounds, dockedBounds, isNavbarColorManagedByIme)) { - state.setSystemUiState(vis, fullscreenStackVis, dockedStackVis, fullscreenBounds, - dockedBounds, isNavbarColorManagedByIme); - mHandler.post(() -> { - if (mBar != null) { - try { - mBar.setSystemUiVisibility(displayId, vis, fullscreenStackVis, - dockedStackVis, mask, fullscreenBounds, dockedBounds, - isNavbarColorManagedByIme); - } catch (RemoteException ex) { - Log.w(TAG, "Can not get StatusBar!"); - } - } - }); + if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")"); + + synchronized (mLock) { + disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1); } } @@ -965,11 +932,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } private class UiState { - private int mSystemUiVisibility = 0; - private int mFullscreenStackSysUiVisibility = 0; - private int mDockedStackSysUiVisibility = 0; - private final Rect mFullscreenStackBounds = new Rect(); - private final Rect mDockedStackBounds = new Rect(); + private @Appearance int mAppearance = 0; + private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; + private ArraySet<Integer> mTransientBarTypes = new ArraySet<>(); + private boolean mNavbarColorManagedByIme = false; private boolean mFullscreen = false; private boolean mImmersive = false; private int mDisabled1 = 0; @@ -978,53 +944,63 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private int mImeBackDisposition = 0; private boolean mShowImeSwitcher = false; private IBinder mImeToken = null; - private boolean mNavbarColorManagedByIme = false; - private int getDisabled1() { - return mDisabled1; + private void setAppearance(@Appearance int appearance, + AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { + mAppearance = appearance; + mAppearanceRegions = appearanceRegions; + mNavbarColorManagedByIme = navbarColorManagedByIme; } - private int getDisabled2() { - return mDisabled2; + private boolean appearanceEquals(@Appearance int appearance, + AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) { + if (mAppearance != appearance || mAppearanceRegions.length != appearanceRegions.length + || mNavbarColorManagedByIme != navbarColorManagedByIme) { + return false; + } + for (int i = appearanceRegions.length - 1; i >= 0; i--) { + if (!mAppearanceRegions[i].equals(appearanceRegions[i])) { + return false; + } + } + return true; } - private void setDisabled(int disabled1, int disabled2) { - mDisabled1 = disabled1; - mDisabled2 = disabled2; + private void showTransient(@InternalInsetType int[] types) { + for (int type : types) { + mTransientBarTypes.add(type); + } + } + + private void clearTransient(@InternalInsetType int[] types) { + for (int type : types) { + mTransientBarTypes.remove(type); + } } private void setFullscreen(boolean isFullscreen) { mFullscreen = isFullscreen; } - private void setImmersive(boolean immersive) { - mImmersive = immersive; + private void setImmersive(boolean isImmersive) { + mImmersive = isImmersive; } - private boolean disableEquals(int disabled1, int disabled2) { - return mDisabled1 == disabled1 && mDisabled2 == disabled2; + private int getDisabled1() { + return mDisabled1; } - private void setSystemUiState(final int vis, final int fullscreenStackVis, - final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds, - final boolean navbarColorManagedByIme) { - mSystemUiVisibility = vis; - mFullscreenStackSysUiVisibility = fullscreenStackVis; - mDockedStackSysUiVisibility = dockedStackVis; - mFullscreenStackBounds.set(fullscreenBounds); - mDockedStackBounds.set(dockedBounds); - mNavbarColorManagedByIme = navbarColorManagedByIme; + private int getDisabled2() { + return mDisabled2; } - private boolean systemUiStateEquals(final int vis, final int fullscreenStackVis, - final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds, - final boolean navbarColorManagedByIme) { - return mSystemUiVisibility == vis - && mFullscreenStackSysUiVisibility == fullscreenStackVis - && mDockedStackSysUiVisibility == dockedStackVis - && mFullscreenStackBounds.equals(fullscreenBounds) - && mDockedStackBounds.equals(dockedBounds) - && mNavbarColorManagedByIme == navbarColorManagedByIme; + private void setDisabled(int disabled1, int disabled2) { + mDisabled1 = disabled1; + mDisabled2 = disabled2; + } + + private boolean disableEquals(int disabled1, int disabled2) { + return mDisabled1 == disabled1 && mDisabled2 == disabled2; } private void setImeWindowState(final int vis, final int backDisposition, @@ -1084,13 +1060,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D // TODO(b/118592525): Currently, status bar only works on the default display. // Make it aware of multi-display if needed. final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY); + final int[] transientBarTypes = new int[state.mTransientBarTypes.size()]; + for (int i = 0; i < transientBarTypes.length; i++) { + transientBarTypes[i] = state.mTransientBarTypes.valueAt(i); + } return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1), - state.mSystemUiVisibility, state.mImeWindowVis, + state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis, state.mImeBackDisposition, state.mShowImeSwitcher, - gatherDisableActionsLocked(mCurrentUserId, 2), - state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility, - state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds, - state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive); + gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken, + state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive, + transientBarTypes); } } diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java new file mode 100644 index 000000000000..1d733f53f055 --- /dev/null +++ b/services/core/java/com/android/server/wallpaper/GLHelper.java @@ -0,0 +1,148 @@ +/* + * 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.server.wallpaper; + +import static android.opengl.EGL14.EGL_ALPHA_SIZE; +import static android.opengl.EGL14.EGL_BLUE_SIZE; +import static android.opengl.EGL14.EGL_CONFIG_CAVEAT; +import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION; +import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY; +import static android.opengl.EGL14.EGL_DEPTH_SIZE; +import static android.opengl.EGL14.EGL_GREEN_SIZE; +import static android.opengl.EGL14.EGL_HEIGHT; +import static android.opengl.EGL14.EGL_NONE; +import static android.opengl.EGL14.EGL_NO_CONTEXT; +import static android.opengl.EGL14.EGL_NO_DISPLAY; +import static android.opengl.EGL14.EGL_NO_SURFACE; +import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT; +import static android.opengl.EGL14.EGL_RED_SIZE; +import static android.opengl.EGL14.EGL_RENDERABLE_TYPE; +import static android.opengl.EGL14.EGL_STENCIL_SIZE; +import static android.opengl.EGL14.EGL_WIDTH; +import static android.opengl.EGL14.eglChooseConfig; +import static android.opengl.EGL14.eglCreateContext; +import static android.opengl.EGL14.eglCreatePbufferSurface; +import static android.opengl.EGL14.eglDestroyContext; +import static android.opengl.EGL14.eglDestroySurface; +import static android.opengl.EGL14.eglGetDisplay; +import static android.opengl.EGL14.eglGetError; +import static android.opengl.EGL14.eglInitialize; +import static android.opengl.EGL14.eglMakeCurrent; +import static android.opengl.EGL14.eglTerminate; +import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE; +import static android.opengl.GLES20.glGetIntegerv; + +import android.opengl.EGLConfig; +import android.opengl.EGLContext; +import android.opengl.EGLDisplay; +import android.opengl.EGLSurface; +import android.opengl.GLUtils; +import android.os.SystemProperties; +import android.util.Log; + +class GLHelper { + private static final String TAG = GLHelper.class.getSimpleName(); + private static final int sMaxTextureSize; + + static { + int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0); + sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL(); + } + + private static int retrieveTextureSizeFromGL() { + try { + String err; + + // Before we can retrieve info from GL, + // we have to create EGLContext, EGLConfig and EGLDisplay first. + // We will fail at querying info from GL once one of above failed. + // When this happens, we will use defValue instead. + EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) { + err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()); + throw new RuntimeException(err); + } + + if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) { + err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError()); + throw new RuntimeException(err); + } + + EGLConfig eglConfig = null; + int[] configsCount = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + int[] configSpec = new int[] { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 0, + EGL_STENCIL_SIZE, 0, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE + }; + + if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */, + configs, 0 /* configOffset */, 1 /* config_size */, + configsCount, 0 /* num_configOffset */)) { + err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError()); + throw new RuntimeException(err); + } else if (configsCount[0] > 0) { + eglConfig = configs[0]; + } + + if (eglConfig == null) { + throw new RuntimeException("eglConfig not initialized!"); + } + + int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + EGLContext eglContext = eglCreateContext( + eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */); + + if (eglContext == null || eglContext == EGL_NO_CONTEXT) { + err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()); + throw new RuntimeException(err); + } + + // We create a push buffer temporarily for querying info from GL. + int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE}; + EGLSurface eglSurface = + eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */); + eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); + + // Now, we are ready to query the info from GL. + int[] maxSize = new int[1]; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */); + + // We have got the info we want, release all egl resources. + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(eglDisplay, eglSurface); + eglDestroyContext(eglDisplay, eglContext); + eglTerminate(eglDisplay); + return maxSize[0]; + } catch (RuntimeException e) { + Log.w(TAG, "Retrieve from GL failed", e); + return Integer.MAX_VALUE; + } + } + + static int getMaxTextureSize() { + return sMaxTextureSize; + } +} + diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 3663f4696a27..3cc6428c792b 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -134,6 +134,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub private static final boolean DEBUG = false; private static final boolean DEBUG_LIVE = true; + // This 100MB limitation is defined in RecordingCanvas. + private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; + public static class Lifecycle extends SystemService { private IWallpaperManagerService mService; @@ -572,7 +575,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // Only generate crop for default display. final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY); - Rect cropHint = new Rect(wallpaper.cropHint); + final Rect cropHint = new Rect(wallpaper.cropHint); + final DisplayInfo displayInfo = new DisplayInfo(); + mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo); if (DEBUG) { Slog.v(TAG, "Generating crop for new wallpaper(s): 0x" @@ -618,12 +623,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } // scale if the crop height winds up not matching the recommended metrics - needScale = (wpData.mHeight != cropHint.height()); + needScale = wpData.mHeight != cropHint.height() + || cropHint.height() > GLHelper.getMaxTextureSize() + || cropHint.width() > GLHelper.getMaxTextureSize(); //make sure screen aspect ratio is preserved if width is scaled under screen size if (needScale) { - final DisplayInfo displayInfo = new DisplayInfo(); - mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo); final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height(); final int newWidth = (int) (cropHint.width() * scaleByHeight); if (newWidth < displayInfo.logicalWidth) { @@ -644,14 +649,29 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (!needCrop && !needScale) { // Simple case: the nominal crop fits what we want, so we take // the whole thing and just copy the image file directly. - if (DEBUG) { - Slog.v(TAG, "Null crop of new wallpaper; copying"); + + // TODO: It is not accurate to estimate bitmap size without decoding it, + // may be we can try to remove this optimized way in the future, + // that means, we will always go into the 'else' block. + + // This is just a quick estimation, may be smaller than it is. + long estimateSize = options.outWidth * options.outHeight * 4; + + // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail. + // Please see: RecordingCanvas#throwIfCannotDraw. + if (estimateSize < MAX_BITMAP_SIZE) { + success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile); } - success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile); + if (!success) { wallpaper.cropFile.delete(); // TODO: fall back to default wallpaper in this case } + + if (DEBUG) { + Slog.v(TAG, "Null crop of new wallpaper, estimate size=" + + estimateSize + ", success=" + success); + } } else { // Fancy case: crop and scale. First, we decode and scale down if appropriate. FileOutputStream f = null; @@ -665,49 +685,78 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // We calculate the largest power-of-two under the actual ratio rather than // just let the decode take care of it because we also want to remap where the // cropHint rectangle lies in the decoded [super]rect. - final BitmapFactory.Options scaler; final int actualScale = cropHint.height() / wpData.mHeight; int scale = 1; - while (2*scale < actualScale) { + while (2 * scale <= actualScale) { scale *= 2; } - if (scale > 1) { - scaler = new BitmapFactory.Options(); - scaler.inSampleSize = scale; + options.inSampleSize = scale; + options.inJustDecodeBounds = false; + + final Rect estimateCrop = new Rect(cropHint); + estimateCrop.scale(1f / options.inSampleSize); + final float hRatio = (float) wpData.mHeight / estimateCrop.height(); + final int destHeight = (int) (estimateCrop.height() * hRatio); + final int destWidth = (int) (estimateCrop.width() * hRatio); + + // We estimated an invalid crop, try to adjust the cropHint to get a valid one. + if (destWidth > GLHelper.getMaxTextureSize()) { + int newHeight = (int) (wpData.mHeight / hRatio); + int newWidth = (int) (wpData.mWidth / hRatio); + if (DEBUG) { - Slog.v(TAG, "Downsampling cropped rect with scale " + scale); + Slog.v(TAG, "Invalid crop dimensions, trying to adjust."); } - } else { - scaler = null; + + estimateCrop.set(cropHint); + estimateCrop.left += (cropHint.width() - newWidth) / 2; + estimateCrop.top += (cropHint.height() - newHeight) / 2; + estimateCrop.right = estimateCrop.left + newWidth; + estimateCrop.bottom = estimateCrop.top + newHeight; + cropHint.set(estimateCrop); + estimateCrop.scale(1f / options.inSampleSize); + } + + // We've got the safe cropHint; now we want to scale it properly to + // the desired rectangle. + // That's a height-biased operation: make it fit the hinted height. + final int safeHeight = (int) (estimateCrop.height() * hRatio); + final int safeWidth = (int) (estimateCrop.width() * hRatio); + + if (DEBUG) { + Slog.v(TAG, "Decode parameters:"); + Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop); + Slog.v(TAG, " down sampling=" + options.inSampleSize + + ", hRatio=" + hRatio); + Slog.v(TAG, " dest=" + destWidth + "x" + destHeight); + Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight); + Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize()); } - Bitmap cropped = decoder.decodeRegion(cropHint, scaler); + + Bitmap cropped = decoder.decodeRegion(cropHint, options); decoder.recycle(); if (cropped == null) { Slog.e(TAG, "Could not decode new wallpaper"); } else { - // We've got the extracted crop; now we want to scale it properly to - // the desired rectangle. That's a height-biased operation: make it - // fit the hinted height, and accept whatever width we end up with. - cropHint.offsetTo(0, 0); - cropHint.right /= scale; // adjust by downsampling factor - cropHint.bottom /= scale; - final float heightR = - ((float) wpData.mHeight) / ((float) cropHint.height()); - if (DEBUG) { - Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint); - } - final int destWidth = (int)(cropHint.width() * heightR); + // We are safe to create final crop with safe dimensions now. final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped, - destWidth, wpData.mHeight, true); + safeWidth, safeHeight, true); if (DEBUG) { Slog.v(TAG, "Final extract:"); Slog.v(TAG, " dims: w=" + wpData.mWidth + " h=" + wpData.mHeight); - Slog.v(TAG, " out: w=" + finalCrop.getWidth() + Slog.v(TAG, " out: w=" + finalCrop.getWidth() + " h=" + finalCrop.getHeight()); } + // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail. + // Please see: RecordingCanvas#throwIfCannotDraw. + if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) { + throw new RuntimeException( + "Too large bitmap, limit=" + MAX_BITMAP_SIZE); + } + f = new FileOutputStream(wallpaper.cropFile); bos = new BufferedOutputStream(f, 32*1024); finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos); @@ -1997,6 +2046,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (!isWallpaperSupported(callingPackage)) { return; } + + // Make sure both width and height are not larger than max texture size. + width = Math.min(width, GLHelper.getMaxTextureSize()); + height = Math.min(height, GLHelper.getMaxTextureSize()); + synchronized (mLock) { int userId = UserHandle.getCallingUserId(); WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 6e238b33d8dd..fcfd9ded9ad7 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -144,13 +144,16 @@ import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.InputEventReceiver; +import android.view.InsetsFlags; import android.view.InsetsState; +import android.view.InsetsState.InternalInsetType; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.Surface; import android.view.View; import android.view.ViewRootImpl; import android.view.WindowInsets; +import android.view.WindowInsetsController.Appearance; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; @@ -332,8 +335,6 @@ public class DisplayPolicy { private int mResettingSystemUiFlags = 0; // Bits that we are currently always keeping cleared. private int mForceClearedSystemUiFlags = 0; - private int mLastFullscreenStackSysUiFlags; - private int mLastDockedStackSysUiFlags; private int mLastAppearance; private int mLastFullscreenAppearance; private int mLastDockedAppearance; @@ -3172,11 +3173,6 @@ public class DisplayPolicy { &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); } - final int appearance = win.mAttrs.insetsFlags.appearance; - final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, - mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); - final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, - mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */, mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */, @@ -3190,9 +3186,9 @@ public class DisplayPolicy { final Pair<Integer, Boolean> result = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); final int visibility = result.first; + final int appearance = win.mAttrs.insetsFlags.appearance + | InsetsFlags.getAppearance(visibility); final int diff = visibility ^ mLastSystemUiFlags; - final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; - final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; final InsetsPolicy insetsPolicy = getInsetsPolicy(); final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0 @@ -3205,7 +3201,7 @@ public class DisplayPolicy { | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0 || behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; - if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 + if (diff == 0 && mLastAppearance == appearance && mLastFullscreenAppearance == fullscreenAppearance && mLastDockedAppearance == dockedAppearance @@ -3216,9 +3212,12 @@ public class DisplayPolicy { && mLastDockedStackBounds.equals(mDockedStackBounds)) { return 0; } + + // Obtains which types should show transient and which types should abort transient. + // If there is no transient state change, this pair will contain two empty arrays. + final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags); + mLastSystemUiFlags = visibility; - mLastFullscreenStackSysUiFlags = fullscreenVisibility; - mLastDockedStackSysUiFlags = dockedVisibility; mLastAppearance = appearance; mLastFullscreenAppearance = fullscreenAppearance; mLastDockedAppearance = dockedAppearance; @@ -3240,14 +3239,16 @@ public class DisplayPolicy { StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); if (statusBar != null) { final int displayId = getDisplayId(); - // TODO(b/118118435): disabled flags only - statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility, - dockedVisibility, 0xffffffff, fullscreenStackBounds, - dockedStackBounds, isNavbarColorManagedByIme, win.toString()); - if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) { - statusBar.onSystemBarAppearanceChanged(displayId, appearance, - appearanceRegions, isNavbarColorManagedByIme); + statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK, + win.toString()); + if (transientState.first.length > 0) { + statusBar.showTransient(displayId, transientState.first); } + if (transientState.second.length > 0) { + statusBar.abortTransient(displayId, transientState.second); + } + statusBar.onSystemBarAppearanceChanged(displayId, appearance, + appearanceRegions, isNavbarColorManagedByIme); statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive); // TODO(b/118118435): Remove this after removing system UI visibilities. @@ -3258,23 +3259,28 @@ public class DisplayPolicy { return diff; } - private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { - final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded(); - final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming; - if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) { - // If the top fullscreen-or-dimming window is also the top fullscreen, respect - // its light flag. - vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) - & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; - } else if (statusColorWin != null && statusColorWin.isDimming()) { - // Otherwise if it's dimming, clear the light flag. - vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + private static Pair<int[], int[]> getTransientState(int vis, int oldVis) { + final IntArray typesToShow = new IntArray(0); + final IntArray typesToAbort = new IntArray(0); + updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, TYPE_TOP_BAR, typesToShow, + typesToAbort); + updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT, + InsetsState.TYPE_NAVIGATION_BAR, typesToShow, typesToAbort); + return Pair.create(typesToShow.toArray(), typesToAbort.toArray()); + } + + private static void updateTransientState(int vis, int oldVis, int transientFlag, + @InternalInsetType int type, IntArray typesToShow, IntArray typesToAbort) { + final boolean wasTransient = (oldVis & transientFlag) != 0; + final boolean isTransient = (vis & transientFlag) != 0; + if (!wasTransient && isTransient) { + typesToShow.add(type); + } else if (wasTransient && !isTransient) { + typesToAbort.add(type); } - return vis; } - private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque, + private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque, WindowState opaqueOrDimming) { final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded(); final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming; @@ -3282,7 +3288,10 @@ public class DisplayPolicy { // If the top fullscreen-or-dimming window is also the top fullscreen, respect // its light flag. appearance &= ~APPEARANCE_LIGHT_TOP_BAR; - appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR; + final int legacyAppearance = InsetsFlags.getAppearance( + PolicyControl.getSystemUiVisibility(statusColorWin, null)); + appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance) + & APPEARANCE_LIGHT_TOP_BAR; } else if (statusColorWin != null && statusColorWin.isDimming()) { // Otherwise if it's dimming, clear the light flag. appearance &= ~APPEARANCE_LIGHT_TOP_BAR; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 1d11acd61a68..344befad8fa9 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -638,7 +638,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private boolean mIsDimming = false; private @Nullable InsetsSourceProvider mControllableInsetProvider; - private InsetsState mClientInsetsState = new InsetsState(); + private InsetsState mClientInsetsState; private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; private KeyInterceptionInfo mKeyInterceptionInfo; @@ -767,6 +767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mSeq = seq; mPowerManagerWrapper = powerManagerWrapper; mForceSeamlesslyRotate = token.mRoundedCornerOverlay; + mClientInsetsState = + getDisplayContent().getInsetsStateController().getInsetsForDispatch(this); if (DEBUG) { Slog.v(TAG, "Window " + this + " client=" + c.asBinder() + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index 8c2ae5a7659a..55947ae9626f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -178,11 +178,14 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() { + // Adding app window before setting source visibility is to prevent the visibility from + // being cleared by InsetsSourceProvider.updateVisibility. + final WindowState app = addWindow(TYPE_APPLICATION, "app"); + addWindow(TYPE_STATUS_BAR, "topBar") .getControllableInsetProvider().getSource().setVisible(false); addWindow(TYPE_NAVIGATION_BAR, "navBar") .getControllableInsetProvider().getSource().setVisible(true); - final WindowState app = addWindow(TYPE_APPLICATION, "app"); final InsetsPolicy policy = mDisplayContent.getInsetsPolicy(); policy.updateBarControlTarget(app); diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java index 7d88161a2805..176c7a0ada7b 100644 --- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java +++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java @@ -32,7 +32,7 @@ public class HierrarchicalDataClassBase implements Parcelable { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -98,8 +98,8 @@ public class HierrarchicalDataClassBase implements Parcelable { }; @DataClass.Generated( - time = 1572655992854L, - codegenVersion = "1.0.12", + time = 1573006405823L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java", inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java index c930ce535ab6..e348c77c0ac6 100644 --- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java +++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java @@ -46,7 +46,7 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -120,8 +120,8 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase { }; @DataClass.Generated( - time = 1572655993858L, - codegenVersion = "1.0.12", + time = 1573006406833L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java", inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java index 368a5c3a81e8..112d3df02280 100644 --- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java +++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java @@ -19,6 +19,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import android.util.ArrayMap; import android.util.SparseArray; import android.util.SparseIntArray; @@ -52,7 +53,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable { - // Code below generated by codegen v1.0.12. + + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -410,8 +412,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable { } @DataClass.Generated( - time = 1572655991821L, - codegenVersion = "1.0.12", + time = 1573006404728L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java", inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java index 9d52287d631e..0fdcf5918c81 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java +++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java @@ -342,7 +342,7 @@ public final class SampleDataClass implements Parcelable { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -1872,8 +1872,8 @@ public final class SampleDataClass implements Parcelable { } @DataClass.Generated( - time = 1572655989589L, - codegenVersion = "1.0.12", + time = 1573006402566L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java", inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_UNDEFINED\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java index cef32d1051df..cab477dafae9 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java +++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java @@ -85,7 +85,7 @@ public class SampleWithCustomBuilder implements Parcelable { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -253,8 +253,8 @@ public class SampleWithCustomBuilder implements Parcelable { } @DataClass.Generated( - time = 1572655990725L, - codegenVersion = "1.0.12", + time = 1573006403628L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java", inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java index 27055f6a4df8..6190085a4d82 100644 --- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java +++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java @@ -36,7 +36,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -135,8 +135,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1572655995915L, - codegenVersion = "1.0.12", + time = 1573006408903L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated @@ -160,7 +160,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -259,8 +259,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1572655995924L, - codegenVersion = "1.0.12", + time = 1573006408912L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated @@ -274,7 +274,7 @@ public class SampleWithNestedDataClasses { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -373,8 +373,8 @@ public class SampleWithNestedDataClasses { }; @DataClass.Generated( - time = 1572655995930L, - codegenVersion = "1.0.12", + time = 1573006408917L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java", inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)") @Deprecated diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java index 4bfec895fdcb..5a960d7dd002 100644 --- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java +++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java @@ -51,7 +51,7 @@ public class StaleDataclassDetectorFalsePositivesTest { - // Code below generated by codegen v1.0.12. + // Code below generated by codegen v1.0.13. // // DO NOT MODIFY! // CHECKSTYLE:OFF Generated code @@ -65,8 +65,8 @@ public class StaleDataclassDetectorFalsePositivesTest { @DataClass.Generated( - time = 1572655994865L, - codegenVersion = "1.0.12", + time = 1573006407900L, + codegenVersion = "1.0.13", sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java", inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)") @Deprecated diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt index ed35a1dfc599..ebfbbd8163b5 100644 --- a/tools/codegen/src/com/android/codegen/FieldInfo.kt +++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt @@ -93,6 +93,8 @@ data class FieldInfo( // Generic args val isArray = Type.endsWith("[]") val isList = FieldClass == "List" || FieldClass == "ArrayList" + val isMap = FieldClass == "Map" || FieldClass == "ArrayMap" + || FieldClass == "HashMap" || FieldClass == "LinkedHashMap" val fieldBit = bitAtExpr(index) var isLast = false val isFinal = fieldAst.isFinal @@ -197,7 +199,7 @@ data class FieldInfo( listOf("String", "CharSequence", "Exception", "Size", "SizeF", "Bundle", "FileDescriptor", "SparseBooleanArray", "SparseIntArray", "SparseArray") -> FieldClass - FieldClass == "Map" && fieldTypeGenegicArgs[0] == "String" -> "Map" + isMap && fieldTypeGenegicArgs[0] == "String" -> "Map" isArray -> when { FieldInnerType!! in (PRIMITIVE_TYPES + "String") -> FieldInnerType + "Array" isBinder(FieldInnerType) -> "BinderArray" diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt index c25d0c74f251..dc1f4c50abc4 100644 --- a/tools/codegen/src/com/android/codegen/Generators.kt +++ b/tools/codegen/src/com/android/codegen/Generators.kt @@ -343,7 +343,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) { } } - if (FieldClass.endsWith("Map") && FieldInnerType != null) { + if (isMap && FieldInnerType != null) { generateBuilderMethod( name = adderName, defVisibility = visibility, @@ -351,7 +351,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) { paramNames = listOf("key", "value"), genJavadoc = { +javadocSeeSetter }) { !singularNameCustomizationHint - +"if ($name == null) $setterName(new $LinkedHashMap());" + +"if ($name == null) $setterName(new ${if (FieldClass == "Map") LinkedHashMap else FieldClass}());" +"$name.put(key, value);" +"return$maybeCast this;" } @@ -507,7 +507,8 @@ fun ClassPrinter.generateParcelable() { // Create container if any val containerInitExpr = when { - FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()" + FieldClass == "Map" -> "new $LinkedHashMap<>()" + isMap -> "new $FieldClass()" FieldClass == "List" || FieldClass == "ArrayList" -> "new ${classRef("java.util.ArrayList")}<>()" else -> "" diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt index 339057f24833..85c832fcf34f 100644 --- a/tools/codegen/src/com/android/codegen/SharedConstants.kt +++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt @@ -1,7 +1,7 @@ package com.android.codegen const val CODEGEN_NAME = "codegen" -const val CODEGEN_VERSION = "1.0.12" +const val CODEGEN_VERSION = "1.0.13" const val CANONICAL_BUILDER_CLASS = "Builder" const val BASE_BUILDER_CLASS = "BaseBuilder" diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index 8a252dd1e447..452a655edc7b 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -15,6 +15,7 @@ */ package android.net.wifi; +import android.net.wifi.SoftApInfo; import android.net.wifi.WifiClient; @@ -43,4 +44,11 @@ oneway interface ISoftApCallback * @param clients the currently connected clients */ void onConnectedClientsChanged(in List<WifiClient> clients); + + /** + * Service to manager callback providing information of softap. + * + * @param softApInfo is the softap information. {@link SoftApInfo} + */ + void onInfoChanged(in SoftApInfo softApInfo); } diff --git a/wifi/java/android/net/wifi/SoftApInfo.aidl b/wifi/java/android/net/wifi/SoftApInfo.aidl new file mode 100644 index 000000000000..d4551cfac044 --- /dev/null +++ b/wifi/java/android/net/wifi/SoftApInfo.aidl @@ -0,0 +1,20 @@ +/** + * 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 android.net.wifi; + +parcelable SoftApInfo; + diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java new file mode 100644 index 000000000000..375a9774f570 --- /dev/null +++ b/wifi/java/android/net/wifi/SoftApInfo.java @@ -0,0 +1,211 @@ +/* + * 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 android.net.wifi; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * A class representing information about SoftAp. + * {@see WifiManager} + * + * @hide + */ +@SystemApi +public final class SoftApInfo implements Parcelable { + + /** + * AP Channel bandwidth is invalid. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_INVALID = 0; + + /** + * AP Channel bandwidth is 20 MHZ but no HT. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; + + /** + * AP Channel bandwidth is 20 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_20MHZ = 2; + + /** + * AP Channel bandwidth is 40 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_40MHZ = 3; + + /** + * AP Channel bandwidth is 80 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_80MHZ = 4; + + /** + * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; + + /** + * AP Channel bandwidth is 160 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_160MHZ = 6; + + /** + * @hide + */ + @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = { + CHANNEL_WIDTH_INVALID, + CHANNEL_WIDTH_20MHZ_NOHT, + CHANNEL_WIDTH_20MHZ, + CHANNEL_WIDTH_40MHZ, + CHANNEL_WIDTH_80MHZ, + CHANNEL_WIDTH_80MHZ_PLUS_MHZ, + CHANNEL_WIDTH_160MHZ, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Bandwidth {} + + + /** The frequency which AP resides on. */ + private int mFrequency = 0; + + @Bandwidth + private int mBandwidth = CHANNEL_WIDTH_INVALID; + + /** + * Get the frequency which AP resides on. + */ + public int getFrequency() { + return mFrequency; + } + + /** + * Set the frequency which AP resides on. + * @hide + */ + public void setFrequency(int freq) { + mFrequency = freq; + } + + /** + * Get AP Channel bandwidth. + * + * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, + * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, + * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_UNKNOWN}. + */ + @Bandwidth + public int getBandwidth() { + return mBandwidth; + } + + /** + * Set AP Channel bandwidth. + * @hide + */ + public void setBandwidth(@Bandwidth int bandwidth) { + mBandwidth = bandwidth; + } + + /** + * @hide + */ + public SoftApInfo(@Nullable SoftApInfo source) { + if (source != null) { + mFrequency = source.mFrequency; + mBandwidth = source.mBandwidth; + } + } + + /** + * @hide + */ + public SoftApInfo() { + } + + @Override + /** Implement the Parcelable interface. */ + public int describeContents() { + return 0; + } + + @Override + /** Implement the Parcelable interface */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mFrequency); + dest.writeInt(mBandwidth); + } + + @NonNull + /** Implement the Parcelable interface */ + public static final Creator<SoftApInfo> CREATOR = new Creator<SoftApInfo>() { + public SoftApInfo createFromParcel(Parcel in) { + SoftApInfo info = new SoftApInfo(); + info.mFrequency = in.readInt(); + info.mBandwidth = in.readInt(); + return info; + } + + public SoftApInfo[] newArray(int size) { + return new SoftApInfo[size]; + } + }; + + @NonNull + @Override + public String toString() { + return "SoftApInfo{" + + "bandwidth= " + mBandwidth + + ",frequency= " + mFrequency + + '}'; + } + + @Override + public boolean equals(@NonNull Object o) { + if (this == o) return true; + if (!(o instanceof SoftApInfo)) return false; + SoftApInfo softApInfo = (SoftApInfo) o; + return mFrequency == softApInfo.mFrequency + && mBandwidth == softApInfo.mBandwidth; + } + + @Override + public int hashCode() { + return Objects.hash(mFrequency, mBandwidth); + } +} diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 07831c71b0d3..8108fef5d3ee 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -3315,6 +3315,15 @@ public class WifiManager { * @param clients the currently connected clients */ void onConnectedClientsChanged(@NonNull List<WifiClient> clients); + + /** + * Called when information of softap changes. + * + * @param softApInfo is the softap information. {@link SoftApInfo} + */ + default void onInfoChanged(@NonNull SoftApInfo softApInfo) { + // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. + } } /** @@ -3354,6 +3363,16 @@ public class WifiManager { mCallback.onConnectedClientsChanged(clients); }); } + + @Override + public void onInfoChanged(SoftApInfo softApInfo) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo); + } + mHandler.post(() -> { + mCallback.onInfoChanged(softApInfo); + }); + } } /** diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java new file mode 100644 index 000000000000..929f3ab88fd8 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java @@ -0,0 +1,71 @@ +/* + * 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 android.net.wifi; + +import android.os.Parcel; + +import static org.junit.Assert.assertEquals; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +/** + * Unit tests for {@link android.net.wifi.SoftApInfo}. + */ +@SmallTest +public class SoftApInfoTest { + + /** + * Verifies copy constructor. + */ + @Test + public void testCopyOperator() throws Exception { + SoftApInfo info = new SoftApInfo(); + info.setFrequency(2412); + info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); + + SoftApInfo copiedInfo = new SoftApInfo(info); + + assertEquals(info, copiedInfo); + assertEquals(info.hashCode(), copiedInfo.hashCode()); + } + + /** + * Verifies parcel serialization/deserialization. + */ + @Test + public void testParcelOperation() throws Exception { + SoftApInfo info = new SoftApInfo(); + info.setFrequency(2412); + info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); + + Parcel parcelW = Parcel.obtain(); + info.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + SoftApInfo fromParcel = SoftApInfo.CREATOR.createFromParcel(parcelR); + + assertEquals(info, fromParcel); + assertEquals(info.hashCode(), fromParcel.hashCode()); + } + +} diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index d2516a33fead..14e994cf0f08 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -97,6 +97,8 @@ public class WifiManagerTest { private static final String TEST_PACKAGE_NAME = "TestPackage"; private static final String TEST_COUNTRY_CODE = "US"; private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"}; + private static final int TEST_AP_FREQUENCY = 2412; + private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; @Mock Context mContext; @Mock android.net.wifi.IWifiManager mWifiService; @@ -122,7 +124,6 @@ public class WifiManagerTest { mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); - mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper()); verify(mWifiService).getVerboseLoggingLevel(); } @@ -776,11 +777,34 @@ public class WifiManagerTest { verify(mSoftApCallback).onConnectedClientsChanged(testClients); } + + /* + * Verify client-provided callback is being called through callback proxy + */ + @Test + public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception { + SoftApInfo testSoftApInfo = new SoftApInfo(); + testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); + testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); + ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ISoftApCallback.Stub.class); + mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); + verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), + anyInt()); + + callbackCaptor.getValue().onInfoChanged(testSoftApInfo); + mLooper.dispatchAll(); + verify(mSoftApCallback).onInfoChanged(testSoftApInfo); + } + /* * Verify client-provided callback is being called through callback proxy on multiple events */ @Test public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception { + SoftApInfo testSoftApInfo = new SoftApInfo(); + testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); + testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler); @@ -790,11 +814,13 @@ public class WifiManagerTest { final List<WifiClient> testClients = new ArrayList(); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0); callbackCaptor.getValue().onConnectedClientsChanged(testClients); + callbackCaptor.getValue().onInfoChanged(testSoftApInfo); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); mLooper.dispatchAll(); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0); verify(mSoftApCallback).onConnectedClientsChanged(testClients); + verify(mSoftApCallback).onInfoChanged(testSoftApInfo); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); } |