[automerge] Re-land "Move rounded corner to provider" 2p: 4301034952
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17630309 Bug: 218951516 Change-Id: I385f6cb2264503e3f8759e66b4f170246b0c4763
This commit is contained in:
@@ -1,40 +0,0 @@
|
|||||||
<?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>
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?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>
|
|
||||||
@@ -170,5 +170,11 @@
|
|||||||
<item type="id" name="action_move_bottom_right"/>
|
<item type="id" name="action_move_bottom_right"/>
|
||||||
<item type="id" name="action_move_to_edge_and_hide"/>
|
<item type="id" name="action_move_to_edge_and_hide"/>
|
||||||
<item type="id" name="action_move_out_edge_and_show"/>
|
<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>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory;
|
|||||||
import com.android.systemui.decor.DecorProviderKt;
|
import com.android.systemui.decor.DecorProviderKt;
|
||||||
import com.android.systemui.decor.OverlayWindow;
|
import com.android.systemui.decor.OverlayWindow;
|
||||||
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
|
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
|
||||||
|
import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
|
||||||
import com.android.systemui.decor.RoundedCornerResDelegate;
|
import com.android.systemui.decor.RoundedCornerResDelegate;
|
||||||
import com.android.systemui.qs.SettingObserver;
|
import com.android.systemui.qs.SettingObserver;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
@@ -137,6 +138,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
|
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
protected DecorProviderFactory mRoundedCornerFactory;
|
||||||
|
private int mProviderRefreshToken = 0;
|
||||||
|
@VisibleForTesting
|
||||||
protected OverlayWindow[] mOverlays = null;
|
protected OverlayWindow[] mOverlays = null;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -282,16 +286,58 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return mDotFactory.getHasProviders();
|
return mDotFactory.getHasProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private List<DecorProvider> getProviders(boolean hasHwLayer) {
|
||||||
|
List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders());
|
||||||
|
if (!hasHwLayer) {
|
||||||
|
decorProviders.addAll(mRoundedCornerFactory.getProviders());
|
||||||
|
}
|
||||||
|
return decorProviders;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDisplayIdToProviderFactories() {
|
||||||
|
mDotFactory.onDisplayUniqueIdChanged(mDisplayUniqueId);
|
||||||
|
mRoundedCornerFactory.onDisplayUniqueIdChanged(mDisplayUniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that newProviders is the same list with decorProviders inside mOverlay.
|
||||||
|
* @param newProviders expected comparing DecorProviders
|
||||||
|
* @return true if same provider list
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean hasSameProviders(@NonNull List<DecorProvider> newProviders) {
|
||||||
|
final ArrayList<Integer> overlayViewIds = new ArrayList<>();
|
||||||
|
if (mOverlays != null) {
|
||||||
|
for (OverlayWindow overlay : mOverlays) {
|
||||||
|
if (overlay == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
overlayViewIds.addAll(overlay.getViewIds());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (overlayViewIds.size() != newProviders.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DecorProvider provider: newProviders) {
|
||||||
|
if (!overlayViewIds.contains(provider.getViewId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void startOnScreenDecorationsThread() {
|
private void startOnScreenDecorationsThread() {
|
||||||
mRotation = mContext.getDisplay().getRotation();
|
mRotation = mContext.getDisplay().getRotation();
|
||||||
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
|
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
|
||||||
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
|
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
|
||||||
mDisplayUniqueId);
|
mDisplayUniqueId);
|
||||||
|
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
|
||||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||||
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
|
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
|
||||||
updateRoundedCornerDrawable();
|
updateHwLayerRoundedCornerDrawable();
|
||||||
updateRoundedCornerRadii();
|
|
||||||
setupDecorations();
|
setupDecorations();
|
||||||
setupCameraListener();
|
setupCameraListener();
|
||||||
|
|
||||||
@@ -343,18 +389,27 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
final String newUniqueId = mContext.getDisplay().getUniqueId();
|
final String newUniqueId = mContext.getDisplay().getUniqueId();
|
||||||
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
|
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
|
||||||
mDisplayUniqueId = newUniqueId;
|
mDisplayUniqueId = newUniqueId;
|
||||||
mRoundedCornerResDelegate.reloadAll(newUniqueId);
|
|
||||||
final DisplayDecorationSupport newScreenDecorationSupport =
|
final DisplayDecorationSupport newScreenDecorationSupport =
|
||||||
mContext.getDisplay().getDisplayDecorationSupport();
|
mContext.getDisplay().getDisplayDecorationSupport();
|
||||||
// When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
|
|
||||||
// screen decoration.
|
updateDisplayIdToProviderFactories();
|
||||||
if (!eq(newScreenDecorationSupport, mHwcScreenDecorationSupport)) {
|
|
||||||
|
// When providers or the value of mSupportHwcScreenDecoration is changed,
|
||||||
|
// re-setup the whole screen decoration.
|
||||||
|
if (!hasSameProviders(getProviders(newScreenDecorationSupport != null))
|
||||||
|
|| !eq(newScreenDecorationSupport, mHwcScreenDecorationSupport)) {
|
||||||
mHwcScreenDecorationSupport = newScreenDecorationSupport;
|
mHwcScreenDecorationSupport = newScreenDecorationSupport;
|
||||||
removeAllOverlays();
|
removeAllOverlays();
|
||||||
setupDecorations();
|
setupDecorations();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateRoundedCornerDrawable();
|
|
||||||
|
if (mScreenDecorHwcLayer != null) {
|
||||||
|
updateHwLayerRoundedCornerDrawable();
|
||||||
|
updateHwLayerRoundedCornerSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOverlayProviderViews();
|
||||||
}
|
}
|
||||||
if (mCutoutViews != null) {
|
if (mCutoutViews != null) {
|
||||||
final int size = mCutoutViews.length;
|
final int size = mCutoutViews.length;
|
||||||
@@ -369,7 +424,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
if (mScreenDecorHwcLayer != null) {
|
if (mScreenDecorHwcLayer != null) {
|
||||||
mScreenDecorHwcLayer.onDisplayChanged(displayId);
|
mScreenDecorHwcLayer.onDisplayChanged(displayId);
|
||||||
}
|
}
|
||||||
updateOrientation();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -396,6 +450,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeRedundantOverlayViews(@NonNull List<DecorProvider> decorProviders) {
|
||||||
|
if (mOverlays == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int[] viewIds = decorProviders.stream().mapToInt(DecorProvider::getViewId).toArray();
|
||||||
|
for (final OverlayWindow overlay : mOverlays) {
|
||||||
|
if (overlay == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
overlay.removeRedundantViews(viewIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void removeOverlayView(@IdRes int id) {
|
private void removeOverlayView(@IdRes int id) {
|
||||||
if (mOverlays == null) {
|
if (mOverlays == null) {
|
||||||
return;
|
return;
|
||||||
@@ -411,9 +478,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupDecorations() {
|
private void setupDecorations() {
|
||||||
List<DecorProvider> decorProviders = mDotFactory.getProviders();
|
if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) {
|
||||||
|
List<DecorProvider> decorProviders = getProviders(mHwcScreenDecorationSupport != null);
|
||||||
|
removeRedundantOverlayViews(decorProviders);
|
||||||
|
|
||||||
if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) {
|
|
||||||
if (mHwcScreenDecorationSupport != null) {
|
if (mHwcScreenDecorationSupport != null) {
|
||||||
createHwcOverlay();
|
createHwcOverlay();
|
||||||
} else {
|
} else {
|
||||||
@@ -427,7 +495,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
Pair<List<DecorProvider>, List<DecorProvider>> pair =
|
Pair<List<DecorProvider>, List<DecorProvider>> pair =
|
||||||
DecorProviderKt.partitionAlignedBound(decorProviders, i);
|
DecorProviderKt.partitionAlignedBound(decorProviders, i);
|
||||||
decorProviders = pair.getSecond();
|
decorProviders = pair.getSecond();
|
||||||
createOverlay(i, cutout, pair.getFirst(), isOnlyPrivacyDotInSwLayer);
|
createOverlay(i, pair.getFirst(), isOnlyPrivacyDotInSwLayer);
|
||||||
} else {
|
} else {
|
||||||
removeOverlay(i);
|
removeOverlay(i);
|
||||||
}
|
}
|
||||||
@@ -560,7 +628,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
|
|
||||||
private void createOverlay(
|
private void createOverlay(
|
||||||
@BoundsPosition int pos,
|
@BoundsPosition int pos,
|
||||||
@Nullable DisplayCutout cutout,
|
|
||||||
@NonNull List<DecorProvider> decorProviders,
|
@NonNull List<DecorProvider> decorProviders,
|
||||||
boolean isOnlyPrivacyDotInSwLayer) {
|
boolean isOnlyPrivacyDotInSwLayer) {
|
||||||
if (mOverlays == null) {
|
if (mOverlays == null) {
|
||||||
@@ -568,14 +635,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mOverlays[pos] != null) {
|
if (mOverlays[pos] != null) {
|
||||||
// When mOverlay[pos] is not null and only privacy dot in sw layer, use privacy dot
|
initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer);
|
||||||
// view's visibility
|
|
||||||
mOverlays[pos].getRootView().setVisibility(
|
|
||||||
getWindowVisibility(mOverlays[pos], isOnlyPrivacyDotInSwLayer));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mOverlays[pos] = overlayForPosition(pos, decorProviders, isOnlyPrivacyDotInSwLayer);
|
mOverlays[pos] = new OverlayWindow(mContext);
|
||||||
|
initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer);
|
||||||
final ViewGroup overlayView = mOverlays[pos].getRootView();
|
final ViewGroup overlayView = mOverlays[pos].getRootView();
|
||||||
overlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
overlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||||
overlayView.setAlpha(0);
|
overlayView.setAlpha(0);
|
||||||
@@ -590,7 +655,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
|
mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
|
||||||
mCutoutViews[pos].setColor(mTintColor);
|
mCutoutViews[pos].setColor(mTintColor);
|
||||||
overlayView.addView(mCutoutViews[pos]);
|
overlayView.addView(mCutoutViews[pos]);
|
||||||
updateView(pos, cutout);
|
mCutoutViews[pos].updateRotation(mRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
|
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
|
||||||
@@ -641,42 +706,24 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow overrides for top/bottom positions
|
* Init OverlayWindow with decorProviders
|
||||||
*/
|
*/
|
||||||
private OverlayWindow overlayForPosition(
|
private void initOverlay(
|
||||||
@BoundsPosition int pos,
|
@NonNull OverlayWindow overlay,
|
||||||
@NonNull List<DecorProvider> decorProviders,
|
@NonNull List<DecorProvider> decorProviders,
|
||||||
boolean isOnlyPrivacyDotInSwLayer) {
|
boolean isOnlyPrivacyDotInSwLayer) {
|
||||||
final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos);
|
if (!overlay.hasSameProviders(decorProviders)) {
|
||||||
decorProviders.forEach(provider -> {
|
decorProviders.forEach(provider -> {
|
||||||
removeOverlayView(provider.getViewId());
|
if (overlay.getView(provider.getViewId()) != null) {
|
||||||
currentOverlay.addDecorProvider(provider, mRotation);
|
return;
|
||||||
});
|
}
|
||||||
// When only privacy dot in mOverlay, set the initial visibility of mOverlays to
|
removeOverlayView(provider.getViewId());
|
||||||
// INVISIBLE and set it to VISIBLE when the privacy dot is showing.
|
overlay.addDecorProvider(provider, mRotation);
|
||||||
if (isOnlyPrivacyDotInSwLayer) {
|
});
|
||||||
currentOverlay.getRootView().setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
return currentOverlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
|
|
||||||
if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
// Use visibility of privacy dot views if only privacy dot in sw layer
|
||||||
|
overlay.getRootView().setVisibility(
|
||||||
|
getWindowVisibility(overlay, isOnlyPrivacyDotInSwLayer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -849,7 +896,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
int oldRotation = mRotation;
|
int oldRotation = mRotation;
|
||||||
mPendingRotationChange = false;
|
mPendingRotationChange = false;
|
||||||
updateOrientation();
|
updateOrientation();
|
||||||
updateRoundedCornerRadii();
|
|
||||||
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
|
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
|
||||||
setupDecorations();
|
setupDecorations();
|
||||||
if (mOverlays != null) {
|
if (mOverlays != null) {
|
||||||
@@ -910,109 +956,32 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mDotViewController.setNewRotation(newRotation);
|
mDotViewController.setNewRotation(newRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPendingRotationChange) {
|
if (!mPendingRotationChange && newRotation != mRotation) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (newRotation != mRotation) {
|
|
||||||
mRotation = newRotation;
|
mRotation = newRotation;
|
||||||
if (mScreenDecorHwcLayer != null) {
|
if (mScreenDecorHwcLayer != null) {
|
||||||
mScreenDecorHwcLayer.pendingRotationChange = false;
|
mScreenDecorHwcLayer.pendingRotationChange = false;
|
||||||
mScreenDecorHwcLayer.updateRotation(mRotation);
|
mScreenDecorHwcLayer.updateRotation(mRotation);
|
||||||
|
updateHwLayerRoundedCornerSize();
|
||||||
|
updateHwLayerRoundedCornerDrawable();
|
||||||
}
|
}
|
||||||
if (mOverlays != null) {
|
updateLayoutParams();
|
||||||
updateLayoutParams();
|
// update cutout view rotation
|
||||||
final DisplayCutout cutout = getCutout();
|
if (mCutoutViews != null) {
|
||||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
|
for (final DisplayCutoutView cutoutView: mCutoutViews) {
|
||||||
if (mOverlays[i] == null) {
|
if (cutoutView == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
updateView(i, cutout);
|
cutoutView.updateRotation(mRotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update all provider views inside overlay
|
||||||
|
updateOverlayProviderViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (shouldShowSwLayerRoundedCorner(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() {
|
private boolean hasRoundedCorners() {
|
||||||
return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
|
return mRoundedCornerFactory.getHasProviders();
|
||||||
|| mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
|
|
||||||
|| mRoundedCornerResDelegate.isMultipleRadius();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
|
private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
|
||||||
@@ -1066,6 +1035,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
context.getResources(), context.getDisplay().getUniqueId());
|
context.getResources(), context.getDisplay().getUniqueId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateOverlayProviderViews() {
|
||||||
|
if (mOverlays == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++mProviderRefreshToken;
|
||||||
|
for (final OverlayWindow overlay: mOverlays) {
|
||||||
|
if (overlay == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateLayoutParams() {
|
private void updateLayoutParams() {
|
||||||
if (mOverlays == null) {
|
if (mOverlays == null) {
|
||||||
return;
|
return;
|
||||||
@@ -1085,63 +1067,33 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
if (mOverlays == null) return;
|
if (mOverlays == null || !SIZE.equals(key)) {
|
||||||
if (SIZE.equals(key)) {
|
return;
|
||||||
boolean hasReloadRoundedCornerRes = false;
|
|
||||||
if (newValue != null) {
|
|
||||||
try {
|
|
||||||
mRoundedCornerResDelegate.updateTuningSizeFactor(
|
|
||||||
Integer.parseInt(newValue));
|
|
||||||
hasReloadRoundedCornerRes = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When onTuningChanged() is not called through updateRoundedCornerRadii(),
|
|
||||||
// we need to reload rounded corner res to prevent incorrect dimen
|
|
||||||
if (!hasReloadRoundedCornerRes) {
|
|
||||||
mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateRoundedCornerSize(
|
|
||||||
mRoundedCornerResDelegate.getTopRoundedSize(),
|
|
||||||
mRoundedCornerResDelegate.getBottomRoundedSize());
|
|
||||||
}
|
}
|
||||||
|
++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;
|
||||||
|
}
|
||||||
|
overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
|
||||||
|
mDisplayUniqueId);
|
||||||
|
}
|
||||||
|
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() {
|
private void updateHwLayerRoundedCornerDrawable() {
|
||||||
if (mScreenDecorHwcLayer == null) {
|
if (mScreenDecorHwcLayer == null) {
|
||||||
return;
|
return;
|
||||||
@@ -1156,25 +1108,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
|
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() {
|
private void updateHwLayerRoundedCornerSize() {
|
||||||
if (mScreenDecorHwcLayer == null) {
|
if (mScreenDecorHwcLayer == null) {
|
||||||
return;
|
return;
|
||||||
@@ -1186,28 +1119,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
|
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
|
@VisibleForTesting
|
||||||
protected void setSize(View view, Size pixelSize) {
|
protected void setSize(View view, Size pixelSize) {
|
||||||
LayoutParams params = view.getLayoutParams();
|
LayoutParams params = view.getLayoutParams();
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.systemui.decor
|
package com.android.systemui.decor
|
||||||
|
import android.content.Context
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -38,9 +38,20 @@ abstract class DecorProvider {
|
|||||||
/** The aligned bounds for the view which is created through inflateView() */
|
/** The aligned bounds for the view which is created through inflateView() */
|
||||||
abstract val alignedBounds: List<Int>
|
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 */
|
/** Inflate view into parent as current rotation */
|
||||||
abstract fun inflateView(
|
abstract fun inflateView(
|
||||||
inflater: LayoutInflater,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int
|
||||||
): View
|
): View
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ package com.android.systemui.decor
|
|||||||
abstract class DecorProviderFactory {
|
abstract class DecorProviderFactory {
|
||||||
abstract val providers: List<DecorProvider>
|
abstract val providers: List<DecorProvider>
|
||||||
abstract val hasProviders: Boolean
|
abstract val hasProviders: Boolean
|
||||||
|
abstract fun onDisplayUniqueIdChanged(displayUniqueId: String?)
|
||||||
}
|
}
|
||||||
@@ -16,31 +16,25 @@
|
|||||||
package com.android.systemui.decor
|
package com.android.systemui.decor
|
||||||
|
|
||||||
import android.annotation.IdRes
|
import android.annotation.IdRes
|
||||||
import android.view.DisplayCutout
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.android.systemui.R
|
import com.android.systemui.RegionInterceptingFrameLayout
|
||||||
import java.util.HashMap
|
|
||||||
|
|
||||||
class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: Int) {
|
class OverlayWindow(private val context: Context) {
|
||||||
|
|
||||||
private val layoutId: Int
|
val rootView = RegionInterceptingFrameLayout(context) as ViewGroup
|
||||||
get() {
|
private val viewProviderMap = mutableMapOf<Int, Pair<View, DecorProvider>>()
|
||||||
return if (pos == DisplayCutout.BOUNDS_POSITION_LEFT ||
|
|
||||||
pos == DisplayCutout.BOUNDS_POSITION_TOP) {
|
|
||||||
R.layout.rounded_corners_top
|
|
||||||
} else {
|
|
||||||
R.layout.rounded_corners_bottom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val rootView = layoutInflater.inflate(layoutId, null) as ViewGroup
|
val viewIds: List<Int>
|
||||||
private val viewProviderMap: MutableMap<Int, Pair<View, DecorProvider>> = HashMap()
|
get() = viewProviderMap.keys.toList()
|
||||||
|
|
||||||
fun addDecorProvider(decorProvider: DecorProvider, @Surface.Rotation rotation: Int) {
|
fun addDecorProvider(
|
||||||
val view = decorProvider.inflateView(layoutInflater, rootView, rotation)
|
decorProvider: DecorProvider,
|
||||||
|
@Surface.Rotation rotation: Int
|
||||||
|
) {
|
||||||
|
val view = decorProvider.inflateView(context, rootView, rotation)
|
||||||
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
|
viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,4 +50,54 @@ class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos:
|
|||||||
viewProviderMap.remove(id)
|
viewProviderMap.remove(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove views which does not been found in expectExistViewIds
|
||||||
|
*/
|
||||||
|
fun removeRedundantViews(expectExistViewIds: IntArray?) {
|
||||||
|
viewIds.forEach {
|
||||||
|
if (expectExistViewIds == null || !(expectExistViewIds.contains(it))) {
|
||||||
|
removeView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that newProviders is the same list with viewProviderMap.
|
||||||
|
*/
|
||||||
|
fun hasSameProviders(newProviders: List<DecorProvider>): Boolean {
|
||||||
|
return (newProviders.size == viewProviderMap.size) &&
|
||||||
|
newProviders.all { getView(it.viewId) != null }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.decor
|
package com.android.systemui.decor
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -38,6 +39,10 @@ class PrivacyDotDecorProviderFactory @Inject constructor(
|
|||||||
override val hasProviders: Boolean
|
override val hasProviders: Boolean
|
||||||
get() = isPrivacyDotEnabled
|
get() = isPrivacyDotEnabled
|
||||||
|
|
||||||
|
override fun onDisplayUniqueIdChanged(displayUniqueId: String?) {
|
||||||
|
// Do nothing for privacy dot
|
||||||
|
}
|
||||||
|
|
||||||
override val providers: List<DecorProvider>
|
override val providers: List<DecorProvider>
|
||||||
get() {
|
get() {
|
||||||
return if (hasProviders) {
|
return if (hasProviders) {
|
||||||
@@ -76,12 +81,21 @@ class PrivacyDotCornerDecorProviderImpl(
|
|||||||
private val layoutId: Int
|
private val layoutId: Int
|
||||||
) : CornerDecorProvider() {
|
) : CornerDecorProvider() {
|
||||||
|
|
||||||
|
override fun onReloadResAndMeasure(
|
||||||
|
view: View,
|
||||||
|
reloadToken: Int,
|
||||||
|
rotation: Int,
|
||||||
|
displayUniqueId: String?
|
||||||
|
) {
|
||||||
|
// Do nothing here because it is handled inside PrivacyDotViewController
|
||||||
|
}
|
||||||
|
|
||||||
override fun inflateView(
|
override fun inflateView(
|
||||||
inflater: LayoutInflater,
|
context: Context,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
@Surface.Rotation rotation: Int
|
@Surface.Rotation rotation: Int
|
||||||
): View {
|
): View {
|
||||||
inflater.inflate(layoutId, parent, true)
|
LayoutInflater.from(context).inflate(layoutId, parent, true)
|
||||||
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
|
return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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 fun onDisplayUniqueIdChanged(displayUniqueId: String?) {
|
||||||
|
roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
}
|
||||||
@@ -35,6 +35,8 @@ class RoundedCornerResDelegate(
|
|||||||
private val density: Float
|
private val density: Float
|
||||||
get() = res.displayMetrics.density
|
get() = res.displayMetrics.density
|
||||||
|
|
||||||
|
private var reloadToken: Int = 0
|
||||||
|
|
||||||
var isMultipleRadius: Boolean = false
|
var isMultipleRadius: Boolean = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
@@ -59,12 +61,26 @@ class RoundedCornerResDelegate(
|
|||||||
reloadMeasures()
|
reloadMeasures()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadAll(newDisplayUniqueId: String?) {
|
private fun reloadAll(newReloadToken: Int) {
|
||||||
displayUniqueId = newDisplayUniqueId
|
if (reloadToken == newReloadToken) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reloadToken = newReloadToken
|
||||||
reloadRes()
|
reloadRes()
|
||||||
reloadMeasures()
|
reloadMeasures()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
|
||||||
|
if (displayUniqueId != newDisplayUniqueId) {
|
||||||
|
displayUniqueId = newDisplayUniqueId
|
||||||
|
newReloadToken ?.let { reloadToken = it }
|
||||||
|
reloadRes()
|
||||||
|
reloadMeasures()
|
||||||
|
} else {
|
||||||
|
newReloadToken?.let { reloadAll(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun reloadRes() {
|
private fun reloadRes() {
|
||||||
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
|
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
|
||||||
isMultipleRadius = getIsMultipleRadius(configIdx)
|
isMultipleRadius = getIsMultipleRadius(configIdx)
|
||||||
@@ -122,7 +138,11 @@ class RoundedCornerResDelegate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTuningSizeFactor(factor: Int) {
|
fun updateTuningSizeFactor(factor: Int?, newReloadToken: Int) {
|
||||||
|
if (reloadToken == newReloadToken) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reloadToken = newReloadToken
|
||||||
reloadMeasures(factor)
|
reloadMeasures(factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,15 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.isA;
|
import static org.mockito.ArgumentMatchers.isA;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
@@ -62,9 +63,11 @@ import android.util.Size;
|
|||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.WindowMetrics;
|
import android.view.WindowMetrics;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
private SecureSettings mSecureSettings;
|
private SecureSettings mSecureSettings;
|
||||||
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
private FakeThreadFactory mThreadFactory;
|
private FakeThreadFactory mThreadFactory;
|
||||||
private ArrayList<DecorProvider> mDecorProviders;
|
private ArrayList<DecorProvider> mPrivacyDecorProviders;
|
||||||
@Mock
|
@Mock
|
||||||
private Display mDisplay;
|
private Display mDisplay;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -216,16 +219,43 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyRoundedCornerViewsVisibility(
|
@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(
|
||||||
@DisplayCutout.BoundsPosition final int overlayId,
|
@DisplayCutout.BoundsPosition final int overlayId,
|
||||||
@View.Visibility final int visibility) {
|
@View.Visibility final boolean isExist) {
|
||||||
final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView();
|
final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView();
|
||||||
final View left = overlay.findViewById(R.id.left);
|
for (int id: getRoundCornerIdsFromOverlayId(overlayId)) {
|
||||||
final View right = overlay.findViewById(R.id.right);
|
final View view = overlay.findViewById(id);
|
||||||
assertNotNull(left);
|
if (isExist) {
|
||||||
assertNotNull(right);
|
assertNotNull(view);
|
||||||
assertThat(left.getVisibility()).isEqualTo(visibility);
|
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
assertThat(right.getVisibility()).isEqualTo(visibility);
|
} else {
|
||||||
|
assertNull(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -388,8 +418,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
mScreenDecorations.mPrivacyDotShowingListener);
|
mScreenDecorations.mPrivacyDotShowingListener);
|
||||||
|
|
||||||
// Rounded corner views shall not exist
|
// Rounded corner views shall not exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||||
|
|
||||||
// Privacy dots shall exist but invisible
|
// Privacy dots shall exist but invisible
|
||||||
verifyDotViewsVisibility(View.INVISIBLE);
|
verifyDotViewsVisibility(View.INVISIBLE);
|
||||||
@@ -417,8 +447,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Privacy dots shall not exist
|
// Privacy dots shall not exist
|
||||||
verifyDotViewsNullable(true);
|
verifyDotViewsNullable(true);
|
||||||
@@ -447,8 +477,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(1)).setShowingListener(null);
|
verify(mDotViewController, times(1)).setShowingListener(null);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Privacy dots shall exist but invisible
|
// Privacy dots shall exist but invisible
|
||||||
verifyDotViewsVisibility(View.INVISIBLE);
|
verifyDotViewsVisibility(View.INVISIBLE);
|
||||||
@@ -488,21 +518,26 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
||||||
.findViewById(R.id.left);
|
.findViewById(R.id.rounded_corner_top_left);
|
||||||
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
|
||||||
.findViewById(R.id.right);
|
.findViewById(R.id.rounded_corner_top_right);
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams();
|
||||||
.setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius));
|
ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams();
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
assertEquals(leftParams.width, testTopRadius);
|
||||||
.setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius));
|
assertEquals(leftParams.height, testTopRadius);
|
||||||
|
assertEquals(rightParams.width, testTopRadius);
|
||||||
|
assertEquals(rightParams.height, testTopRadius);
|
||||||
|
|
||||||
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
||||||
.findViewById(R.id.left);
|
.findViewById(R.id.rounded_corner_bottom_left);
|
||||||
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
|
||||||
.findViewById(R.id.right);
|
.findViewById(R.id.rounded_corner_bottom_right);
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
leftParams = leftRoundedCorner.getLayoutParams();
|
||||||
.setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius));
|
rightParams = rightRoundedCorner.getLayoutParams();
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
assertEquals(leftParams.width, testBottomRadius);
|
||||||
.setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius));
|
assertEquals(leftParams.height, testBottomRadius);
|
||||||
|
assertEquals(rightParams.width, testBottomRadius);
|
||||||
|
assertEquals(rightParams.height, testBottomRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -518,31 +553,27 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
.when(mScreenDecorations).getCutout();
|
.when(mScreenDecorations).getCutout();
|
||||||
|
|
||||||
mScreenDecorations.start();
|
mScreenDecorations.start();
|
||||||
final Size topRadius = new Size(testTopRadius, testTopRadius);
|
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||||
final Size bottomRadius = new Size(testBottomRadius, testBottomRadius);
|
.findViewById(R.id.rounded_corner_top_left);
|
||||||
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
||||||
.findViewById(R.id.left);
|
.findViewById(R.id.rounded_corner_bottom_left);
|
||||||
boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
|
ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams();
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams();
|
||||||
.setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
|
assertEquals(topParams.width, testTopRadius);
|
||||||
|
assertEquals(topParams.height, testTopRadius);
|
||||||
|
assertEquals(bottomParams.width, testBottomRadius);
|
||||||
|
assertEquals(bottomParams.height, testBottomRadius);
|
||||||
|
|
||||||
View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
|
topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||||
.findViewById(R.id.right);
|
.findViewById(R.id.rounded_corner_top_right);
|
||||||
isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right);
|
bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
.findViewById(R.id.rounded_corner_bottom_right);
|
||||||
.setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
|
topParams = topRoundedCorner.getLayoutParams();
|
||||||
|
bottomParams = bottomRoundedCorner.getLayoutParams();
|
||||||
leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
|
assertEquals(topParams.width, testTopRadius);
|
||||||
.findViewById(R.id.left);
|
assertEquals(topParams.height, testTopRadius);
|
||||||
isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left);
|
assertEquals(bottomParams.width, testBottomRadius);
|
||||||
verify(mScreenDecorations, atLeastOnce())
|
assertEquals(bottomParams.height, testBottomRadius);
|
||||||
.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
|
@Test
|
||||||
@@ -562,8 +593,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Privacy dots shall not exist
|
// Privacy dots shall not exist
|
||||||
verifyDotViewsNullable(true);
|
verifyDotViewsNullable(true);
|
||||||
@@ -598,8 +629,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(1)).setShowingListener(null);
|
verify(mDotViewController, times(1)).setShowingListener(null);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Privacy dots shall exist but invisible
|
// Privacy dots shall exist but invisible
|
||||||
verifyDotViewsVisibility(View.INVISIBLE);
|
verifyDotViewsVisibility(View.INVISIBLE);
|
||||||
@@ -660,10 +691,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// Top rounded corner views shall exist because of cutout
|
// Top rounded corner views shall exist because of cutout
|
||||||
// but be gone because of no rounded corner
|
// but be gone because of no rounded corner
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||||
// Bottom rounded corner views shall exist because of privacy dot
|
// Bottom rounded corner views shall exist because of privacy dot
|
||||||
// but be gone because of no rounded corner
|
// but be gone because of no rounded corner
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||||
|
|
||||||
// Privacy dots shall exist but invisible
|
// Privacy dots shall exist but invisible
|
||||||
verifyDotViewsVisibility(View.INVISIBLE);
|
verifyDotViewsVisibility(View.INVISIBLE);
|
||||||
@@ -691,7 +722,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// Left rounded corner views shall exist because of cutout
|
// Left rounded corner views shall exist because of cutout
|
||||||
// but be gone because of no rounded corner
|
// but be gone because of no rounded corner
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_LEFT, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false);
|
||||||
|
|
||||||
// Top privacy dots shall not exist because of no privacy
|
// Top privacy dots shall not exist because of no privacy
|
||||||
verifyDotViewsNullable(true);
|
verifyDotViewsNullable(true);
|
||||||
@@ -745,8 +776,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Top privacy dots shall not exist because of no privacy dot
|
// Top privacy dots shall not exist because of no privacy dot
|
||||||
verifyDotViewsNullable(true);
|
verifyDotViewsNullable(true);
|
||||||
@@ -775,8 +806,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(1)).setShowingListener(null);
|
verify(mDotViewController, times(1)).setShowingListener(null);
|
||||||
|
|
||||||
// Rounded corner views shall exist
|
// Rounded corner views shall exist
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
|
||||||
|
|
||||||
// Top privacy dots shall exist but invisible
|
// Top privacy dots shall exist but invisible
|
||||||
verifyDotViewsVisibility(View.INVISIBLE);
|
verifyDotViewsVisibility(View.INVISIBLE);
|
||||||
@@ -914,7 +945,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(mDotViewController, times(2)).setShowingListener(null);
|
verify(mDotViewController, times(2)).setShowingListener(null);
|
||||||
|
|
||||||
// Verify each privacy dot id appears only once
|
// Verify each privacy dot id appears only once
|
||||||
mDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
|
mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
|
||||||
int findCount = 0;
|
int findCount = 0;
|
||||||
for (OverlayWindow overlay: mScreenDecorations.mOverlays) {
|
for (OverlayWindow overlay: mScreenDecorations.mOverlays) {
|
||||||
if (overlay == null) {
|
if (overlay == null) {
|
||||||
@@ -968,8 +999,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
|
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
|
||||||
// but rounded corners visibility shall be gone because of no rounding.
|
// but rounded corners visibility shall be gone because of no rounding.
|
||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||||
verify(mDotViewController, times(1)).initialize(any(), any(), any(), any());
|
verify(mDotViewController, times(1)).initialize(any(), any(), any(), any());
|
||||||
verify(mDotViewController, times(1)).setShowingListener(
|
verify(mDotViewController, times(1)).setShowingListener(
|
||||||
mScreenDecorations.mPrivacyDotShowingListener);
|
mScreenDecorations.mPrivacyDotShowingListener);
|
||||||
@@ -982,8 +1013,8 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
|
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
|
||||||
// cutout, but rounded corners visibility shall be gone because of no rounding.
|
// cutout, but rounded corners visibility shall be gone because of no rounding.
|
||||||
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
|
||||||
verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
|
verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
|
||||||
verify(mDotViewController, times(2)).initialize(any(), any(), any(), any());
|
verify(mDotViewController, times(2)).initialize(any(), any(), any(), any());
|
||||||
verify(mDotViewController, times(1)).setShowingListener(null);
|
verify(mDotViewController, times(1)).setShowingListener(null);
|
||||||
}
|
}
|
||||||
@@ -1297,6 +1328,48 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
verify(cutoutView, times(1)).onDisplayChanged(1);
|
verify(cutoutView, times(1)).onDisplayChanged(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasSameProvidersWithNullOverlays() {
|
||||||
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
|
0 /* roundedPadding */, false /* multipleRadius */,
|
||||||
|
false /* fillCutout */, false /* privacyDot */);
|
||||||
|
|
||||||
|
mScreenDecorations.start();
|
||||||
|
|
||||||
|
final ArrayList<DecorProvider> newProviders = new ArrayList<>();
|
||||||
|
assertTrue(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotTopLeftDecorProvider);
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotTopRightDecorProvider);
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasSameProvidersWithPrivacyDots() {
|
||||||
|
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
|
||||||
|
0 /* roundedPadding */, false /* multipleRadius */,
|
||||||
|
true /* fillCutout */, true /* privacyDot */);
|
||||||
|
|
||||||
|
mScreenDecorations.start();
|
||||||
|
|
||||||
|
final ArrayList<DecorProvider> newProviders = new ArrayList<>();
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotTopLeftDecorProvider);
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotTopRightDecorProvider);
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotBottomLeftDecorProvider);
|
||||||
|
assertFalse(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
|
||||||
|
newProviders.add(mPrivacyDotBottomRightDecorProvider);
|
||||||
|
assertTrue(mScreenDecorations.hasSameProviders(newProviders));
|
||||||
|
}
|
||||||
|
|
||||||
private void setupResources(int radius, int radiusTop, int radiusBottom, int roundedPadding,
|
private void setupResources(int radius, int radiusTop, int radiusBottom, int roundedPadding,
|
||||||
boolean multipleRadius, boolean fillCutout, boolean privacyDot) {
|
boolean multipleRadius, boolean fillCutout, boolean privacyDot) {
|
||||||
mContext.getOrCreateTestableResources().addOverride(
|
mContext.getOrCreateTestableResources().addOverride(
|
||||||
@@ -1336,14 +1409,14 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
mContext.getOrCreateTestableResources().addOverride(
|
mContext.getOrCreateTestableResources().addOverride(
|
||||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
|
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
|
||||||
|
|
||||||
mDecorProviders = new ArrayList<>();
|
mPrivacyDecorProviders = new ArrayList<>();
|
||||||
if (privacyDot) {
|
if (privacyDot) {
|
||||||
mDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
|
mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
|
||||||
mDecorProviders.add(mPrivacyDotTopRightDecorProvider);
|
mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider);
|
||||||
mDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
|
mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
|
||||||
mDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
|
mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
|
||||||
}
|
}
|
||||||
when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mDecorProviders);
|
when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders);
|
||||||
when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot);
|
when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,25 +19,19 @@ package com.android.systemui.decor
|
|||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.util.mockito.eq
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.Mock
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito
|
|
||||||
import org.mockito.Mockito.anyInt
|
|
||||||
import org.mockito.Mockito.spy
|
import org.mockito.Mockito.spy
|
||||||
|
import org.mockito.Mockito.times
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper(setAsMainLooper = true)
|
@RunWithLooper(setAsMainLooper = true)
|
||||||
@@ -45,62 +39,144 @@ import org.mockito.Mockito.`when` as whenever
|
|||||||
class OverlayWindowTest : SysuiTestCase() {
|
class OverlayWindowTest : SysuiTestCase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TEST_DECOR_VIEW_ID = R.id.privacy_dot_bottom_right_container
|
private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container
|
||||||
private val TEST_DECOR_LAYOUT_ID = R.layout.privacy_dot_bottom_right
|
private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_left_container
|
||||||
|
private val TEST_DECOR_VIEW_ID_3 = R.id.privacy_dot_bottom_right_container
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var overlay: OverlayWindow
|
private lateinit var overlay: OverlayWindow
|
||||||
|
private lateinit var decorProvider1: DecorProvider
|
||||||
@Mock private lateinit var layoutInflater: LayoutInflater
|
private lateinit var decorProvider2: DecorProvider
|
||||||
@Mock private lateinit var decorProvider: DecorProvider
|
private lateinit var decorProvider3: DecorProvider
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
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_LEFT,
|
||||||
|
layoutId = R.layout.privacy_dot_bottom_left))
|
||||||
|
decorProvider3 = spy(PrivacyDotCornerDecorProviderImpl(
|
||||||
|
viewId = TEST_DECOR_VIEW_ID_3,
|
||||||
|
alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
|
||||||
|
alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
|
||||||
|
layoutId = R.layout.privacy_dot_bottom_right))
|
||||||
|
|
||||||
layoutInflater = spy(LayoutInflater.from(mContext))
|
overlay = OverlayWindow(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
|
@Test
|
||||||
fun testAddProvider() {
|
fun testAddProvider() {
|
||||||
@Surface.Rotation val rotation = Surface.ROTATION_270
|
@Surface.Rotation val rotation = Surface.ROTATION_270
|
||||||
overlay.addDecorProvider(decorProvider, rotation)
|
overlay.addDecorProvider(decorProvider1, rotation)
|
||||||
verify(decorProvider, Mockito.times(1)).inflateView(
|
overlay.addDecorProvider(decorProvider2, rotation)
|
||||||
eq(layoutInflater), eq(overlay.rootView), eq(rotation))
|
|
||||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
|
verify(decorProvider1, times(1)).inflateView(
|
||||||
Assert.assertNotNull(viewFoundFromRootView)
|
mContext, overlay.rootView, rotation)
|
||||||
Assert.assertEquals(viewFoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID))
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRemoveView() {
|
fun testRemoveView() {
|
||||||
@Surface.Rotation val rotation = Surface.ROTATION_270
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
||||||
overlay.addDecorProvider(decorProvider, rotation)
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
||||||
overlay.removeView(TEST_DECOR_VIEW_ID)
|
overlay.removeView(TEST_DECOR_VIEW_ID_1)
|
||||||
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
|
|
||||||
|
val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
|
||||||
Assert.assertNull(viewFoundFromRootView)
|
Assert.assertNull(viewFoundFromRootView)
|
||||||
Assert.assertNull(overlay.getView(TEST_DECOR_LAYOUT_ID))
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testRemoveRedundantViewsWithNullParameter() {
|
||||||
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
||||||
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
||||||
|
|
||||||
|
overlay.removeRedundantViews(null)
|
||||||
|
|
||||||
|
Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
|
||||||
|
Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
|
||||||
|
Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2))
|
||||||
|
Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testRemoveRedundantViewsWith2Providers() {
|
||||||
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
|
||||||
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
|
||||||
|
|
||||||
|
overlay.removeRedundantViews(IntArray(2).apply {
|
||||||
|
this[0] = TEST_DECOR_VIEW_ID_3
|
||||||
|
this[1] = TEST_DECOR_VIEW_ID_1
|
||||||
|
})
|
||||||
|
|
||||||
|
Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
|
||||||
|
Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1))
|
||||||
|
Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2))
|
||||||
|
Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasSameProviders() {
|
||||||
|
Assert.assertTrue(overlay.hasSameProviders(emptyList()))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
|
|
||||||
|
overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
||||||
|
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1)))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
|
|
||||||
|
overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(emptyList()))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1)))
|
||||||
|
Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2)))
|
||||||
|
Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,6 @@ package com.android.systemui.decor
|
|||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
|
||||||
import android.view.DisplayCutout
|
import android.view.DisplayCutout
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
@@ -32,7 +31,6 @@ import org.mockito.Mockito.spy
|
|||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper(setAsMainLooper = true)
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() {
|
class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() {
|
||||||
private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory
|
private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
@Test
|
||||||
fun testReloadAllAndDefaultRadius() {
|
fun testUpdateDisplayUniqueId() {
|
||||||
mContext.orCreateTestableResources.addOverrides(
|
mContext.orCreateTestableResources.addOverrides(
|
||||||
mockTypeArray = mockTypedArray,
|
mockTypeArray = mockTypedArray,
|
||||||
radius = 3,
|
radius = 3,
|
||||||
@@ -65,7 +65,34 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
|
|||||||
radiusTop = 6,
|
radiusTop = 6,
|
||||||
radiusBottom = 0)
|
radiusBottom = 0)
|
||||||
|
|
||||||
roundedCornerResDelegate.reloadAll("test")
|
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)
|
||||||
|
|
||||||
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
|
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
|
||||||
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
|
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
|
||||||
@@ -82,11 +109,21 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
|
|||||||
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
|
roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
|
||||||
|
|
||||||
val factor = 5
|
val factor = 5
|
||||||
roundedCornerResDelegate.updateTuningSizeFactor(factor)
|
roundedCornerResDelegate.updateTuningSizeFactor(factor, 1)
|
||||||
val length = (factor * mContext.resources.displayMetrics.density).toInt()
|
val length = (factor * mContext.resources.displayMetrics.density).toInt()
|
||||||
|
|
||||||
assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
|
assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
|
||||||
assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize)
|
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
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user