Revert "Move rounded corner to provider"
This reverts commit cb4664745c.
Reason for revert: Missed frame on lockscreen swipe
Bug: 226240098
Change-Id: I904ae32be17b3e12bcbd99747113c6a97fce17e2
This commit is contained in:
40
packages/SystemUI/res/layout/rounded_corners_bottom.xml
Normal file
40
packages/SystemUI/res/layout/rounded_corners_bottom.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
** Copyright 2020, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
-->
|
||||
<com.android.systemui.RegionInterceptingFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rounded_corners_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:id="@+id/left"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_gravity="left|bottom"
|
||||
android:tint="#ff000000"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/rounded_corner_bottom"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/right"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:tint="#ff000000"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="right|bottom"
|
||||
android:src="@drawable/rounded_corner_bottom"/>
|
||||
|
||||
</com.android.systemui.RegionInterceptingFrameLayout>
|
||||
40
packages/SystemUI/res/layout/rounded_corners_top.xml
Normal file
40
packages/SystemUI/res/layout/rounded_corners_top.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
** Copyright 2020, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
-->
|
||||
<com.android.systemui.RegionInterceptingFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/rounded_corners_top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:id="@+id/left"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_gravity="left|top"
|
||||
android:tint="#ff000000"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/rounded_corner_top"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/right"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:tint="#ff000000"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="right|top"
|
||||
android:src="@drawable/rounded_corner_top"/>
|
||||
|
||||
</com.android.systemui.RegionInterceptingFrameLayout>
|
||||
@@ -167,11 +167,5 @@
|
||||
<item type="id" name="action_move_bottom_right"/>
|
||||
<item type="id" name="action_move_to_edge_and_hide"/>
|
||||
<item type="id" name="action_move_out_edge_and_show"/>
|
||||
|
||||
<!-- rounded corner view id -->
|
||||
<item type="id" name="rounded_corner_top_left"/>
|
||||
<item type="id" name="rounded_corner_top_right"/>
|
||||
<item type="id" name="rounded_corner_bottom_left"/>
|
||||
<item type="id" name="rounded_corner_bottom_right"/>
|
||||
</resources>
|
||||
|
||||
|
||||
@@ -369,15 +369,10 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec
|
||||
* Update the rounded corner size.
|
||||
*/
|
||||
fun updateRoundedCornerSize(top: Int, bottom: Int) {
|
||||
if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) {
|
||||
return
|
||||
}
|
||||
roundedCornerTopSize = top
|
||||
roundedCornerBottomSize = bottom
|
||||
updateRoundedCornerDrawableBounds()
|
||||
|
||||
// Use requestLayout() to trigger transparent region recalculated
|
||||
requestLayout()
|
||||
invalidate()
|
||||
}
|
||||
|
||||
private fun updateRoundedCornerDrawableBounds() {
|
||||
|
||||
@@ -77,7 +77,6 @@ import com.android.systemui.decor.DecorProviderFactory;
|
||||
import com.android.systemui.decor.DecorProviderKt;
|
||||
import com.android.systemui.decor.OverlayWindow;
|
||||
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
|
||||
import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
|
||||
import com.android.systemui.decor.RoundedCornerResDelegate;
|
||||
import com.android.systemui.qs.SettingObserver;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
@@ -139,9 +138,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
@VisibleForTesting
|
||||
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
|
||||
@VisibleForTesting
|
||||
protected DecorProviderFactory mRoundedCornerFactory;
|
||||
private int mProviderRefreshToken = 0;
|
||||
@VisibleForTesting
|
||||
protected OverlayWindow[] mOverlays = null;
|
||||
@Nullable
|
||||
private DisplayCutoutView[] mCutoutViews;
|
||||
@@ -296,11 +292,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
|
||||
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
|
||||
mDisplayUniqueId);
|
||||
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
|
||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
|
||||
updateHwLayerRoundedCornerDrawable();
|
||||
updateRoundedCornerDrawable();
|
||||
updateRoundedCornerRadii();
|
||||
setupDecorations();
|
||||
setupCameraListener();
|
||||
|
||||
@@ -352,7 +348,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
final String newUniqueId = mContext.getDisplay().getUniqueId();
|
||||
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
|
||||
mDisplayUniqueId = newUniqueId;
|
||||
mRoundedCornerResDelegate.updateDisplayUniqueId(newUniqueId, null);
|
||||
mRoundedCornerResDelegate.reloadAll(newUniqueId);
|
||||
final DisplayDecorationSupport newScreenDecorationSupport =
|
||||
mContext.getDisplay().getDisplayDecorationSupport();
|
||||
// When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
|
||||
@@ -363,12 +359,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
setupDecorations();
|
||||
return;
|
||||
}
|
||||
updateHwLayerRoundedCornerDrawable();
|
||||
updateRoundedCornerDrawable();
|
||||
}
|
||||
if (mScreenDecorHwcLayer != null) {
|
||||
mScreenDecorHwcLayer.onDisplayChanged(displayId);
|
||||
}
|
||||
updateView();
|
||||
updateOrientation();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -410,22 +406,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
}
|
||||
|
||||
private void setupDecorations() {
|
||||
if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) {
|
||||
List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders());
|
||||
List<DecorProvider> decorProviders = mDotFactory.getProviders();
|
||||
|
||||
if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) {
|
||||
if (mHwcScreenDecorationSupport != null) {
|
||||
createHwcOverlay();
|
||||
} else {
|
||||
removeHwcOverlay();
|
||||
decorProviders.addAll(mRoundedCornerFactory.getProviders());
|
||||
}
|
||||
final DisplayCutout cutout = getCutout();
|
||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
||||
if (shouldShowSwLayerCutout(i, cutout) || shouldShowSwLayerRoundedCorner(i, cutout)
|
||||
|| shouldShowSwLayerPrivacyDot(i, cutout)) {
|
||||
if (shouldShowCutout(i, cutout) || shouldShowRoundedCorner(i, cutout)
|
||||
|| shouldShowPrivacyDot(i, cutout)) {
|
||||
Pair<List<DecorProvider>, List<DecorProvider>> pair =
|
||||
DecorProviderKt.partitionAlignedBound(decorProviders, i);
|
||||
decorProviders = pair.getSecond();
|
||||
createOverlay(i, pair.getFirst());
|
||||
createOverlay(i, cutout, pair.getFirst());
|
||||
} else {
|
||||
removeOverlay(i);
|
||||
}
|
||||
@@ -526,6 +522,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
|
||||
private void createOverlay(
|
||||
@BoundsPosition int pos,
|
||||
@Nullable DisplayCutout cutout,
|
||||
@NonNull List<DecorProvider> decorProviders) {
|
||||
if (mOverlays == null) {
|
||||
mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH];
|
||||
@@ -550,7 +547,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
|
||||
mCutoutViews[pos].setColor(mTintColor);
|
||||
overlayView.addView(mCutoutViews[pos]);
|
||||
mCutoutViews[pos].updateRotation(mRotation);
|
||||
updateView(pos, cutout);
|
||||
}
|
||||
|
||||
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
|
||||
@@ -606,7 +603,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
private OverlayWindow overlayForPosition(
|
||||
@BoundsPosition int pos,
|
||||
@NonNull List<DecorProvider> decorProviders) {
|
||||
final OverlayWindow currentOverlay = new OverlayWindow(mContext);
|
||||
final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos);
|
||||
decorProviders.forEach(provider -> {
|
||||
removeOverlayView(provider.getViewId());
|
||||
currentOverlay.addDecorProvider(provider, mRotation);
|
||||
@@ -620,16 +617,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
return currentOverlay;
|
||||
}
|
||||
|
||||
private void updateView() {
|
||||
if (mOverlays == null) {
|
||||
private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
|
||||
if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) {
|
||||
return;
|
||||
}
|
||||
++mProviderRefreshToken;
|
||||
for (final OverlayWindow overlay: mOverlays) {
|
||||
if (overlay == null) {
|
||||
continue;
|
||||
}
|
||||
overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
|
||||
|
||||
// update rounded corner view rotation
|
||||
updateRoundedCornerView(pos, R.id.left, cutout);
|
||||
updateRoundedCornerView(pos, R.id.right, cutout);
|
||||
updateRoundedCornerSize(
|
||||
mRoundedCornerResDelegate.getTopRoundedSize(),
|
||||
mRoundedCornerResDelegate.getBottomRoundedSize());
|
||||
updateRoundedCornerImageView();
|
||||
|
||||
// update cutout view rotation
|
||||
if (mCutoutViews != null && mCutoutViews[pos] != null) {
|
||||
mCutoutViews[pos].updateRotation(mRotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,6 +806,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
int oldRotation = mRotation;
|
||||
mPendingRotationChange = false;
|
||||
updateOrientation();
|
||||
updateRoundedCornerRadii();
|
||||
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
|
||||
setupDecorations();
|
||||
if (mOverlays != null) {
|
||||
@@ -862,32 +866,109 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
mDotViewController.setNewRotation(newRotation);
|
||||
}
|
||||
|
||||
if (!mPendingRotationChange && newRotation != mRotation) {
|
||||
if (mPendingRotationChange) {
|
||||
return;
|
||||
}
|
||||
if (newRotation != mRotation) {
|
||||
mRotation = newRotation;
|
||||
if (mScreenDecorHwcLayer != null) {
|
||||
mScreenDecorHwcLayer.pendingRotationChange = false;
|
||||
mScreenDecorHwcLayer.updateRotation(mRotation);
|
||||
updateHwLayerRoundedCornerSize();
|
||||
updateHwLayerRoundedCornerDrawable();
|
||||
}
|
||||
updateLayoutParams();
|
||||
// update cutout view rotation
|
||||
if (mCutoutViews != null) {
|
||||
for (final DisplayCutoutView cutoutView: mCutoutViews) {
|
||||
if (cutoutView == null) {
|
||||
if (mOverlays != null) {
|
||||
updateLayoutParams();
|
||||
final DisplayCutout cutout = getCutout();
|
||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
||||
if (mOverlays[i] == null) {
|
||||
continue;
|
||||
}
|
||||
cutoutView.updateRotation(mRotation);
|
||||
updateView(i, cutout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update views
|
||||
updateView();
|
||||
}
|
||||
|
||||
private void updateRoundedCornerRadii() {
|
||||
// We should eventually move to just using the intrinsic size of the drawables since
|
||||
// they should be sized to the exact pixels they want to cover. Therefore I'm purposely not
|
||||
// upgrading all of the configs to contain (width, height) pairs. Instead assume that a
|
||||
// device configured using the single integer config value is okay with drawing the corners
|
||||
// as a square
|
||||
final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
|
||||
final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
|
||||
mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
|
||||
final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
|
||||
final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
|
||||
|
||||
if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth()
|
||||
|| oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) {
|
||||
onTuningChanged(SIZE, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRoundedCornerView(@BoundsPosition int pos, int id,
|
||||
@Nullable DisplayCutout cutout) {
|
||||
final View rounded = mOverlays[pos].getRootView().findViewById(id);
|
||||
if (rounded == null) {
|
||||
return;
|
||||
}
|
||||
rounded.setVisibility(View.GONE);
|
||||
if (shouldShowRoundedCorner(pos, cutout)) {
|
||||
final int gravity = getRoundedCornerGravity(pos, id == R.id.left);
|
||||
((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity;
|
||||
setRoundedCornerOrientation(rounded, gravity);
|
||||
rounded.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private int getRoundedCornerGravity(@BoundsPosition int pos, boolean isStart) {
|
||||
final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
|
||||
switch (rotatedPos) {
|
||||
case BOUNDS_POSITION_LEFT:
|
||||
return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.BOTTOM | Gravity.LEFT;
|
||||
case BOUNDS_POSITION_TOP:
|
||||
return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT;
|
||||
case BOUNDS_POSITION_RIGHT:
|
||||
return isStart ? Gravity.TOP | Gravity.RIGHT : Gravity.BOTTOM | Gravity.RIGHT;
|
||||
case BOUNDS_POSITION_BOTTOM:
|
||||
return isStart ? Gravity.BOTTOM | Gravity.LEFT : Gravity.BOTTOM | Gravity.RIGHT;
|
||||
default:
|
||||
throw new IllegalArgumentException("Incorrect position: " + rotatedPos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the rounded corner drawable's view matrix based on the gravity.
|
||||
*
|
||||
* The gravity describes which corner to configure for, and the drawable we are rotating is
|
||||
* assumed to be oriented for the top-left corner of the device regardless of the target corner.
|
||||
* Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
|
||||
* y-axis for the top-right and bottom-left corners.
|
||||
*/
|
||||
private void setRoundedCornerOrientation(View corner, int gravity) {
|
||||
corner.setRotation(0);
|
||||
corner.setScaleX(1);
|
||||
corner.setScaleY(1);
|
||||
switch (gravity) {
|
||||
case Gravity.TOP | Gravity.LEFT:
|
||||
return;
|
||||
case Gravity.TOP | Gravity.RIGHT:
|
||||
corner.setScaleX(-1); // flip X axis
|
||||
return;
|
||||
case Gravity.BOTTOM | Gravity.LEFT:
|
||||
corner.setScaleY(-1); // flip Y axis
|
||||
return;
|
||||
case Gravity.BOTTOM | Gravity.RIGHT:
|
||||
corner.setRotation(180);
|
||||
return;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported gravity: " + gravity);
|
||||
}
|
||||
}
|
||||
private boolean hasRoundedCorners() {
|
||||
return mRoundedCornerFactory.getHasProviders();
|
||||
return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
|
||||
|| mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
|
||||
|| mRoundedCornerResDelegate.isMultipleRadius();
|
||||
}
|
||||
|
||||
private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
|
||||
@@ -906,19 +987,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
|
||||
private boolean shouldShowRoundedCorner(@BoundsPosition int pos,
|
||||
@Nullable DisplayCutout cutout) {
|
||||
return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
|
||||
&& mHwcScreenDecorationSupport == null;
|
||||
}
|
||||
|
||||
private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
|
||||
@Nullable DisplayCutout cutout) {
|
||||
private boolean shouldShowPrivacyDot(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
|
||||
return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
|
||||
}
|
||||
|
||||
private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
|
||||
@Nullable DisplayCutout cutout) {
|
||||
private boolean shouldShowCutout(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
|
||||
final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
|
||||
final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
|
||||
return (bounds != null && !bounds[rotatedPos].isEmpty()
|
||||
@@ -953,33 +1032,54 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
return;
|
||||
}
|
||||
mExecutor.execute(() -> {
|
||||
if (mOverlays == null || !SIZE.equals(key)) {
|
||||
return;
|
||||
}
|
||||
++mProviderRefreshToken;
|
||||
try {
|
||||
final int sizeFactor = Integer.parseInt(newValue);
|
||||
mRoundedCornerResDelegate.updateTuningSizeFactor(sizeFactor, mProviderRefreshToken);
|
||||
} catch (NumberFormatException e) {
|
||||
mRoundedCornerResDelegate.updateTuningSizeFactor(null, mProviderRefreshToken);
|
||||
}
|
||||
Integer[] filterIds = {
|
||||
R.id.rounded_corner_top_left,
|
||||
R.id.rounded_corner_top_right,
|
||||
R.id.rounded_corner_bottom_left,
|
||||
R.id.rounded_corner_bottom_right
|
||||
};
|
||||
for (final OverlayWindow overlay: mOverlays) {
|
||||
if (overlay == null) {
|
||||
continue;
|
||||
if (mOverlays == null) return;
|
||||
if (SIZE.equals(key)) {
|
||||
if (newValue != null) {
|
||||
try {
|
||||
mRoundedCornerResDelegate.updateTuningSizeFactor(
|
||||
Integer.parseInt(newValue));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
|
||||
mDisplayUniqueId);
|
||||
updateRoundedCornerSize(
|
||||
mRoundedCornerResDelegate.getTopRoundedSize(),
|
||||
mRoundedCornerResDelegate.getBottomRoundedSize());
|
||||
}
|
||||
updateHwLayerRoundedCornerSize();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRoundedCornerDrawable() {
|
||||
mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
|
||||
updateRoundedCornerImageView();
|
||||
}
|
||||
|
||||
private void updateRoundedCornerImageView() {
|
||||
final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable();
|
||||
final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable();
|
||||
|
||||
if (mScreenDecorHwcLayer != null) {
|
||||
mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOverlays == null) {
|
||||
return;
|
||||
}
|
||||
final ColorStateList colorStateList = ColorStateList.valueOf(mTintColor);
|
||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
||||
if (mOverlays[i] == null) {
|
||||
continue;
|
||||
}
|
||||
final ViewGroup overlayView = mOverlays[i].getRootView();
|
||||
((ImageView) overlayView.findViewById(R.id.left)).setImageTintList(colorStateList);
|
||||
((ImageView) overlayView.findViewById(R.id.right)).setImageTintList(colorStateList);
|
||||
((ImageView) overlayView.findViewById(R.id.left)).setImageDrawable(
|
||||
isTopRoundedCorner(i, R.id.left) ? top : bottom);
|
||||
((ImageView) overlayView.findViewById(R.id.right)).setImageDrawable(
|
||||
isTopRoundedCorner(i, R.id.right) ? top : bottom);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHwLayerRoundedCornerDrawable() {
|
||||
if (mScreenDecorHwcLayer == null) {
|
||||
return;
|
||||
@@ -994,6 +1094,25 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
|
||||
switch (pos) {
|
||||
case BOUNDS_POSITION_LEFT:
|
||||
case BOUNDS_POSITION_RIGHT:
|
||||
if (mRotation == ROTATION_270) {
|
||||
return id == R.id.left ? false : true;
|
||||
} else {
|
||||
return id == R.id.left ? true : false;
|
||||
}
|
||||
case BOUNDS_POSITION_TOP:
|
||||
return true;
|
||||
case BOUNDS_POSITION_BOTTOM:
|
||||
return false;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown bounds position");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHwLayerRoundedCornerSize() {
|
||||
if (mScreenDecorHwcLayer == null) {
|
||||
return;
|
||||
@@ -1005,6 +1124,28 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
||||
mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
|
||||
}
|
||||
|
||||
private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) {
|
||||
|
||||
if (mScreenDecorHwcLayer != null) {
|
||||
mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth());
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOverlays == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
||||
if (mOverlays[i] == null) {
|
||||
continue;
|
||||
}
|
||||
final ViewGroup overlayView = mOverlays[i].getRootView();
|
||||
setSize(overlayView.findViewById(R.id.left),
|
||||
isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom);
|
||||
setSize(overlayView.findViewById(R.id.right),
|
||||
isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void setSize(View view, Size pixelSize) {
|
||||
LayoutParams params = view.getLayoutParams();
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
package com.android.systemui.decor
|
||||
import android.content.Context
|
||||
import android.view.DisplayCutout
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -38,20 +38,9 @@ abstract class DecorProvider {
|
||||
/** The aligned bounds for the view which is created through inflateView() */
|
||||
abstract val alignedBounds: List<Int>
|
||||
|
||||
/**
|
||||
* Called when res info changed.
|
||||
* Child provider needs to implement it if its view needs to be updated.
|
||||
*/
|
||||
abstract fun onReloadResAndMeasure(
|
||||
view: View,
|
||||
reloadToken: Int,
|
||||
@Surface.Rotation rotation: Int,
|
||||
displayUniqueId: String? = null
|
||||
)
|
||||
|
||||
/** Inflate view into parent as current rotation */
|
||||
abstract fun inflateView(
|
||||
context: Context,
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup,
|
||||
@Surface.Rotation rotation: Int
|
||||
): View
|
||||
|
||||
@@ -16,22 +16,31 @@
|
||||
package com.android.systemui.decor
|
||||
|
||||
import android.annotation.IdRes
|
||||
import android.content.Context
|
||||
import android.view.DisplayCutout
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.android.systemui.RegionInterceptingFrameLayout
|
||||
import com.android.systemui.R
|
||||
import java.util.HashMap
|
||||
|
||||
class OverlayWindow(private val context: Context) {
|
||||
class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: Int) {
|
||||
|
||||
val rootView = RegionInterceptingFrameLayout(context) as ViewGroup
|
||||
private val viewProviderMap = mutableMapOf<Int, Pair<View, DecorProvider>>()
|
||||
private val layoutId: Int
|
||||
get() {
|
||||
return if (pos == DisplayCutout.BOUNDS_POSITION_LEFT ||
|
||||
pos == DisplayCutout.BOUNDS_POSITION_TOP) {
|
||||
R.layout.rounded_corners_top
|
||||
} else {
|
||||
R.layout.rounded_corners_bottom
|
||||
}
|
||||
}
|
||||
|
||||
fun addDecorProvider(
|
||||
decorProvider: DecorProvider,
|
||||
@Surface.Rotation rotation: Int
|
||||
) {
|
||||
val view = decorProvider.inflateView(context, rootView, rotation)
|
||||
val rootView = layoutInflater.inflate(layoutId, null) as ViewGroup
|
||||
private val viewProviderMap: MutableMap<Int, Pair<View, DecorProvider>> = HashMap()
|
||||
|
||||
fun addDecorProvider(decorProvider: DecorProvider, @Surface.Rotation rotation: Int) {
|
||||
val view = decorProvider.inflateView(layoutInflater, rootView, rotation)
|
||||
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
|
||||
}
|
||||
|
||||
@@ -47,35 +56,4 @@ class OverlayWindow(private val context: Context) {
|
||||
viewProviderMap.remove(id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply new configuration info into views.
|
||||
* @param filterIds target view ids. Apply to all if null.
|
||||
* @param rotation current or new rotation direction.
|
||||
* @param displayUniqueId new displayUniqueId if any.
|
||||
*/
|
||||
fun onReloadResAndMeasure(
|
||||
filterIds: Array<Int>? = null,
|
||||
reloadToken: Int,
|
||||
@Surface.Rotation rotation: Int,
|
||||
displayUniqueId: String? = null
|
||||
) {
|
||||
filterIds?.forEach { id ->
|
||||
viewProviderMap[id]?.let {
|
||||
it.second.onReloadResAndMeasure(
|
||||
view = it.first,
|
||||
reloadToken = reloadToken,
|
||||
displayUniqueId = displayUniqueId,
|
||||
rotation = rotation)
|
||||
}
|
||||
} ?: run {
|
||||
viewProviderMap.values.forEach {
|
||||
it.second.onReloadResAndMeasure(
|
||||
view = it.first,
|
||||
reloadToken = reloadToken,
|
||||
displayUniqueId = displayUniqueId,
|
||||
rotation = rotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.systemui.decor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.view.DisplayCutout
|
||||
import android.view.LayoutInflater
|
||||
@@ -77,21 +76,12 @@ class PrivacyDotCornerDecorProviderImpl(
|
||||
private val layoutId: Int
|
||||
) : CornerDecorProvider() {
|
||||
|
||||
override fun onReloadResAndMeasure(
|
||||
view: View,
|
||||
reloadToken: Int,
|
||||
rotation: Int,
|
||||
displayUniqueId: String?
|
||||
) {
|
||||
// Do nothing here because it is handled inside PrivacyDotViewController
|
||||
}
|
||||
|
||||
override fun inflateView(
|
||||
context: Context,
|
||||
inflater: LayoutInflater,
|
||||
parent: ViewGroup,
|
||||
@Surface.Rotation rotation: Int
|
||||
): View {
|
||||
LayoutInflater.from(context).inflate(layoutId, parent, true)
|
||||
inflater.inflate(layoutId, parent, true)
|
||||
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.decor
|
||||
|
||||
import android.view.DisplayCutout
|
||||
import com.android.systemui.R
|
||||
|
||||
class RoundedCornerDecorProviderFactory(
|
||||
private val roundedCornerResDelegate: RoundedCornerResDelegate
|
||||
) : DecorProviderFactory() {
|
||||
|
||||
override val hasProviders: Boolean
|
||||
get() = roundedCornerResDelegate.run {
|
||||
// We don't consider isMultipleRadius here because it makes no sense if size is zero.
|
||||
topRoundedSize.width > 0 || bottomRoundedSize.width > 0
|
||||
}
|
||||
|
||||
override val providers: List<DecorProvider>
|
||||
get() {
|
||||
val hasTop = roundedCornerResDelegate.topRoundedSize.width > 0
|
||||
val hasBottom = roundedCornerResDelegate.bottomRoundedSize.width > 0
|
||||
return when {
|
||||
hasTop && hasBottom -> listOf(
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_top_left,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate),
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_top_right,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate),
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_bottom_left,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate),
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_bottom_right,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate)
|
||||
)
|
||||
hasTop -> listOf(
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_top_left,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate),
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_top_right,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate)
|
||||
)
|
||||
hasBottom -> listOf(
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_bottom_left,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate),
|
||||
RoundedCornerDecorProviderImpl(
|
||||
viewId = R.id.rounded_corner_bottom_right,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||
roundedCornerResDelegate = roundedCornerResDelegate)
|
||||
)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.decor
|
||||
|
||||
import android.content.Context
|
||||
import android.view.DisplayCutout
|
||||
import android.view.Gravity
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import com.android.systemui.R
|
||||
|
||||
class RoundedCornerDecorProviderImpl(
|
||||
override val viewId: Int,
|
||||
@DisplayCutout.BoundsPosition override val alignedBound1: Int,
|
||||
@DisplayCutout.BoundsPosition override val alignedBound2: Int,
|
||||
private val roundedCornerResDelegate: RoundedCornerResDelegate
|
||||
) : CornerDecorProvider() {
|
||||
|
||||
private val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
|
||||
override fun inflateView(
|
||||
context: Context,
|
||||
parent: ViewGroup,
|
||||
@Surface.Rotation rotation: Int
|
||||
): View {
|
||||
return ImageView(context).also { view ->
|
||||
// View
|
||||
view.id = viewId
|
||||
initView(view, rotation)
|
||||
|
||||
// LayoutParams
|
||||
val layoutSize = if (isTop) {
|
||||
roundedCornerResDelegate.topRoundedSize
|
||||
} else {
|
||||
roundedCornerResDelegate.bottomRoundedSize
|
||||
}
|
||||
val params = FrameLayout.LayoutParams(
|
||||
layoutSize.width,
|
||||
layoutSize.height,
|
||||
alignedBound1.toLayoutGravity(rotation) or
|
||||
alignedBound2.toLayoutGravity(rotation))
|
||||
|
||||
// AddView
|
||||
parent.addView(view, params)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
|
||||
view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
|
||||
view.adjustRotation(alignedBounds, rotation)
|
||||
view.setColorFilter(IMAGE_TINT_COLOR)
|
||||
}
|
||||
|
||||
override fun onReloadResAndMeasure(
|
||||
view: View,
|
||||
reloadToken: Int,
|
||||
@Surface.Rotation rotation: Int,
|
||||
displayUniqueId: String?
|
||||
) {
|
||||
roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
|
||||
|
||||
initView((view as ImageView), rotation)
|
||||
|
||||
val layoutSize = if (isTop) {
|
||||
roundedCornerResDelegate.topRoundedSize
|
||||
} else {
|
||||
roundedCornerResDelegate.bottomRoundedSize
|
||||
}
|
||||
(view.layoutParams as FrameLayout.LayoutParams).let {
|
||||
it.width = layoutSize.width
|
||||
it.height = layoutSize.height
|
||||
it.gravity = alignedBound1.toLayoutGravity(rotation) or
|
||||
alignedBound2.toLayoutGravity(rotation)
|
||||
view.setLayoutParams(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val IMAGE_TINT_COLOR: Int = 0xFF000000.toInt()
|
||||
|
||||
@DisplayCutout.BoundsPosition
|
||||
private fun Int.toLayoutGravity(@Surface.Rotation rotation: Int): Int = when (rotation) {
|
||||
Surface.ROTATION_0 -> when (this) {
|
||||
DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.LEFT
|
||||
DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.TOP
|
||||
DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.RIGHT
|
||||
else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.BOTTOM
|
||||
}
|
||||
Surface.ROTATION_90 -> when (this) {
|
||||
DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.BOTTOM
|
||||
DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.LEFT
|
||||
DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.TOP
|
||||
else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
|
||||
}
|
||||
Surface.ROTATION_270 -> when (this) {
|
||||
DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.TOP
|
||||
DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.RIGHT
|
||||
DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.BOTTOM
|
||||
else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
|
||||
}
|
||||
else /* Surface.ROTATION_180 */ -> when (this) {
|
||||
DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.RIGHT
|
||||
DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.BOTTOM
|
||||
DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.LEFT
|
||||
else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.TOP
|
||||
}
|
||||
}
|
||||
|
||||
private fun ImageView.setRoundedCornerImage(
|
||||
resDelegate: RoundedCornerResDelegate,
|
||||
isTop: Boolean
|
||||
) {
|
||||
val drawable = if (isTop)
|
||||
resDelegate.topRoundedDrawable
|
||||
else
|
||||
resDelegate.bottomRoundedDrawable
|
||||
|
||||
if (drawable != null) {
|
||||
setImageDrawable(drawable)
|
||||
} else {
|
||||
setImageResource(
|
||||
if (isTop)
|
||||
R.drawable.rounded_corner_top
|
||||
else
|
||||
R.drawable.rounded_corner_bottom
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the rounded corner drawable's view matrix based on the gravity.
|
||||
*
|
||||
* The gravity describes which corner to configure for, and the drawable we are rotating is assumed
|
||||
* to be oriented for the top-left corner of the device regardless of the target corner.
|
||||
* Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
|
||||
* y-axis for the top-right and bottom-left corners.
|
||||
*/
|
||||
private fun ImageView.adjustRotation(alignedBounds: List<Int>, @Surface.Rotation rotation: Int) {
|
||||
var newRotation = 0F
|
||||
var newScaleX = 1F
|
||||
var newScaleY = 1F
|
||||
|
||||
val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
val isLeft = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)
|
||||
when (rotation) {
|
||||
Surface.ROTATION_0 -> when {
|
||||
isTop && isLeft -> {}
|
||||
isTop && !isLeft -> { newScaleX = -1F }
|
||||
!isTop && isLeft -> { newScaleY = -1F }
|
||||
else /* !isTop && !isLeft */ -> { newRotation = 180F }
|
||||
}
|
||||
Surface.ROTATION_90 -> when {
|
||||
isTop && isLeft -> { newScaleY = -1F }
|
||||
isTop && !isLeft -> {}
|
||||
!isTop && isLeft -> { newRotation = 180F }
|
||||
else /* !isTop && !isLeft */ -> { newScaleX = -1F }
|
||||
}
|
||||
Surface.ROTATION_270 -> when {
|
||||
isTop && isLeft -> { newScaleX = -1F }
|
||||
isTop && !isLeft -> { newRotation = 180F }
|
||||
!isTop && isLeft -> {}
|
||||
else /* !isTop && !isLeft */ -> { newScaleY = -1F }
|
||||
}
|
||||
else /* Surface.ROTATION_180 */ -> when {
|
||||
isTop && isLeft -> { newRotation = 180F }
|
||||
isTop && !isLeft -> { newScaleY = -1F }
|
||||
!isTop && isLeft -> { newScaleX = -1F }
|
||||
else /* !isTop && !isLeft */ -> {}
|
||||
}
|
||||
}
|
||||
|
||||
this.rotation = newRotation
|
||||
this.scaleX = newScaleX
|
||||
this.scaleY = newScaleY
|
||||
}
|
||||
@@ -36,8 +36,6 @@ class RoundedCornerResDelegate(
|
||||
private val density: Float
|
||||
get() = res.displayMetrics.density
|
||||
|
||||
private var reloadToken: Int = 0
|
||||
|
||||
var isMultipleRadius: Boolean = false
|
||||
private set
|
||||
|
||||
@@ -62,26 +60,12 @@ class RoundedCornerResDelegate(
|
||||
reloadMeasures()
|
||||
}
|
||||
|
||||
private fun reloadAll(newReloadToken: Int) {
|
||||
if (reloadToken == newReloadToken) {
|
||||
return
|
||||
}
|
||||
reloadToken = newReloadToken
|
||||
fun reloadAll(newDisplayUniqueId: String?) {
|
||||
displayUniqueId = newDisplayUniqueId
|
||||
reloadDrawables()
|
||||
reloadMeasures()
|
||||
}
|
||||
|
||||
fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
|
||||
if (displayUniqueId != newDisplayUniqueId) {
|
||||
displayUniqueId = newDisplayUniqueId
|
||||
newReloadToken ?.let { reloadToken = it }
|
||||
reloadDrawables()
|
||||
reloadMeasures()
|
||||
} else {
|
||||
newReloadToken?.let { reloadAll(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadDrawables() {
|
||||
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
|
||||
isMultipleRadius = getIsMultipleRadius(configIdx)
|
||||
@@ -101,6 +85,34 @@ class RoundedCornerResDelegate(
|
||||
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
|
||||
backupDrawableId = R.drawable.rounded_corner_bottom
|
||||
) ?: roundedDrawable
|
||||
|
||||
// If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
|
||||
// (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
|
||||
if (isMultipleRadius) {
|
||||
roundedSize = Size(
|
||||
roundedDrawable?.intrinsicWidth ?: 0,
|
||||
roundedDrawable?.intrinsicHeight ?: 0)
|
||||
topRoundedDrawable?.let {
|
||||
topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
|
||||
}
|
||||
bottomRoundedDrawable?.let {
|
||||
bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
|
||||
}
|
||||
} else {
|
||||
val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
|
||||
val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
|
||||
val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
|
||||
roundedSize = Size(defaultRadius, defaultRadius)
|
||||
topRoundedSize = Size(topRadius, topRadius)
|
||||
bottomRoundedSize = Size(bottomRadius, bottomRadius)
|
||||
}
|
||||
|
||||
if (topRoundedSize.width == 0) {
|
||||
topRoundedSize = roundedSize
|
||||
}
|
||||
if (bottomRoundedSize.width == 0) {
|
||||
bottomRoundedSize = roundedSize
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadMeasures(roundedSizeFactor: Int? = null) {
|
||||
@@ -125,8 +137,8 @@ class RoundedCornerResDelegate(
|
||||
bottomRoundedSize = Size(bottomRadius, bottomRadius)
|
||||
}
|
||||
|
||||
if (roundedSizeFactor != null && roundedSizeFactor > 0) {
|
||||
val length: Int = (roundedSizeFactor * density).toInt()
|
||||
roundedSizeFactor ?.let {
|
||||
val length: Int = (it * density).toInt()
|
||||
roundedSize = Size(length, length)
|
||||
}
|
||||
|
||||
@@ -138,11 +150,7 @@ class RoundedCornerResDelegate(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTuningSizeFactor(factor: Int?, newReloadToken: Int) {
|
||||
if (reloadToken == newReloadToken) {
|
||||
return
|
||||
}
|
||||
reloadToken = newReloadToken
|
||||
fun updateTuningSizeFactor(factor: Int) {
|
||||
reloadMeasures(factor)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isA;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -60,11 +61,9 @@ import android.util.Size;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowMetrics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -103,7 +102,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
private SecureSettings mSecureSettings;
|
||||
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private FakeThreadFactory mThreadFactory;
|
||||
private ArrayList<DecorProvider> mPrivacyDecorProviders;
|
||||
private ArrayList<DecorProvider> mDecorProviders;
|
||||
@Mock
|
||||
private Display mDisplay;
|
||||
@Mock
|
||||
@@ -198,43 +197,17 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
reset(mTunerService);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private int[] getRoundCornerIdsFromOverlayId(@DisplayCutout.BoundsPosition int overlayId) {
|
||||
switch (overlayId) {
|
||||
case BOUNDS_POSITION_LEFT:
|
||||
return new int[] {
|
||||
R.id.rounded_corner_top_left,
|
||||
R.id.rounded_corner_top_left };
|
||||
case BOUNDS_POSITION_TOP:
|
||||
return new int[] {
|
||||
R.id.rounded_corner_top_left,
|
||||
R.id.rounded_corner_top_right };
|
||||
case BOUNDS_POSITION_RIGHT:
|
||||
return new int[] {
|
||||
R.id.rounded_corner_top_right,
|
||||
R.id.rounded_corner_bottom_right };
|
||||
case BOUNDS_POSITION_BOTTOM:
|
||||
return new int[] {
|
||||
R.id.rounded_corner_bottom_left,
|
||||
R.id.rounded_corner_bottom_right };
|
||||
default:
|
||||
throw new IllegalArgumentException("unknown overlayId: " + overlayId);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyRoundedCornerViewsExist(
|
||||
private void verifyRoundedCornerViewsVisibility(
|
||||
@DisplayCutout.BoundsPosition final int overlayId,
|
||||
@View.Visibility final boolean isExist) {
|
||||
@View.Visibility final int visibility) {
|
||||
final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView();
|
||||
for (int id: getRoundCornerIdsFromOverlayId(overlayId)) {
|
||||
final View view = overlay.findViewById(id);
|
||||
if (isExist) {
|
||||
assertNotNull(view);
|
||||
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
} else {
|
||||
assertNull(view);
|
||||
}
|
||||
}
|
||||
final View left = overlay.findViewById(R.id.left);
|
||||
final View right = overlay.findViewById(R.id.right);
|
||||
assertNotNull(left);
|
||||
assertNotNull(right);
|
||||
assertThat(left.getVisibility()).isEqualTo(visibility);
|
||||
assertThat(right.getVisibility()).isEqualTo(visibility);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -378,8 +351,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall not exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
||||
|
||||
// Privacy dots shall exist but invisible
|
||||
verifyDotViewsVisibility(View.INVISIBLE);
|
||||
@@ -407,8 +380,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Privacy dots shall not exist
|
||||
verifyDotViewsNullable(true);
|
||||
@@ -435,8 +408,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Privacy dots shall exist but invisible
|
||||
verifyDotViewsVisibility(View.INVISIBLE);
|
||||
@@ -476,26 +449,21 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
|
||||
mScreenDecorations.start();
|
||||
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
||||
.findViewById(R.id.rounded_corner_top_left);
|
||||
.findViewById(R.id.left);
|
||||
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
||||
.findViewById(R.id.rounded_corner_top_right);
|
||||
ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams();
|
||||
ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams();
|
||||
assertEquals(leftParams.width, testTopRadius);
|
||||
assertEquals(leftParams.height, testTopRadius);
|
||||
assertEquals(rightParams.width, testTopRadius);
|
||||
assertEquals(rightParams.height, testTopRadius);
|
||||
|
||||
.findViewById(R.id.right);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius));
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius));
|
||||
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
||||
.findViewById(R.id.rounded_corner_bottom_left);
|
||||
.findViewById(R.id.left);
|
||||
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
||||
.findViewById(R.id.rounded_corner_bottom_right);
|
||||
leftParams = leftRoundedCorner.getLayoutParams();
|
||||
rightParams = rightRoundedCorner.getLayoutParams();
|
||||
assertEquals(leftParams.width, testBottomRadius);
|
||||
assertEquals(leftParams.height, testBottomRadius);
|
||||
assertEquals(rightParams.width, testBottomRadius);
|
||||
assertEquals(rightParams.height, testBottomRadius);
|
||||
.findViewById(R.id.right);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius));
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -511,27 +479,31 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
.when(mScreenDecorations).getCutout();
|
||||
|
||||
mScreenDecorations.start();
|
||||
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||
.findViewById(R.id.rounded_corner_top_left);
|
||||
View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||
.findViewById(R.id.rounded_corner_bottom_left);
|
||||
ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams();
|
||||
ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams();
|
||||
assertEquals(topParams.width, testTopRadius);
|
||||
assertEquals(topParams.height, testTopRadius);
|
||||
assertEquals(bottomParams.width, testBottomRadius);
|
||||
assertEquals(bottomParams.height, testBottomRadius);
|
||||
final Size topRadius = new Size(testTopRadius, testTopRadius);
|
||||
final Size bottomRadius = new Size(testBottomRadius, testBottomRadius);
|
||||
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||
.findViewById(R.id.left);
|
||||
boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
|
||||
|
||||
topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||
.findViewById(R.id.rounded_corner_top_right);
|
||||
bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||
.findViewById(R.id.rounded_corner_bottom_right);
|
||||
topParams = topRoundedCorner.getLayoutParams();
|
||||
bottomParams = bottomRoundedCorner.getLayoutParams();
|
||||
assertEquals(topParams.width, testTopRadius);
|
||||
assertEquals(topParams.height, testTopRadius);
|
||||
assertEquals(bottomParams.width, testBottomRadius);
|
||||
assertEquals(bottomParams.height, testBottomRadius);
|
||||
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||
.findViewById(R.id.right);
|
||||
isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
|
||||
|
||||
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||
.findViewById(R.id.left);
|
||||
isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
|
||||
|
||||
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||
.findViewById(R.id.right);
|
||||
isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.right);
|
||||
verify(mScreenDecorations, atLeastOnce())
|
||||
.setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -551,8 +523,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Privacy dots shall not exist
|
||||
verifyDotViewsNullable(true);
|
||||
@@ -585,8 +557,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Privacy dots shall exist but invisible
|
||||
verifyDotViewsVisibility(View.INVISIBLE);
|
||||
@@ -645,10 +617,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
|
||||
// Top rounded corner views shall exist because of cutout
|
||||
// but be gone because of no rounded corner
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
||||
// Bottom rounded corner views shall exist because of privacy dot
|
||||
// but be gone because of no rounded corner
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
||||
|
||||
// Privacy dots shall exist but invisible
|
||||
verifyDotViewsVisibility(View.INVISIBLE);
|
||||
@@ -676,7 +648,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
|
||||
// Left rounded corner views shall exist because of cutout
|
||||
// but be gone because of no rounded corner
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_LEFT, View.GONE);
|
||||
|
||||
// Top privacy dots shall not exist because of no privacy
|
||||
verifyDotViewsNullable(true);
|
||||
@@ -728,8 +700,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Top privacy dots shall not exist because of no privacy dot
|
||||
verifyDotViewsNullable(true);
|
||||
@@ -756,8 +728,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
|
||||
// Rounded corner views shall exist
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
||||
|
||||
// Top privacy dots shall exist but invisible
|
||||
verifyDotViewsVisibility(View.INVISIBLE);
|
||||
@@ -887,7 +859,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verifyOverlaysExistAndAdded(true, false, true, false);
|
||||
|
||||
// Verify each privacy dot id appears only once
|
||||
mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
|
||||
mDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
|
||||
int findCount = 0;
|
||||
for (OverlayWindow overlay: mScreenDecorations.mOverlays) {
|
||||
if (overlay == null) {
|
||||
@@ -941,8 +913,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
// Both top and bottom windows should be added because of privacy dot,
|
||||
// but their visibility shall be gone because of no rounding.
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
||||
|
||||
when(mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
|
||||
@@ -953,8 +925,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
// Both top and bottom windows should be added because of privacy dot,
|
||||
// but their visibility shall be gone because of no rounding.
|
||||
verifyOverlaysExistAndAdded(false, true, false, true);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1202,14 +1174,14 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
|
||||
|
||||
mPrivacyDecorProviders = new ArrayList<>();
|
||||
mDecorProviders = new ArrayList<>();
|
||||
if (privacyDot) {
|
||||
mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
|
||||
mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider);
|
||||
mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
|
||||
mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
|
||||
mDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
|
||||
mDecorProviders.add(mPrivacyDotTopRightDecorProvider);
|
||||
mDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
|
||||
mDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
|
||||
}
|
||||
when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders);
|
||||
when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mDecorProviders);
|
||||
when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,19 +19,25 @@ package com.android.systemui.decor
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.view.DisplayCutout
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Surface
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.anyInt
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
@@ -39,88 +45,62 @@ import org.mockito.Mockito.verify
|
||||
class OverlayWindowTest : SysuiTestCase() {
|
||||
|
||||
companion object {
|
||||
private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container
|
||||
private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_right_container
|
||||
private val TEST_DECOR_VIEW_ID = R.id.privacy_dot_bottom_right_container
|
||||
private val TEST_DECOR_LAYOUT_ID = R.layout.privacy_dot_bottom_right
|
||||
}
|
||||
|
||||
private lateinit var overlay: OverlayWindow
|
||||
private lateinit var decorProvider1: DecorProvider
|
||||
private lateinit var decorProvider2: DecorProvider
|
||||
|
||||
@Mock private lateinit var layoutInflater: LayoutInflater
|
||||
@Mock private lateinit var decorProvider: DecorProvider
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
|
||||
viewId = TEST_DECOR_VIEW_ID_1,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
|
||||
layoutId = R.layout.privacy_dot_top_left))
|
||||
decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
|
||||
viewId = TEST_DECOR_VIEW_ID_2,
|
||||
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||
layoutId = R.layout.privacy_dot_bottom_right))
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
overlay = OverlayWindow(mContext)
|
||||
layoutInflater = spy(LayoutInflater.from(mContext))
|
||||
|
||||
overlay = OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
|
||||
|
||||
whenever(decorProvider.viewId).thenReturn(TEST_DECOR_VIEW_ID)
|
||||
whenever(decorProvider.inflateView(
|
||||
eq(layoutInflater),
|
||||
eq(overlay.rootView),
|
||||
anyInt())
|
||||
).then {
|
||||
val layoutInflater = it.getArgument<LayoutInflater>(0)
|
||||
val parent = it.getArgument<ViewGroup>(1)
|
||||
layoutInflater.inflate(TEST_DECOR_LAYOUT_ID, parent)
|
||||
return@then parent.getChildAt(parent.childCount - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnyBoundsPositionShallNoExceptionForConstructor() {
|
||||
OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_LEFT)
|
||||
OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
|
||||
OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_BOTTOM)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddProvider() {
|
||||
@Surface.Rotation val rotation = Surface.ROTATION_270
|
||||
overlay.addDecorProvider(decorProvider1, rotation)
|
||||
overlay.addDecorProvider(decorProvider2, rotation)
|
||||
|
||||
verify(decorProvider1, times(1)).inflateView(
|
||||
mContext, overlay.rootView, rotation)
|
||||
verify(decorProvider2, times(1)).inflateView(
|
||||
mContext, overlay.rootView, rotation)
|
||||
|
||||
val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
||||
Assert.assertNotNull(view1FoundFromRootView)
|
||||
Assert.assertEquals(view1FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_1))
|
||||
val view2FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_2)
|
||||
Assert.assertNotNull(view2FoundFromRootView)
|
||||
Assert.assertEquals(view2FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_2))
|
||||
overlay.addDecorProvider(decorProvider, rotation)
|
||||
verify(decorProvider, Mockito.times(1)).inflateView(
|
||||
eq(layoutInflater), eq(overlay.rootView), eq(rotation))
|
||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
|
||||
Assert.assertNotNull(viewFoundFromRootView)
|
||||
Assert.assertEquals(viewFoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveView() {
|
||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
||||
overlay.removeView(TEST_DECOR_VIEW_ID_1)
|
||||
|
||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
||||
@Surface.Rotation val rotation = Surface.ROTATION_270
|
||||
overlay.addDecorProvider(decorProvider, rotation)
|
||||
overlay.removeView(TEST_DECOR_VIEW_ID)
|
||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
|
||||
Assert.assertNull(viewFoundFromRootView)
|
||||
Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnReloadResAndMeasureWithoutIds() {
|
||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
||||
|
||||
overlay.onReloadResAndMeasure(
|
||||
reloadToken = 1,
|
||||
rotation = Surface.ROTATION_90,
|
||||
displayUniqueId = null)
|
||||
verify(decorProvider1, times(1)).onReloadResAndMeasure(
|
||||
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
|
||||
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
||||
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnReloadResAndMeasureWithIds() {
|
||||
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
||||
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
||||
|
||||
overlay.onReloadResAndMeasure(
|
||||
filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
|
||||
reloadToken = 1,
|
||||
rotation = Surface.ROTATION_90,
|
||||
displayUniqueId = null)
|
||||
verify(decorProvider1, never()).onReloadResAndMeasure(
|
||||
overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
|
||||
verify(decorProvider2, times(1)).onReloadResAndMeasure(
|
||||
overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
|
||||
Assert.assertNull(overlay.getView(TEST_DECOR_LAYOUT_ID))
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.decor
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.view.DisplayCutout
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
@@ -31,6 +32,7 @@ import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
@SmallTest
|
||||
class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() {
|
||||
private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.decor
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.util.Size
|
||||
import android.view.DisplayCutout
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.spy
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class RoundedCornerDecorProviderFactoryTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate
|
||||
private lateinit var roundedCornerDecorProviderFactory: RoundedCornerDecorProviderFactory
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
roundedCornerResDelegate = spy(RoundedCornerResDelegate(mContext.resources, null))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNoRoundedCorners() {
|
||||
Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
|
||||
Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
|
||||
Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
|
||||
|
||||
roundedCornerDecorProviderFactory =
|
||||
RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
|
||||
|
||||
Assert.assertEquals(false, roundedCornerDecorProviderFactory.hasProviders)
|
||||
Assert.assertEquals(0, roundedCornerDecorProviderFactory.providers.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testHasRoundedCornersIfTopWidthLargerThan0() {
|
||||
Mockito.doReturn(Size(1, 0)).`when`(roundedCornerResDelegate).topRoundedSize
|
||||
Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
|
||||
Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
|
||||
|
||||
roundedCornerDecorProviderFactory =
|
||||
RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
|
||||
|
||||
Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
|
||||
roundedCornerDecorProviderFactory.providers.let { providers ->
|
||||
Assert.assertEquals(2, providers.size)
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_top_left)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
|
||||
})
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_top_right)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testHasRoundedCornersIfBottomWidthLargerThan0() {
|
||||
Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
|
||||
Mockito.doReturn(Size(1, 1)).`when`(roundedCornerResDelegate).bottomRoundedSize
|
||||
Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
|
||||
|
||||
roundedCornerDecorProviderFactory =
|
||||
RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
|
||||
|
||||
Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
|
||||
roundedCornerDecorProviderFactory.providers.let { providers ->
|
||||
Assert.assertEquals(2, providers.size)
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_bottom_left)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
|
||||
})
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_bottom_right)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test4CornerDecorProvidersInfo() {
|
||||
Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).topRoundedSize
|
||||
Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).bottomRoundedSize
|
||||
Mockito.doReturn(true).`when`(roundedCornerResDelegate).isMultipleRadius
|
||||
|
||||
roundedCornerDecorProviderFactory =
|
||||
RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
|
||||
|
||||
Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
|
||||
roundedCornerDecorProviderFactory.providers.let { providers ->
|
||||
Assert.assertEquals(4, providers.size)
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_top_left)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
|
||||
})
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_top_right)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
|
||||
})
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_bottom_left)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
|
||||
})
|
||||
Assert.assertEquals(1, providers.count {
|
||||
((it.viewId == R.id.rounded_corner_bottom_right)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
|
||||
and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUpdateDisplayUniqueId() {
|
||||
fun testReloadAllAndDefaultRadius() {
|
||||
mContext.orCreateTestableResources.addOverrides(
|
||||
mockTypeArray = mockTypedArray,
|
||||
radius = 3,
|
||||
@@ -65,34 +65,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
|
||||
radiusTop = 6,
|
||||
radiusBottom = 0)
|
||||
|
||||
roundedCornerResDelegate.updateDisplayUniqueId("test", null)
|
||||
|
||||
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
|
||||
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNotUpdateDisplayUniqueIdButChangeRefreshToken() {
|
||||
mContext.orCreateTestableResources.addOverrides(
|
||||
mockTypeArray = mockTypedArray,
|
||||
radius = 3,
|
||||
radiusTop = 0,
|
||||
radiusBottom = 4,
|
||||
multipleRadius = false)
|
||||
|
||||
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
|
||||
|
||||
assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
|
||||
assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize)
|
||||
assertEquals(false, roundedCornerResDelegate.isMultipleRadius)
|
||||
|
||||
mContext.orCreateTestableResources.addOverrides(
|
||||
mockTypeArray = mockTypedArray,
|
||||
radius = 5,
|
||||
radiusTop = 6,
|
||||
radiusBottom = 0)
|
||||
|
||||
roundedCornerResDelegate.updateDisplayUniqueId(null, 1)
|
||||
roundedCornerResDelegate.reloadAll("test")
|
||||
|
||||
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
|
||||
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
|
||||
@@ -109,21 +82,11 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
|
||||
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
|
||||
|
||||
val factor = 5
|
||||
roundedCornerResDelegate.updateTuningSizeFactor(factor, 1)
|
||||
roundedCornerResDelegate.updateTuningSizeFactor(factor)
|
||||
val length = (factor * mContext.resources.displayMetrics.density).toInt()
|
||||
|
||||
assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
|
||||
assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize)
|
||||
|
||||
mContext.orCreateTestableResources.addOverrides(
|
||||
mockTypeArray = mockTypedArray,
|
||||
radiusTop = 1,
|
||||
radiusBottom = 2,
|
||||
multipleRadius = false)
|
||||
roundedCornerResDelegate.updateTuningSizeFactor(null, 2)
|
||||
|
||||
assertEquals(Size(1, 1), roundedCornerResDelegate.topRoundedSize)
|
||||
assertEquals(Size(2, 2), roundedCornerResDelegate.bottomRoundedSize)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user