diff options
32 files changed, 430 insertions, 228 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 71aeff59402f..4382b3207e1e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -18537,6 +18537,23 @@ package android.hardware.camera2.params { package android.hardware.display { + public final class DeviceProductInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getConnectionToSinkType(); + method public int getManufactureWeek(); + method public int getManufactureYear(); + method @NonNull public String getManufacturerPnpId(); + method public int getModelYear(); + method @Nullable public String getName(); + method @NonNull public String getProductId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CONNECTION_TO_SINK_BUILT_IN = 1; // 0x1 + field public static final int CONNECTION_TO_SINK_DIRECT = 2; // 0x2 + field public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; // 0x3 + field public static final int CONNECTION_TO_SINK_UNKNOWN = 0; // 0x0 + field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.DeviceProductInfo> CREATOR; + } + public final class DisplayManager { method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int); method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler); @@ -46613,6 +46630,7 @@ package android.view { method public long getAppVsyncOffsetNanos(); method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point); method @Nullable public android.view.DisplayCutout getCutout(); + method @Nullable public android.hardware.display.DeviceProductInfo getDeviceProductInfo(); method public int getDisplayId(); method public int getFlags(); method public android.view.Display.HdrCapabilities getHdrCapabilities(); diff --git a/core/java/android/hardware/display/DeviceProductInfo.java b/core/java/android/hardware/display/DeviceProductInfo.java index 41126b70c89f..9457d8f1aac4 100644 --- a/core/java/android/hardware/display/DeviceProductInfo.java +++ b/core/java/android/hardware/display/DeviceProductInfo.java @@ -16,40 +16,69 @@ package android.hardware.display; +import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; -import java.util.Arrays; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Product-specific information about the display or the directly connected device on the * display chain. For example, if the display is transitively connected, this field may contain * product information about the intermediate device. - * @hide */ public final class DeviceProductInfo implements Parcelable { + /** @hide */ + @IntDef(prefix = {"CONNECTION_TO_SINK_"}, value = { + CONNECTION_TO_SINK_UNKNOWN, + CONNECTION_TO_SINK_BUILT_IN, + CONNECTION_TO_SINK_DIRECT, + CONNECTION_TO_SINK_TRANSITIVE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ConnectionToSinkType { } + + /** The device connection to the display sink is unknown. */ + public static final int CONNECTION_TO_SINK_UNKNOWN = + IDeviceProductInfoConstants.CONNECTION_TO_SINK_UNKNOWN; + + /** The display sink is built-in to the device */ + public static final int CONNECTION_TO_SINK_BUILT_IN = + IDeviceProductInfoConstants.CONNECTION_TO_SINK_BUILT_IN; + + /** The device is directly connected to the display sink. */ + public static final int CONNECTION_TO_SINK_DIRECT = + IDeviceProductInfoConstants.CONNECTION_TO_SINK_DIRECT; + + /** The device is transitively connected to the display sink. */ + public static final int CONNECTION_TO_SINK_TRANSITIVE = + IDeviceProductInfoConstants.CONNECTION_TO_SINK_TRANSITIVE; + private final String mName; private final String mManufacturerPnpId; private final String mProductId; private final Integer mModelYear; private final ManufactureDate mManufactureDate; - private final int[] mRelativeAddress; + private final @ConnectionToSinkType int mConnectionToSinkType; + /** @hide */ public DeviceProductInfo( String name, String manufacturerPnpId, String productId, Integer modelYear, ManufactureDate manufactureDate, - int[] relativeAddress) { + int connectionToSinkType) { this.mName = name; this.mManufacturerPnpId = manufacturerPnpId; this.mProductId = productId; this.mModelYear = modelYear; this.mManufactureDate = manufactureDate; - this.mRelativeAddress = relativeAddress; + this.mConnectionToSinkType = connectionToSinkType; } private DeviceProductInfo(Parcel in) { @@ -58,12 +87,13 @@ public final class DeviceProductInfo implements Parcelable { mProductId = (String) in.readValue(null); mModelYear = (Integer) in.readValue(null); mManufactureDate = (ManufactureDate) in.readValue(null); - mRelativeAddress = in.createIntArray(); + mConnectionToSinkType = in.readInt(); } /** * @return Display name. */ + @Nullable public String getName() { return mName; } @@ -71,6 +101,7 @@ public final class DeviceProductInfo implements Parcelable { /** * @return Manufacturer Plug and Play ID. */ + @NonNull public String getManufacturerPnpId() { return mManufacturerPnpId; } @@ -78,32 +109,58 @@ public final class DeviceProductInfo implements Parcelable { /** * @return Manufacturer product ID. */ + @NonNull public String getProductId() { return mProductId; } /** - * @return Model year of the device. Typically exactly one of model year or - * manufacture date will be present. + * @return Model year of the device. Return -1 if not available. Typically, + * one of model year or manufacture year is available. */ - public Integer getModelYear() { - return mModelYear; + public int getModelYear() { + return mModelYear != null ? mModelYear : -1; + } + + /** + * @return The year of manufacture, or -1 it is not available. Typically, + * one of model year or manufacture year is available. + */ + public int getManufactureYear() { + if (mManufactureDate == null) { + return -1; + } + return mManufactureDate.mYear != null ? mManufactureDate.mYear : -1; + } + + /** + * @return The week of manufacture, or -1 it is not available. Typically, + * not present if model year is available. + */ + public int getManufactureWeek() { + if (mManufactureDate == null) { + return -1; + } + return mManufactureDate.mWeek != null ? mManufactureDate.mWeek : -1; } /** * @return Manufacture date. Typically exactly one of model year or manufacture * date will be present. + * + * @hide */ public ManufactureDate getManufactureDate() { return mManufactureDate; } /** - * @return Relative address in the display network. For example, for HDMI connected devices this - * can be its physical address. Each component of the address is in the range [0, 255]. + * @return How the current device is connected to the display sink. For example, the display + * can be connected immediately to the device or there can be a receiver in between. */ - public int[] getRelativeAddress() { - return mRelativeAddress; + @ConnectionToSinkType + public int getConnectionToSinkType() { + return mConnectionToSinkType; } @Override @@ -119,8 +176,8 @@ public final class DeviceProductInfo implements Parcelable { + mModelYear + ", manufactureDate=" + mManufactureDate - + ", relativeAddress=" - + Arrays.toString(mRelativeAddress) + + ", connectionToSinkType=" + + mConnectionToSinkType + '}'; } @@ -134,16 +191,16 @@ public final class DeviceProductInfo implements Parcelable { && Objects.equals(mProductId, that.mProductId) && Objects.equals(mModelYear, that.mModelYear) && Objects.equals(mManufactureDate, that.mManufactureDate) - && Arrays.equals(mRelativeAddress, that.mRelativeAddress); + && mConnectionToSinkType == that.mConnectionToSinkType; } @Override public int hashCode() { return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate, - Arrays.hashCode(mRelativeAddress)); + mConnectionToSinkType); } - public static final Creator<DeviceProductInfo> CREATOR = + @NonNull public static final Creator<DeviceProductInfo> CREATOR = new Creator<DeviceProductInfo>() { @Override public DeviceProductInfo createFromParcel(Parcel in) { @@ -162,13 +219,13 @@ public final class DeviceProductInfo implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mName); dest.writeString(mManufacturerPnpId); dest.writeValue(mProductId); dest.writeValue(mModelYear); dest.writeValue(mManufactureDate); - dest.writeIntArray(mRelativeAddress); + dest.writeInt(mConnectionToSinkType); } /** diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 0ba1dfee16f3..8117c963b959 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -34,6 +34,7 @@ import android.graphics.ColorSpace; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; +import android.hardware.display.DeviceProductInfo; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.os.Build; @@ -1181,6 +1182,18 @@ public final class Display { } /** + * Returns the product-specific information about the display or the directly connected + * device on the display chain. + * For example, if the display is transitively connected, this field may contain product + * information about the intermediate device. + * Returns {@code null} if product information is not available. + */ + @Nullable + public DeviceProductInfo getDeviceProductInfo() { + return mDisplayInfo.deviceProductInfo; + } + + /** * Gets display metrics that describe the size and density of this display. * The size returned by this method does not necessarily represent the * actual raw size (native resolution) of the display. diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 7a3366acce27..961d4cb23679 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -27,6 +27,7 @@ #include <android-base/chrono_utils.h> #include <android/graphics/region.h> #include <android/gui/BnScreenCaptureListener.h> +#include <android/hardware/display/IDeviceProductInfoConstants.h> #include <android/os/IInputConstants.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_hardware_HardwareBuffer.h> @@ -999,16 +1000,24 @@ static jobject convertDeviceProductInfoToJavaObject( } else { LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate"); } - auto relativeAddress = env->NewIntArray(info->relativeAddress.size()); - auto relativeAddressData = env->GetIntArrayElements(relativeAddress, nullptr); - for (int i = 0; i < info->relativeAddress.size(); i++) { - relativeAddressData[i] = info->relativeAddress[i]; + jint connectionToSinkType; + // Relative address maps to HDMI physical address. All addresses are 4 digits long allowing + // for a 5–device-deep hierarchy. For more information, refer: + // Section 8.7 - Physical Address of HDMI Specification Version 1.3a + using android::hardware::display::IDeviceProductInfoConstants; + if (info->relativeAddress.size() != 4) { + connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN; + } else if (info->relativeAddress[0] == 0) { + connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN; + } else if (info->relativeAddress[1] == 0) { + connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_DIRECT; + } else { + connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_TRANSITIVE; } - env->ReleaseIntArrayElements(relativeAddress, relativeAddressData, 0); return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name, manufacturerPnpId, productId, modelYear, manufactureDate, - relativeAddress); + connectionToSinkType); } static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) { @@ -1948,7 +1957,7 @@ int register_android_view_SurfaceControl(JNIEnv* env) "Ljava/lang/String;" "Ljava/lang/Integer;" "Landroid/hardware/display/DeviceProductInfo$ManufactureDate;" - "[I)V"); + "I)V"); jclass deviceProductInfoManufactureDateClazz = FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate"); diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index b2884023a83d..04e3a1cb887e 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -194,25 +194,6 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) { return filterPaint(std::move(paint)); } -static BlurDrawLooper* get_looper(const Paint* paint) { - return paint ? paint->getLooper() : nullptr; -} - -template <typename Proc> -void applyLooper(BlurDrawLooper* looper, const SkPaint* paint, Proc proc) { - if (looper) { - SkPaint p; - if (paint) { - p = *paint; - } - looper->apply(p, [&](SkPoint offset, const SkPaint& modifiedPaint) { - proc(offset.fX, offset.fY, &modifiedPaint); - }); - } else { - proc(0, 0, paint); - } -} - static SkFilterMode Paint_to_filter(const SkPaint* paint) { return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear : SkFilterMode::kNearest; @@ -226,8 +207,7 @@ static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) { void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) { sk_sp<SkImage> image = bitmap.makeImage(); - applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y, - const SkPaint* p) { + applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, left + x, top + y, Paint_to_sampling(p), p, bitmap.palette()); }); @@ -245,8 +225,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con sk_sp<SkImage> image = bitmap.makeImage(); - applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y, - const SkPaint* p) { + applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImage(image, x, y, Paint_to_sampling(p), p, bitmap.palette()); }); @@ -263,8 +242,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop sk_sp<SkImage> image = bitmap.makeImage(); - applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y, - const SkPaint* p) { + applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageRect(image, srcRect, dstRect.makeOffset(x, y), Paint_to_sampling(p), p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette()); }); @@ -303,8 +281,7 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch // HWUI always draws 9-patches with linear filtering, regardless of the Paint. const SkFilterMode filter = SkFilterMode::kLinear; - applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y, - const SkPaint* p) { + applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) { mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), filter, p, bitmap.palette()); }); diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h index 8d7a21a732dd..1e404b845084 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -87,6 +87,23 @@ private: std::unique_ptr<SkiaDisplayList> mDisplayList; StartReorderBarrierDrawable* mCurrentBarrier; + template <typename Proc> + void applyLooper(const Paint* paint, Proc proc) { + SkPaint skp; + BlurDrawLooper* looper = nullptr; + if (paint) { + skp = *filterBitmap(paint); + looper = paint->getLooper(); + } + if (looper) { + looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) { + proc(offset.fX, offset.fY, &modifiedPaint); + }); + } else { + proc(0, 0, &skp); + } + } + /** * A new SkiaDisplayList is created or recycled if available. * diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index d896c1fc82b5..f87f90d8e0a2 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -3123,52 +3123,57 @@ public class AudioManager { /** * @hide Home sound - * Played by the framework when the home app becomes active if config_enableHomeSound is set to - * true. This is currently only used on TV devices. + * <p> + * To be played by the framework when the home app becomes active if config_enableHomeSound is + * set to true. This is currently only used on TV devices. * Note that this sound is only available if a sound file is specified in audio_assets.xml. * @see #playSoundEffect(int) */ public static final int FX_HOME = 11; /** - * @hide Fast scroll sound 1 - * To be by the framework when a fast-scrolling is performed and - * {@link #areFastScrollSoundEffectsEnabled()} is true. + * @hide Navigation repeat sound 1 + * <p> + * To be played by the framework when a focus navigation is repeatedly triggered + * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. * This is currently only used on TV devices. * Note that this sound is only available if a sound file is specified in audio_assets.xml * @see #playSoundEffect(int) */ - public static final int FX_FAST_SCROLL_1 = 12; + public static final int FX_FOCUS_NAVIGATION_REPEAT_1 = 12; /** - * @hide Fast scroll sound 2 - * To be by the framework when a fast-scrolling is performed and - * {@link #areFastScrollSoundEffectsEnabled()} is true. + * @hide Navigation repeat sound 2 + * <p> + * To be played by the framework when a focus navigation is repeatedly triggered + * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. * This is currently only used on TV devices. * Note that this sound is only available if a sound file is specified in audio_assets.xml * @see #playSoundEffect(int) */ - public static final int FX_FAST_SCROLL_2 = 13; + public static final int FX_FOCUS_NAVIGATION_REPEAT_2 = 13; /** - * @hide Fast scroll sound 3 - * To be by the framework when a fast-scrolling is performed and - * {@link #areFastScrollSoundEffectsEnabled()} is true. + * @hide Navigation repeat sound 3 + * <p> + * To be played by the framework when a focus navigation is repeatedly triggered + * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. * This is currently only used on TV devices. * Note that this sound is only available if a sound file is specified in audio_assets.xml * @see #playSoundEffect(int) */ - public static final int FX_FAST_SCROLL_3 = 14; + public static final int FX_FOCUS_NAVIGATION_REPEAT_3 = 14; /** - * @hide Fast scroll sound 4 - * To be by the framework when a fast-scrolling is performed and - * {@link #areFastScrollSoundEffectsEnabled()} is true. + * @hide Navigation repeat sound 4 + * <p> + * To be played by the framework when a focus navigation is repeatedly triggered + * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true. * This is currently only used on TV devices. * Note that this sound is only available if a sound file is specified in audio_assets.xml * @see #playSoundEffect(int) */ - public static final int FX_FAST_SCROLL_4 = 15; + public static final int FX_FOCUS_NAVIGATION_REPEAT_4 = 15; /** * @hide Number of sound effects @@ -3177,27 +3182,27 @@ public class AudioManager { public static final int NUM_SOUND_EFFECTS = 16; /** - * @hide Number of fast scroll sound effects + * @hide Number of FX_FOCUS_NAVIGATION_REPEAT_* sound effects */ - public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4; + public static final int NUM_NAVIGATION_REPEAT_SOUND_EFFECTS = 4; /** * @hide - * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[ - * @return The id of a fast scroll sound effect or -1 if out of bounds + * @param n a value in [0, {@link #NUM_NAVIGATION_REPEAT_SOUND_EFFECTS}[ + * @return The id of a navigation repeat sound effect or -1 if out of bounds */ - public static int getNthFastScrollSoundEffectId(int n) { + public static int getNthNavigationRepeatSoundEffect(int n) { switch (n) { case 0: - return FX_FAST_SCROLL_1; + return FX_FOCUS_NAVIGATION_REPEAT_1; case 1: - return FX_FAST_SCROLL_2; + return FX_FOCUS_NAVIGATION_REPEAT_2; case 2: - return FX_FAST_SCROLL_3; + return FX_FOCUS_NAVIGATION_REPEAT_3; case 3: - return FX_FAST_SCROLL_4; + return FX_FOCUS_NAVIGATION_REPEAT_4; default: - Log.w(TAG, "Invalid fast-scroll sound effect id: " + n); + Log.w(TAG, "Invalid navigation repeat sound effect id: " + n); return -1; } } @@ -3205,9 +3210,9 @@ public class AudioManager { /** * @hide */ - public void setFastScrollSoundEffectsEnabled(boolean enabled) { + public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) { try { - getService().setFastScrollSoundEffectsEnabled(enabled); + getService().setNavigationRepeatSoundEffectsEnabled(enabled); } catch (RemoteException e) { } @@ -3215,11 +3220,11 @@ public class AudioManager { /** * @hide - * @return true if the fast scroll sound effects are enabled + * @return true if the navigation repeat sound effects are enabled */ - public boolean areFastScrollSoundEffectsEnabled() { + public boolean areNavigationRepeatSoundEffectsEnabled() { try { - return getService().areFastScrollSoundEffectsEnabled(); + return getService().areNavigationRepeatSoundEffectsEnabled(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 71ee57e3d471..0073b5cc93b9 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -351,9 +351,9 @@ interface IAudioService { oneway void unregisterCommunicationDeviceDispatcher( ICommunicationDeviceDispatcher dispatcher); - boolean areFastScrollSoundEffectsEnabled(); + boolean areNavigationRepeatSoundEffectsEnabled(); - oneway void setFastScrollSoundEffectsEnabled(boolean enabled); + oneway void setNavigationRepeatSoundEffectsEnabled(boolean enabled); boolean isHomeSoundEffectEnabled(); diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index f3ec39d2b1fb..b6a41c20a607 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -64,7 +64,7 @@ android:id="@+id/new_lockscreen_clock_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentEnd="true" + android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:visibility="gone"> <com.android.keyguard.AnimatableClockView @@ -73,7 +73,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center_horizontal" - android:textSize="100dp" + android:textSize="60dp" android:fontFamily="@font/clock" android:typeface="monospace" android:elegantTextHeight="false" diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 2a5784a1e6e9..115a156b65e7 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -47,26 +47,25 @@ <dimen name="eca_overlap">-10dip</dimen> <!-- Slice header --> - <dimen name="widget_title_font_size">24dp</dimen> - <dimen name="header_subtitle_padding">12dp</dimen> + <dimen name="widget_title_font_size">20dp</dimen> + <dimen name="widget_title_line_height">24dp</dimen> <dimen name="header_icon_size">16dp</dimen> <!-- Slice subtitle --> - <dimen name="widget_label_font_size">18dp</dimen> + <dimen name="widget_label_font_size">16dp</dimen> + <dimen name="widget_label_line_height">20dp</dimen> <!-- Clock without header --> <dimen name="widget_big_font_size">54dp</dimen> <dimen name="bottom_text_spacing_digital">0dp</dimen> <dimen name="title_clock_padding">4dp</dimen> <!-- Clock with header --> <dimen name="widget_small_font_size">@dimen/widget_title_font_size</dimen> - <dimen name="widget_vertical_padding">17dp</dimen> + <dimen name="widget_vertical_padding">5dp</dimen> <dimen name="widget_vertical_padding_with_header">25dp</dimen> <dimen name="widget_vertical_padding_clock">12dp</dimen> <!-- Subtitle paddings --> <dimen name="widget_horizontal_padding">8dp</dimen> - <dimen name="widget_icon_size">20dp</dimen> + <dimen name="widget_icon_size">18dp</dimen> <dimen name="widget_icon_padding">8dp</dimen> - <dimen name="subtitle_clock_padding">0dp</dimen> - <dimen name="header_row_font_size">14dp</dimen> <!-- Notification shelf padding when dark --> <dimen name="widget_bottom_separator_padding">-6dp</dimen> diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 2391803957e5..8f42cbe31646 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -120,6 +120,7 @@ <style name="TextAppearance.Keyguard"> <item name="android:textSize">@dimen/widget_title_font_size</item> + <item name="android:lineHeight">@dimen/widget_title_line_height</item> <item name="android:gravity">center</item> <item name="android:ellipsize">end</item> <item name="android:maxLines">2</item> @@ -133,6 +134,7 @@ <item name="android:layout_height">wrap_content</item> <item name="android:lines">1</item> <item name="android:textSize">@dimen/widget_label_font_size</item> + <item name="android:lineHeight">@dimen/widget_label_line_height</item> </style> <style name="TextAppearance.Keyguard.BottomArea"> diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java index 0a117c17a354..1569fff63453 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -21,9 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; -import android.graphics.Paint; import android.icu.text.NumberFormat; -import android.util.MathUtils; import com.android.settingslib.Utils; import com.android.systemui.R; @@ -94,11 +92,6 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie mStatusBarStateController.removeCallback(mStatusBarStateListener); } - float getClockTextTopPadding() { - Paint.FontMetrics fm = mView.getPaint().getFontMetrics(); - return MathUtils.abs(fm.ascent - fm.top); - } - /** * Updates the time for the view. */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 6eb54c25a440..93ed0eaa3fba 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -179,20 +179,15 @@ public class KeyguardClockSwitch extends RelativeLayout { setPaddingRelative(startEndPadding, 0, startEndPadding, 0); mSmallClockFrame.setVisibility(GONE); mNewLockscreenClockFrame.setVisibility(VISIBLE); - - statusAreaLP.removeRule(RelativeLayout.BELOW); + statusAreaLP.addRule(RelativeLayout.BELOW, R.id.new_lockscreen_clock_view); statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START); - statusAreaLP.addRule(RelativeLayout.START_OF, R.id.new_lockscreen_clock_view); - statusAreaLP.width = 0; } else { setPaddingRelative(0, 0, 0, 0); mSmallClockFrame.setVisibility(VISIBLE); mNewLockscreenClockFrame.setVisibility(GONE); statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START); - statusAreaLP.removeRule(RelativeLayout.START_OF); statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view); - statusAreaLP.width = ViewGroup.LayoutParams.MATCH_PARENT; } requestLayout(); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index e375877ed6cf..0675200f81e2 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -20,6 +20,7 @@ import android.app.WallpaperManager; import android.content.ContentResolver; import android.content.res.Resources; import android.provider.Settings; +import android.text.TextUtils; import android.text.format.DateFormat; import android.view.View; import android.view.ViewGroup; @@ -212,10 +213,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS * keep the clock centered. */ void updatePosition(int x, float scale, AnimationProperties props, boolean animate) { - x = Math.abs(x); + x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x; if (mNewLockScreenClockFrame != null) { PropertyAnimator.setProperty(mNewLockScreenClockFrame, AnimatableProperty.TRANSLATION_X, - -x, props, animate); + x, props, animate); PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_X, scale, props, animate); PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_Y, @@ -277,15 +278,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS refreshFormat(mTimeFormat); } - float getClockTextTopPadding() { - if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1 - && mNewLockScreenClockViewController != null) { - return mNewLockScreenClockViewController.getClockTextTopPadding(); - } - - return mView.getClockTextTopPadding(); - } - private void updateAodIcons() { NotificationIconContainer nic = (NotificationIconContainer) mView.findViewById( @@ -337,4 +329,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS sCacheKey = key; } } + + private int getCurrentLayoutDirection() { + return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()); + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index fb97a30f93fb..2373d75cd4ea 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -85,10 +85,6 @@ public class KeyguardSliceView extends LinearLayout { */ private Runnable mContentChangeListener; private boolean mHasHeader; - private final int mRowWithHeaderPadding; - private final int mRowPadding; - private float mRowTextSize; - private float mRowWithHeaderTextSize; private View.OnClickListener mOnClickListener; private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL; @@ -97,9 +93,6 @@ public class KeyguardSliceView extends LinearLayout { super(context, attrs); Resources resources = context.getResources(); - mRowPadding = resources.getDimensionPixelSize(R.dimen.subtitle_clock_padding); - mRowWithHeaderPadding = resources.getDimensionPixelSize(R.dimen.header_subtitle_padding); - mLayoutTransition = new LayoutTransition(); mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2); mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION); @@ -120,10 +113,6 @@ public class KeyguardSliceView extends LinearLayout { mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor); mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size); mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size); - mRowTextSize = mContext.getResources().getDimensionPixelSize( - R.dimen.widget_label_font_size); - mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize( - R.dimen.header_row_font_size); mTitle.setBreakStrategy(LineBreaker.BREAK_STRATEGY_BALANCED); } @@ -204,7 +193,6 @@ public class KeyguardSliceView extends LinearLayout { LinearLayout.LayoutParams layoutParams = (LayoutParams) mRow.getLayoutParams(); layoutParams.gravity = mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL ? Gravity.START : Gravity.CENTER; - layoutParams.topMargin = mHasHeader ? mRowWithHeaderPadding : mRowPadding; mRow.setLayoutParams(layoutParams); for (int i = startIndex; i < subItemsCount; i++) { @@ -230,8 +218,6 @@ public class KeyguardSliceView extends LinearLayout { final SliceItem titleItem = rc.getTitleItem(); button.setText(titleItem == null ? null : titleItem.getText()); button.setContentDescription(rc.getContentDescription()); - button.setTextSize(TypedValue.COMPLEX_UNIT_PX, - mHasHeader ? mRowWithHeaderTextSize : mRowTextSize); Drawable iconDrawable = null; SliceItem icon = SliceQuery.find(item.getSlice(), @@ -313,10 +299,6 @@ public class KeyguardSliceView extends LinearLayout { void onDensityOrFontScaleChanged() { mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size); mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size); - mRowTextSize = mContext.getResources().getDimensionPixelSize( - R.dimen.widget_label_font_size); - mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize( - R.dimen.header_row_font_size); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 6fb6760be653..934e768f9ba8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -266,15 +266,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV mKeyguardClockSwitchController.updateLockScreenMode(mode); mKeyguardSliceViewController.updateLockScreenMode(mode); if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) { - // align the top of keyguard_status_area with the top of the clock text instead - // of the top of the view - mKeyguardSliceViewController.updateTopMargin( - mKeyguardClockSwitchController.getClockTextTopPadding()); mView.setCanShowOwnerInfo(false); mView.setCanShowLogout(false); } else { - // reset margin - mKeyguardSliceViewController.updateTopMargin(0); mView.setCanShowOwnerInfo(true); mView.setCanShowLogout(false); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java index 3ea8140427cb..3bf75d105b9f 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java @@ -19,8 +19,10 @@ package com.android.systemui.biometrics; import android.content.Context; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.view.View; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.systemui.R; @@ -33,6 +35,7 @@ public abstract class UdfpsAnimation extends Drawable { @NonNull protected final Context mContext; @NonNull protected final Drawable mFingerprintDrawable; + @Nullable private View mView; public UdfpsAnimation(@NonNull Context context) { mContext = context; @@ -53,6 +56,10 @@ public abstract class UdfpsAnimation extends Drawable { mFingerprintDrawable.setAlpha(alpha); } + public void setAnimationView(UdfpsAnimationView view) { + mView = view; + } + /** * @return The amount of padding that's needed on each side of the sensor, in pixels. */ @@ -66,4 +73,10 @@ public abstract class UdfpsAnimation extends Drawable { public int getPaddingY() { return 0; } + + protected void postInvalidateView() { + if (mView != null) { + mView.postInvalidate(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java index 501de9df575b..8664e44c9ad2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java @@ -23,7 +23,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.util.MathUtils; -import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -42,7 +41,6 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv private static final String TAG = "UdfpsAnimationKeyguard"; - @NonNull private final View mParent; @NonNull private final Context mContext; private final int mMaxBurnInOffsetX; private final int mMaxBurnInOffsetY; @@ -52,10 +50,9 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv private float mBurnInOffsetX; private float mBurnInOffsetY; - UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context, + UdfpsAnimationKeyguard(@NonNull Context context, @NonNull StatusBarStateController statusBarStateController) { super(context); - mParent = parent; mContext = context; mMaxBurnInOffsetX = context.getResources() @@ -73,10 +70,10 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv mInterpolatedDarkAmount); mBurnInOffsetY = MathUtils.lerp(0f, getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */) - - 0.5f * mMaxBurnInOffsetY, + - mMaxBurnInOffsetY, mInterpolatedDarkAmount); updateColor(); - mParent.postInvalidate(); + postInvalidateView(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java index 41ea4d66f575..44122cba8716 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java @@ -74,7 +74,14 @@ public class UdfpsAnimationView extends View implements DozeReceiver, } void setAnimation(@Nullable UdfpsAnimation animation) { + if (mUdfpsAnimation != null) { + mUdfpsAnimation.setAnimationView(null); + } + mUdfpsAnimation = animation; + if (mUdfpsAnimation != null) { + mUdfpsAnimation.setAnimationView(this); + } } void onSensorRectUpdated(@NonNull RectF sensorRect) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index e7b08e72877d..6451ad9fd5d2 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -44,7 +44,6 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.util.concurrency.DelayableExecutor; @@ -324,7 +323,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback { case IUdfpsOverlayController.REASON_ENROLL_ENROLLING: return new UdfpsAnimationEnroll(mContext); case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD: - return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController); + return new UdfpsAnimationKeyguard(mContext, mStatusBarStateController); case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER: return new UdfpsAnimationFpmOther(mContext); default: diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index 00cb28b8b8fb..6ffecdba883b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -113,6 +113,7 @@ public class UdfpsView extends FrameLayout implements DozeReceiver, UdfpsIllumin void setExtras(@Nullable UdfpsAnimation animation, @Nullable UdfpsEnrollHelper enrollHelper) { mAnimationView.setAnimation(animation); + mEnrollHelper = enrollHelper; if (enrollHelper != null) { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 8ab135ced97e..4418696bfc9b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -32,6 +32,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.dagger.DozeScope; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.AlarmTimeout; @@ -41,12 +42,15 @@ import java.util.Calendar; import javax.inject.Inject; +import dagger.Lazy; + /** * The policy controlling doze. */ @DozeScope public class DozeUi implements DozeMachine.Part, TunerService.Tunable { - + // if enabled, calls dozeTimeTick() whenever the time changes: + private static final boolean BURN_IN_TESTING_ENABLED = false; private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min private final Context mContext; private final DozeHost mHost; @@ -57,16 +61,28 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable { private final boolean mCanAnimateTransition; private final DozeParameters mDozeParameters; private final DozeLog mDozeLog; + private final Lazy<StatusBarStateController> mStatusBarStateController; private boolean mKeyguardShowing; private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback = new KeyguardUpdateMonitorCallback() { - @Override public void onKeyguardVisibilityChanged(boolean showing) { mKeyguardShowing = showing; updateAnimateScreenOff(); } + + @Override + public void onTimeChanged() { + if (BURN_IN_TESTING_ENABLED && mStatusBarStateController != null + && mStatusBarStateController.get().isDozing()) { + // update whenever the time changes for manual burn in testing + mHost.dozeTimeTick(); + + // Keep wakelock until a frame has been pushed. + mHandler.post(mWakeLock.wrap(() -> {})); + } + } }; private long mLastTimeTickElapsed = 0; @@ -75,7 +91,8 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable { public DozeUi(Context context, AlarmManager alarmManager, WakeLock wakeLock, DozeHost host, @Main Handler handler, DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor, - DozeLog dozeLog, TunerService tunerService) { + DozeLog dozeLog, TunerService tunerService, + Lazy<StatusBarStateController> statusBarStateController) { mContext = context; mWakeLock = wakeLock; mHost = host; @@ -85,8 +102,8 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable { mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler); keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback); mDozeLog = dozeLog; - tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON); + mStatusBarStateController = statusBarStateController; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 2c7c5cc91120..76925a7eceee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; +import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -83,6 +84,7 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DragDownHelper.DragDownCallback; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -453,6 +455,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private NotificationEntry mTopHeadsUpEntry; private long mNumHeadsUp; private NotificationStackScrollLayoutController.TouchHandler mTouchHandler; + private final FeatureFlags mFeatureFlags; private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener = new ExpandableView.OnHeightChangedListener() { @@ -492,8 +495,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable GroupMembershipManager groupMembershipManager, GroupExpansionManager groupExpansionManager, SysuiStatusBarStateController statusbarStateController, - AmbientState ambientState - ) { + AmbientState ambientState, + FeatureFlags featureFlags) { super(context, attrs, 0, 0); Resources res = getResources(); mSectionsManager = notificationSectionsManager; @@ -530,6 +533,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mGroupMembershipManager = groupMembershipManager; mGroupExpansionManager = groupExpansionManager; mStatusbarStateController = statusbarStateController; + mFeatureFlags = featureFlags; } void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) { @@ -1156,8 +1160,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (stackStartPosition <= stackEndPosition) { stackHeight = stackEndPosition; } else { - stackHeight = (int) NotificationUtils.interpolate(stackStartPosition, - stackEndPosition, mQsExpansionFraction); + if (shouldUseSplitNotificationShade(mFeatureFlags, getResources())) { + // This prevents notifications from being collapsed when QS is expanded. + stackHeight = (int) height; + } else { + stackHeight = (int) NotificationUtils.interpolate(stackStartPosition, + stackEndPosition, mQsExpansionFraction); + } } } else { stackHeight = (int) height; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index 8cdaa63994e4..f4830fbb0028 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -134,7 +134,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mStackScrollerController = stackScrollerController; mNotificationPanelViewController = notificationPanelViewController; notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp); - notificationPanelViewController.addVerticalTranslationListener(mUpdatePanelTranslation); + notificationPanelViewController.setVerticalTranslationListener(mUpdatePanelTranslation); notificationPanelViewController.setHeadsUpAppearanceController(this); mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener); @@ -171,7 +171,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null); mWakeUpCoordinator.removeListener(this); mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp); - mNotificationPanelViewController.removeVerticalTranslationListener(mUpdatePanelTranslation); + mNotificationPanelViewController.setVerticalTranslationListener(null); mNotificationPanelViewController.setHeadsUpAppearanceController(null); mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight); mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index a6daed5a0850..2ce403764c7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -344,8 +344,11 @@ public class KeyguardClockPositionAlgorithm { } private float burnInPreventionOffsetX() { - return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */) - - mBurnInPreventionOffsetX; + if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) { + return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */) + - mBurnInPreventionOffsetX; + } + return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */); } public static class Result { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 0b3fd161d865..f4ffb207e665 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -196,7 +196,8 @@ public class NotificationPanelViewController extends PanelViewController { new MyOnHeadsUpChangedListener(); private final HeightListener mHeightListener = new HeightListener(); private final ConfigurationListener mConfigurationListener = new ConfigurationListener(); - private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener(); + @VisibleForTesting final StatusBarStateListener mStatusBarStateListener = + new StatusBarStateListener(); private final ExpansionCallback mExpansionCallback = new ExpansionCallback(); private final BiometricUnlockController mBiometricUnlockController; private final NotificationPanelView mView; @@ -473,7 +474,7 @@ public class NotificationPanelViewController extends PanelViewController { private ArrayList<Consumer<ExpandableNotificationRow>> mTrackingHeadsUpListeners = new ArrayList<>(); - private ArrayList<Runnable> mVerticalTranslationListener = new ArrayList<>(); + private Runnable mVerticalTranslationListener; private HeadsUpAppearanceController mHeadsUpAppearanceController; private int mPanelAlpha; @@ -1852,7 +1853,7 @@ public class NotificationPanelViewController extends PanelViewController { } } - private void setQsExpanded(boolean expanded) { + @VisibleForTesting void setQsExpanded(boolean expanded) { boolean changed = mQsExpanded != expanded; if (changed) { mQsExpanded = expanded; @@ -1955,8 +1956,10 @@ public class NotificationPanelViewController extends PanelViewController { private void updateQsState() { mNotificationStackScrollLayoutController.setQsExpanded(mQsExpanded); mNotificationStackScrollLayoutController.setScrollingEnabled( - mBarState != KEYGUARD && (!mQsExpanded - || mQsExpansionFromOverscroll)); + mBarState != KEYGUARD + && (!mQsExpanded + || mQsExpansionFromOverscroll + || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources))); if (mKeyguardUserSwitcherController != null && mQsExpanded && !mStackScrollerOverscrolling) { @@ -2236,13 +2239,16 @@ public class NotificationPanelViewController extends PanelViewController { @Override protected boolean canCollapsePanelOnTouch() { - if (!isInSettings()) { - return mBarState == KEYGUARD - || mIsPanelCollapseOnQQS - || mNotificationStackScrollLayoutController.isScrolledToBottom(); - } else { + if (!isInSettings() && mBarState == KEYGUARD) { return true; } + + if (mNotificationStackScrollLayoutController.isScrolledToBottom()) { + return true; + } + + return !Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources) + && (isInSettings() || mIsPanelCollapseOnQQS); } @Override @@ -2920,7 +2926,8 @@ public class NotificationPanelViewController extends PanelViewController { * @param x the x-coordinate the touch event */ protected void updateHorizontalPanelPosition(float x) { - if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()) { + if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth() + || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { resetHorizontalPanelPosition(); return; } @@ -2948,9 +2955,8 @@ public class NotificationPanelViewController extends PanelViewController { protected void setHorizontalPanelTranslation(float translation) { mNotificationStackScrollLayoutController.setTranslationX(translation); mQsFrame.setTranslationX(translation); - int size = mVerticalTranslationListener.size(); - for (int i = 0; i < size; i++) { - mVerticalTranslationListener.get(i).run(); + if (mVerticalTranslationListener != null) { + mVerticalTranslationListener.run(); } } @@ -3243,12 +3249,8 @@ public class NotificationPanelViewController extends PanelViewController { mTrackingHeadsUpListeners.remove(listener); } - public void addVerticalTranslationListener(Runnable verticalTranslationListener) { - mVerticalTranslationListener.add(verticalTranslationListener); - } - - public void removeVerticalTranslationListener(Runnable verticalTranslationListener) { - mVerticalTranslationListener.remove(verticalTranslationListener); + public void setVerticalTranslationListener(Runnable verticalTranslationListener) { + mVerticalTranslationListener = verticalTranslationListener; } public void setHeadsUpAppearanceController( @@ -3615,6 +3617,10 @@ public class NotificationPanelViewController extends PanelViewController { NotificationStackScrollLayout.OnOverscrollTopChangedListener { @Override public void onOverscrollTopChanged(float amount, boolean isRubberbanded) { + // When in split shade, overscroll shouldn't carry through to QS + if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { + return; + } cancelQsAnimation(); if (!mQsExpansionEnabled) { amount = 0f; diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java index d60772730dff..afe5c0b2edbd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java @@ -41,6 +41,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.wakelock.WakeLockFake; @@ -74,6 +75,8 @@ public class DozeUiTest extends SysuiTestCase { private Handler mHandler; private HandlerThread mHandlerThread; private DozeUi mDozeUi; + @Mock + private StatusBarStateController mStatusBarStateController; @Before public void setUp() throws Exception { @@ -85,7 +88,8 @@ public class DozeUiTest extends SysuiTestCase { mHandler = mHandlerThread.getThreadHandler(); mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler, - mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService); + mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService, + () -> mStatusBarStateController); mDozeUi.setDozeMachine(mMachine); } @@ -141,7 +145,8 @@ public class DozeUiTest extends SysuiTestCase { reset(mHost); when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true); mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler, - mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService); + mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService, + () -> mStatusBarStateController); mDozeUi.setDozeMachine(mMachine); // Never animate if display doesn't support it. diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 461f64eda6e5..84fb3689b0b0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -21,6 +21,8 @@ import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; +import static com.google.common.truth.Truth.assertWithMessage; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -49,6 +51,7 @@ import com.android.systemui.ExpandHelper; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.EmptyShadeView; +import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -101,6 +104,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private SysuiStatusBarStateController mStatusBarStateController; @Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; + @Mock private FeatureFlags mFeatureFlags; @Before @UiThreadTest @@ -139,8 +143,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mGroupMembershipManger, mGroupExpansionManager, mStatusBarStateController, - mAmbientState - ); + mAmbientState, + mFeatureFlags); mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, mNotificationSwipeHelper); mStackScroller = spy(mStackScrollerInternal); @@ -205,8 +209,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test @UiThreadTest public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() { - final float expectedHeight[] = {0f}; - final float expectedAppear[] = {0f}; + final float[] expectedHeight = {0f}; + final float[] expectedAppear = {0f}; mStackScroller.addOnExpandedHeightChangedListener((height, appear) -> { Assert.assertEquals(expectedHeight[0], height, 0); @@ -222,6 +226,29 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + @UiThreadTest + public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() { + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + final int[] expectedStackHeight = {0}; + + mStackScroller.addOnExpandedHeightChangedListener((expandedHeight, appear) -> { + assertWithMessage("Given shade enabled: %s", + mFeatureFlags.isTwoColumnNotificationShadeEnabled()) + .that(mStackScroller.getHeight()) + .isEqualTo(expectedStackHeight[0]); + }); + + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false); + expectedStackHeight[0] = 0; + mStackScroller.setExpandedHeight(100f); + + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + expectedStackHeight[0] = 100; + mStackScroller.setExpandedHeight(100f); + } + + + @Test public void manageNotifications_visible() { FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java index 8dea84c4d0b6..6e0cbd9ecfa3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -197,9 +198,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { mHeadsUpAppearanceController.destroy(); verify(mHeadsUpManager).removeListener(any()); verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any()); - verify(mPanelView).removeVerticalTranslationListener(any()); + verify(mPanelView).setVerticalTranslationListener(isNull()); verify(mPanelView).removeTrackingHeadsUpListener(any()); - verify(mPanelView).setHeadsUpAppearanceController(any()); + verify(mPanelView).setHeadsUpAppearanceController(isNull()); verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any()); verify(mStackScrollerController).removeOnLayoutChangeListener(any()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index e788a1c0954b..8cb898443fd2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -18,13 +18,15 @@ package com.android.systemui.statusbar.phone; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.StatusBarState.SHADE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -45,6 +47,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; @@ -53,6 +56,7 @@ import androidx.constraintlayout.widget.ConstraintSet; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardClockSwitch; @@ -100,7 +104,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; @@ -116,8 +119,6 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private StatusBar mStatusBar; @Mock - private SysuiStatusBarStateController mStatusBarStateController; - @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @Mock private KeyguardBottomAreaView mKeyguardBottomArea; @@ -227,7 +228,10 @@ public class NotificationPanelViewTest extends SysuiTestCase { private AmbientState mAmbientState; @Mock private UserManager mUserManager; + @Mock + private UiEventLogger mUiEventLogger; + private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; private View.AccessibilityDelegate mAccessibiltyDelegate; private NotificationsQuickSettingsContainer mNotificationContainerParent; @@ -235,6 +239,8 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); + mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger); + when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false); when(mHeadsUpCallback.getContext()).thenReturn(mContext); when(mView.getResources()).thenReturn(mResources); @@ -258,6 +264,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea); when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class)); + when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer); when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame); when(mView.findViewById(R.id.keyguard_status_view)) @@ -336,17 +343,19 @@ public class NotificationPanelViewTest extends SysuiTestCase { ArgumentCaptor.forClass(View.AccessibilityDelegate.class); verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture()); mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue(); + mNotificationPanelViewController.mStatusBarStateController + .addCallback(mNotificationPanelViewController.mStatusBarStateListener); + mNotificationPanelViewController + .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class)); } @Test public void testSetDozing_notifiesNsslAndStateController() { - mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */, + mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */, null /* touch */); - InOrder inOrder = inOrder( - mNotificationStackScrollLayoutController, mStatusBarStateController); - inOrder.verify(mNotificationStackScrollLayoutController) - .setDozing(eq(true), eq(true), eq(null)); - inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true)); + verify(mNotificationStackScrollLayoutController) + .setDozing(eq(true), eq(false), eq(null)); + assertThat(mStatusBarStateController.getDozeAmount()).isEqualTo(1f); } @Test @@ -442,9 +451,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Test public void testAllChildrenOfNotificationContainer_haveIds() { - when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); - when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); - + enableDualPaneShade(); mNotificationContainerParent.addView(newViewWithId(1)); mNotificationContainerParent.addView(newViewWithId(View.NO_ID)); @@ -473,8 +480,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Test public void testSplitShadeLayout_isAlignedToGuideline() { - when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); - when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + enableDualPaneShade(); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); @@ -489,6 +495,39 @@ public class NotificationPanelViewTest extends SysuiTestCase { assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline); } + @Test + public void testCanCollapsePanelOnTouch_trueForKeyGuard() { + mStatusBarStateController.setState(KEYGUARD); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_trueWhenScrolledToBottom() { + mStatusBarStateController.setState(SHADE); + when(mNotificationStackScrollLayoutController.isScrolledToBottom()).thenReturn(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_trueWhenInSettings() { + mStatusBarStateController.setState(SHADE); + mNotificationPanelViewController.setQsExpanded(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue(); + } + + @Test + public void testCanCollapsePanelOnTouch_falseInDualPaneShade() { + mStatusBarStateController.setState(SHADE); + when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + mNotificationPanelViewController.setQsExpanded(true); + + assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isFalse(); + } + private View newViewWithId(int id) { View view = new View(mContext); view.setId(id); @@ -499,6 +538,23 @@ public class NotificationPanelViewTest extends SysuiTestCase { return view; } + @Test + public void testOnDragDownEvent_horizontalTranslationIsZeroForDualPaneShade() { + when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(350f); + when(mView.getWidth()).thenReturn(800); + enableDualPaneShade(); + + onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, + 200f /* x position */, 0f, 0)); + + verify(mQsFrame).setTranslationX(0); + } + + private void enableDualPaneShade() { + when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); + when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); + } + private void onTouchEvent(MotionEvent ev) { mTouchHandler.onTouch(mView, ev); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 29ee8b6c675d..5f3405379715 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -726,7 +726,7 @@ public class AudioService extends IAudioService.Stub // caches the value returned by AudioSystem.isMicrophoneMuted() private boolean mMicMuteFromSystemCached; - private boolean mFastScrollSoundEffectsEnabled; + private boolean mNavigationRepeatSoundEffectsEnabled; private boolean mHomeSoundEffectEnabled; @GuardedBy("mSettingsLock") @@ -2325,15 +2325,15 @@ public class AudioService extends IAudioService.Stub VOL_ADJUST_NORMAL); } - public void setFastScrollSoundEffectsEnabled(boolean enabled) { - mFastScrollSoundEffectsEnabled = enabled; + public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) { + mNavigationRepeatSoundEffectsEnabled = enabled; } /** * @return true if the fast scroll sound effects are enabled */ - public boolean areFastScrollSoundEffectsEnabled() { - return mFastScrollSoundEffectsEnabled; + public boolean areNavigationRepeatSoundEffectsEnabled() { + return mNavigationRepeatSoundEffectsEnabled; } public void setHomeSoundEffectEnabled(boolean enabled) { diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java index c14bb3ee5df1..7031e02af05a 100644 --- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java +++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java @@ -52,6 +52,7 @@ import java.util.Map; * used by AudioService. As its methods are called on the message handler thread * of AudioService, the actual work is offloaded to a dedicated thread. * This helps keeping AudioService responsive. + * * @hide */ class SoundEffectsHelper { @@ -89,15 +90,18 @@ class SoundEffectsHelper { final String mFileName; int mSampleId; boolean mLoaded; // for effects in SoundPool + Resource(String fileName) { mFileName = fileName; mSampleId = EFFECT_NOT_IN_SOUND_POOL; } + void unload() { mSampleId = EFFECT_NOT_IN_SOUND_POOL; mLoaded = false; } } + // All the fields below are accessed by the worker thread exclusively private final List<Resource> mResources = new ArrayList<Resource>(); private final int[] mEffects = new int[AudioManager.NUM_SOUND_EFFECTS]; // indexes in mResources @@ -116,9 +120,9 @@ class SoundEffectsHelper { } /** - * Unloads samples from the sound pool. - * This method can be called to free some memory when - * sound effects are disabled. + * Unloads samples from the sound pool. + * This method can be called to free some memory when + * sound effects are disabled. */ /*package*/ void unloadSoundEffects() { sendMsg(MSG_UNLOAD_EFFECTS, 0, 0, null, 0); @@ -385,12 +389,12 @@ class SoundEffectsHelper { } } - boolean fastScrollSoundEffectsParsed = allFastScrollSoundsParsed(parserCounter); + boolean navigationRepeatFxParsed = allNavigationRepeatSoundsParsed(parserCounter); boolean homeSoundParsed = parserCounter.getOrDefault(AudioManager.FX_HOME, 0) > 0; - if (fastScrollSoundEffectsParsed || homeSoundParsed) { + if (navigationRepeatFxParsed || homeSoundParsed) { AudioManager audioManager = mContext.getSystemService(AudioManager.class); - if (audioManager != null && fastScrollSoundEffectsParsed) { - audioManager.setFastScrollSoundEffectsEnabled(true); + if (audioManager != null && navigationRepeatFxParsed) { + audioManager.setNavigationRepeatSoundEffectsEnabled(true); } if (audioManager != null && homeSoundParsed) { audioManager.setHomeSoundEffectEnabled(true); @@ -410,13 +414,13 @@ class SoundEffectsHelper { } } - private boolean allFastScrollSoundsParsed(Map<Integer, Integer> parserCounter) { + private boolean allNavigationRepeatSoundsParsed(Map<Integer, Integer> parserCounter) { int numFastScrollSoundEffectsParsed = - parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_1, 0) - + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_2, 0) - + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_3, 0) - + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_4, 0); - return numFastScrollSoundEffectsParsed == AudioManager.NUM_FAST_SCROLL_SOUND_EFFECTS; + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_1, 0) + + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_2, 0) + + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_3, 0) + + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_4, 0); + return numFastScrollSoundEffectsParsed == AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS; } private int findOrAddResourceByFileName(String fileName) { |