Loading packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +15 −19 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.view.Display; import android.view.GestureDetector; Loading Loading @@ -654,20 +653,22 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt } }); if (mCarNotificationListener != null) { try { // If we already had a notification listener we need to unreigster is before // making a new one mCarNotificationListener.unregisterAsSystemService(); } catch (RemoteException e) { Log.e(TAG, "Error unregistering notification listener."); } } mCarNotificationListener = new CarNotificationListener(); mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper(); if (mCarNotificationListener == null) { // Only make and register a listener if we don't already have one since // #connectNotificationsUI can be called multiple times on locale change. mCarNotificationListener = new CarNotificationListener(); mNotificationDataManager = new NotificationDataManager(); CarHeadsUpNotificationManager carHeadsUpNotificationManager = new CarSystemUIHeadsUpNotificationManager(mContext, mNotificationClickHandlerFactory, mNotificationDataManager); mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, carHeadsUpNotificationManager, mNotificationDataManager); } mNotificationDataManager.setOnUnseenCountUpdateListener(() -> { if (mNavigationBarView != null && mNotificationDataManager != null) { onUseenCountUpdate(mNotificationDataManager.getUnseenNotificationCount()); Loading @@ -676,13 +677,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt mEnableHeadsUpNotificationWhenNotificationShadeOpen = mContext.getResources().getBoolean( R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen); CarHeadsUpNotificationManager carHeadsUpNotificationManager = new CarSystemUIHeadsUpNotificationManager(mContext, mNotificationClickHandlerFactory, mNotificationDataManager); mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager); mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, carHeadsUpNotificationManager, mNotificationDataManager); mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager); mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view); View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane); Loading packages/SystemUI/res/values/config.xml +17 −0 Original line number Diff line number Diff line Loading @@ -491,4 +491,21 @@ <!-- Respect the drawable/rounded.xml that allow to customize as multiple radius corner path --> <bool name="config_roundedCornerMultipleRadius">false</bool> <!-- A path similar to frameworks/base/core/res/res/values/config.xml config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then SystemUI will draw this "protection path" instead of the display cutout path that is normally used for anti-aliasing. This path will only be drawn when the front-facing camera turns on, otherwise the main DisplayCutout path will be rendered --> <string translatable="false" name="config_frontBuiltInDisplayCutoutProtection"></string> <!-- ID for the camera that needs extra protection --> <string translatable="false" name="config_protectedCameraId"></string> <!-- Flag to turn on the rendering of the above path or not --> <bool name="config_enableDisplayCutoutProtection">false</bool> </resources> packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui import android.content.Context import android.graphics.Path import android.graphics.Rect import android.graphics.RectF import android.hardware.camera2.CameraManager import android.util.PathParser import java.util.concurrent.Executor import kotlin.math.roundToInt const val TAG = "CameraOpTransitionController" /** * Listens for usage of the Camera and controls the ScreenDecorations transition to show extra * protection around a display cutout based on config_frontBuiltInDisplayCutoutProtection and * config_enableDisplayCutoutProtection */ class CameraAvailabilityListener( private val cameraManager: CameraManager, private val cutoutProtectionPath: Path, private val targetCameraId: String, private val executor: Executor ) { private var cutoutBounds = Rect() private val listeners = mutableListOf<CameraTransitionCallback>() private val availabilityCallback: CameraManager.AvailabilityCallback = object : CameraManager.AvailabilityCallback() { override fun onCameraAvailable(cameraId: String) { if (targetCameraId == cameraId) { notifyCameraInactive() } } override fun onCameraUnavailable(cameraId: String) { if (targetCameraId == cameraId) { notifyCameraActive() } } } init { val computed = RectF() cutoutProtectionPath.computeBounds(computed, false /* unused */) cutoutBounds.set( computed.left.roundToInt(), computed.top.roundToInt(), computed.right.roundToInt(), computed.bottom.roundToInt()) } /** * Start listening for availability events, and maybe notify listeners * * @return true if we started listening */ fun startListening() { registerCameraListener() } fun stop() { unregisterCameraListener() } fun addTransitionCallback(callback: CameraTransitionCallback) { listeners.add(callback) } fun removeTransitionCallback(callback: CameraTransitionCallback) { listeners.remove(callback) } private fun registerCameraListener() { cameraManager.registerAvailabilityCallback(executor, availabilityCallback) } private fun unregisterCameraListener() { cameraManager.unregisterAvailabilityCallback(availabilityCallback) } private fun notifyCameraActive() { listeners.forEach { it.onApplyCameraProtection(cutoutProtectionPath, cutoutBounds) } } private fun notifyCameraInactive() { listeners.forEach { it.onHideCameraProtection() } } /** * Callbacks to tell a listener that a relevant camera turned on and off. */ interface CameraTransitionCallback { fun onApplyCameraProtection(protectionPath: Path, bounds: Rect) fun onHideCameraProtection() } companion object Factory { fun build(context: Context, executor: Executor): CameraAvailabilityListener { val manager = context .getSystemService(Context.CAMERA_SERVICE) as CameraManager val res = context.resources val pathString = res.getString(R.string.config_frontBuiltInDisplayCutoutProtection) val cameraId = res.getString(R.string.config_protectedCameraId) return CameraAvailabilityListener( manager, pathFromString(pathString), cameraId, executor) } private fun pathFromString(pathString: String): Path { val spec = pathString.trim() val p: Path try { p = PathParser.createPathFromPathData(spec) } catch (e: Throwable) { throw IllegalArgumentException("Invalid protection path", e) } return p } } } No newline at end of file packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +79 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.Dimension; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.Fragment; import android.content.BroadcastReceiver; Loading @@ -37,6 +38,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; Loading Loading @@ -110,6 +112,7 @@ public class ScreenDecorations extends SystemUI implements Tunable, private DisplayManager mDisplayManager; private DisplayManager.DisplayListener mDisplayListener; private CameraAvailabilityListener mCameraListener; @VisibleForTesting protected int mRoundedDefault; Loading @@ -133,6 +136,25 @@ public class ScreenDecorations extends SystemUI implements Tunable, private boolean mInGesturalMode; private boolean mIsRoundedCornerMultipleRadius; private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback = new CameraAvailabilityListener.CameraTransitionCallback() { @Override public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { // Show the extra protection around the front facing camera if necessary mCutoutTop.setProtection(protectionPath, bounds); mCutoutTop.setShowProtection(true); mCutoutBottom.setProtection(protectionPath, bounds); mCutoutBottom.setShowProtection(true); } @Override public void onHideCameraProtection() { // Go back to the regular anti-aliasing mCutoutTop.setShowProtection(false); mCutoutBottom.setShowProtection(false); } }; /** * Converts a set of {@link Rect}s into a {@link Region} * Loading Loading @@ -331,6 +353,7 @@ public class ScreenDecorations extends SystemUI implements Tunable, updateRoundedCornerRadii(); if (hasRoundedCorners() || shouldDrawCutout() || shouldHostHandles()) { setupDecorations(); setupCameraListener(); } mDisplayListener = new DisplayManager.DisplayListener() { Loading Loading @@ -446,6 +469,16 @@ public class ScreenDecorations extends SystemUI implements Tunable, new ValidatingPreDrawListener(mBottomOverlay)); } private void setupCameraListener() { Resources res = mContext.getResources(); boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection); if (enabled) { mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mHandler::post); mCameraListener.addTransitionCallback(mCameraTransitionCallback); mCameraListener.startListening(); } } private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading Loading @@ -841,6 +874,13 @@ public class ScreenDecorations extends SystemUI implements Tunable, private final List<Rect> mBounds = new ArrayList(); private final Rect mBoundingRect = new Rect(); private final Path mBoundingPath = new Path(); // Don't initialize these because they are cached elsewhere and may not exist private Rect mProtectionRect; private Path mProtectionPath; private Rect mTotalBounds = new Rect(); // Whether or not to show the cutout protection path private boolean mShowProtection = false; private final int[] mLocation = new int[2]; private final boolean mInitialStart; private final Runnable mVisibilityChangedListener; Loading Loading @@ -887,7 +927,13 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onDraw(canvas); getLocationOnScreen(mLocation); canvas.translate(-mLocation[0], -mLocation[1]); if (!mBoundingPath.isEmpty()) { if (mShowProtection && !mProtectionRect.isEmpty()) { mPaint.setColor(mColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); canvas.drawPath(mProtectionPath, mPaint); } else if (!mBoundingPath.isEmpty()) { mPaint.setColor(mColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); Loading Loading @@ -915,6 +961,22 @@ public class ScreenDecorations extends SystemUI implements Tunable, update(); } void setProtection(Path protectionPath, Rect pathBounds) { mProtectionPath = protectionPath; mProtectionRect = pathBounds; } void setShowProtection(boolean shouldShow) { if (mShowProtection == shouldShow) { return; } mShowProtection = shouldShow; updateBoundingPath(); requestLayout(); invalidate(); } private boolean isStart() { final boolean flipped = (mRotation == RotationUtils.ROTATION_SEASCAPE || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN); Loading Loading @@ -961,6 +1023,9 @@ public class ScreenDecorations extends SystemUI implements Tunable, Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m); mBoundingPath.transform(m); if (mProtectionPath != null) { mProtectionPath.transform(m); } } private static void transformPhysicalToLogicalCoordinates(@Surface.Rotation int rotation, Loading Loading @@ -1018,10 +1083,20 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } if (mShowProtection) { // Make sure that our measured height encompases the protection mTotalBounds.union(mBoundingRect); mTotalBounds.union(mProtectionRect); setMeasuredDimension( resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)); } else { setMeasuredDimension( resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); } } public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, Rect out) { Loading Loading
packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +15 −19 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.view.Display; import android.view.GestureDetector; Loading Loading @@ -654,20 +653,22 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt } }); if (mCarNotificationListener != null) { try { // If we already had a notification listener we need to unreigster is before // making a new one mCarNotificationListener.unregisterAsSystemService(); } catch (RemoteException e) { Log.e(TAG, "Error unregistering notification listener."); } } mCarNotificationListener = new CarNotificationListener(); mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper(); if (mCarNotificationListener == null) { // Only make and register a listener if we don't already have one since // #connectNotificationsUI can be called multiple times on locale change. mCarNotificationListener = new CarNotificationListener(); mNotificationDataManager = new NotificationDataManager(); CarHeadsUpNotificationManager carHeadsUpNotificationManager = new CarSystemUIHeadsUpNotificationManager(mContext, mNotificationClickHandlerFactory, mNotificationDataManager); mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, carHeadsUpNotificationManager, mNotificationDataManager); } mNotificationDataManager.setOnUnseenCountUpdateListener(() -> { if (mNavigationBarView != null && mNotificationDataManager != null) { onUseenCountUpdate(mNotificationDataManager.getUnseenNotificationCount()); Loading @@ -676,13 +677,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt mEnableHeadsUpNotificationWhenNotificationShadeOpen = mContext.getResources().getBoolean( R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen); CarHeadsUpNotificationManager carHeadsUpNotificationManager = new CarSystemUIHeadsUpNotificationManager(mContext, mNotificationClickHandlerFactory, mNotificationDataManager); mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager); mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, carHeadsUpNotificationManager, mNotificationDataManager); mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager); mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view); View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane); Loading
packages/SystemUI/res/values/config.xml +17 −0 Original line number Diff line number Diff line Loading @@ -491,4 +491,21 @@ <!-- Respect the drawable/rounded.xml that allow to customize as multiple radius corner path --> <bool name="config_roundedCornerMultipleRadius">false</bool> <!-- A path similar to frameworks/base/core/res/res/values/config.xml config_mainBuiltInDisplayCutout that describes a path larger than the exact path of a display cutout. If present as well as config_enableDisplayCutoutProtection is set to true, then SystemUI will draw this "protection path" instead of the display cutout path that is normally used for anti-aliasing. This path will only be drawn when the front-facing camera turns on, otherwise the main DisplayCutout path will be rendered --> <string translatable="false" name="config_frontBuiltInDisplayCutoutProtection"></string> <!-- ID for the camera that needs extra protection --> <string translatable="false" name="config_protectedCameraId"></string> <!-- Flag to turn on the rendering of the above path or not --> <bool name="config_enableDisplayCutoutProtection">false</bool> </resources>
packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui import android.content.Context import android.graphics.Path import android.graphics.Rect import android.graphics.RectF import android.hardware.camera2.CameraManager import android.util.PathParser import java.util.concurrent.Executor import kotlin.math.roundToInt const val TAG = "CameraOpTransitionController" /** * Listens for usage of the Camera and controls the ScreenDecorations transition to show extra * protection around a display cutout based on config_frontBuiltInDisplayCutoutProtection and * config_enableDisplayCutoutProtection */ class CameraAvailabilityListener( private val cameraManager: CameraManager, private val cutoutProtectionPath: Path, private val targetCameraId: String, private val executor: Executor ) { private var cutoutBounds = Rect() private val listeners = mutableListOf<CameraTransitionCallback>() private val availabilityCallback: CameraManager.AvailabilityCallback = object : CameraManager.AvailabilityCallback() { override fun onCameraAvailable(cameraId: String) { if (targetCameraId == cameraId) { notifyCameraInactive() } } override fun onCameraUnavailable(cameraId: String) { if (targetCameraId == cameraId) { notifyCameraActive() } } } init { val computed = RectF() cutoutProtectionPath.computeBounds(computed, false /* unused */) cutoutBounds.set( computed.left.roundToInt(), computed.top.roundToInt(), computed.right.roundToInt(), computed.bottom.roundToInt()) } /** * Start listening for availability events, and maybe notify listeners * * @return true if we started listening */ fun startListening() { registerCameraListener() } fun stop() { unregisterCameraListener() } fun addTransitionCallback(callback: CameraTransitionCallback) { listeners.add(callback) } fun removeTransitionCallback(callback: CameraTransitionCallback) { listeners.remove(callback) } private fun registerCameraListener() { cameraManager.registerAvailabilityCallback(executor, availabilityCallback) } private fun unregisterCameraListener() { cameraManager.unregisterAvailabilityCallback(availabilityCallback) } private fun notifyCameraActive() { listeners.forEach { it.onApplyCameraProtection(cutoutProtectionPath, cutoutBounds) } } private fun notifyCameraInactive() { listeners.forEach { it.onHideCameraProtection() } } /** * Callbacks to tell a listener that a relevant camera turned on and off. */ interface CameraTransitionCallback { fun onApplyCameraProtection(protectionPath: Path, bounds: Rect) fun onHideCameraProtection() } companion object Factory { fun build(context: Context, executor: Executor): CameraAvailabilityListener { val manager = context .getSystemService(Context.CAMERA_SERVICE) as CameraManager val res = context.resources val pathString = res.getString(R.string.config_frontBuiltInDisplayCutoutProtection) val cameraId = res.getString(R.string.config_protectedCameraId) return CameraAvailabilityListener( manager, pathFromString(pathString), cameraId, executor) } private fun pathFromString(pathString: String): Path { val spec = pathString.trim() val p: Path try { p = PathParser.createPathFromPathData(spec) } catch (e: Throwable) { throw IllegalArgumentException("Invalid protection path", e) } return p } } } No newline at end of file
packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +79 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.Dimension; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.Fragment; import android.content.BroadcastReceiver; Loading @@ -37,6 +38,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; Loading Loading @@ -110,6 +112,7 @@ public class ScreenDecorations extends SystemUI implements Tunable, private DisplayManager mDisplayManager; private DisplayManager.DisplayListener mDisplayListener; private CameraAvailabilityListener mCameraListener; @VisibleForTesting protected int mRoundedDefault; Loading @@ -133,6 +136,25 @@ public class ScreenDecorations extends SystemUI implements Tunable, private boolean mInGesturalMode; private boolean mIsRoundedCornerMultipleRadius; private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback = new CameraAvailabilityListener.CameraTransitionCallback() { @Override public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { // Show the extra protection around the front facing camera if necessary mCutoutTop.setProtection(protectionPath, bounds); mCutoutTop.setShowProtection(true); mCutoutBottom.setProtection(protectionPath, bounds); mCutoutBottom.setShowProtection(true); } @Override public void onHideCameraProtection() { // Go back to the regular anti-aliasing mCutoutTop.setShowProtection(false); mCutoutBottom.setShowProtection(false); } }; /** * Converts a set of {@link Rect}s into a {@link Region} * Loading Loading @@ -331,6 +353,7 @@ public class ScreenDecorations extends SystemUI implements Tunable, updateRoundedCornerRadii(); if (hasRoundedCorners() || shouldDrawCutout() || shouldHostHandles()) { setupDecorations(); setupCameraListener(); } mDisplayListener = new DisplayManager.DisplayListener() { Loading Loading @@ -446,6 +469,16 @@ public class ScreenDecorations extends SystemUI implements Tunable, new ValidatingPreDrawListener(mBottomOverlay)); } private void setupCameraListener() { Resources res = mContext.getResources(); boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection); if (enabled) { mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mHandler::post); mCameraListener.addTransitionCallback(mCameraTransitionCallback); mCameraListener.startListening(); } } private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Loading Loading @@ -841,6 +874,13 @@ public class ScreenDecorations extends SystemUI implements Tunable, private final List<Rect> mBounds = new ArrayList(); private final Rect mBoundingRect = new Rect(); private final Path mBoundingPath = new Path(); // Don't initialize these because they are cached elsewhere and may not exist private Rect mProtectionRect; private Path mProtectionPath; private Rect mTotalBounds = new Rect(); // Whether or not to show the cutout protection path private boolean mShowProtection = false; private final int[] mLocation = new int[2]; private final boolean mInitialStart; private final Runnable mVisibilityChangedListener; Loading Loading @@ -887,7 +927,13 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onDraw(canvas); getLocationOnScreen(mLocation); canvas.translate(-mLocation[0], -mLocation[1]); if (!mBoundingPath.isEmpty()) { if (mShowProtection && !mProtectionRect.isEmpty()) { mPaint.setColor(mColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); canvas.drawPath(mProtectionPath, mPaint); } else if (!mBoundingPath.isEmpty()) { mPaint.setColor(mColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); Loading Loading @@ -915,6 +961,22 @@ public class ScreenDecorations extends SystemUI implements Tunable, update(); } void setProtection(Path protectionPath, Rect pathBounds) { mProtectionPath = protectionPath; mProtectionRect = pathBounds; } void setShowProtection(boolean shouldShow) { if (mShowProtection == shouldShow) { return; } mShowProtection = shouldShow; updateBoundingPath(); requestLayout(); invalidate(); } private boolean isStart() { final boolean flipped = (mRotation == RotationUtils.ROTATION_SEASCAPE || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN); Loading Loading @@ -961,6 +1023,9 @@ public class ScreenDecorations extends SystemUI implements Tunable, Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m); mBoundingPath.transform(m); if (mProtectionPath != null) { mProtectionPath.transform(m); } } private static void transformPhysicalToLogicalCoordinates(@Surface.Rotation int rotation, Loading Loading @@ -1018,10 +1083,20 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } if (mShowProtection) { // Make sure that our measured height encompases the protection mTotalBounds.union(mBoundingRect); mTotalBounds.union(mProtectionRect); setMeasuredDimension( resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)); } else { setMeasuredDimension( resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); } } public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, Rect out) { Loading