Merge "Hook up the sysui backend for status bar content rects" into sc-dev

This commit is contained in:
Evan Laird
2021-07-22 17:34:12 +00:00
committed by Android (Google) Code Review
11 changed files with 289 additions and 88 deletions

View File

@@ -100,6 +100,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -362,6 +363,7 @@ public class Dependency {
@Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy; @Inject Lazy<EdgeBackGestureHandler.Factory> mEdgeBackGestureHandlerFactoryLazy;
@Inject Lazy<UiEventLogger> mUiEventLogger; @Inject Lazy<UiEventLogger> mUiEventLogger;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy; @Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
@Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
@Inject @Inject
public Dependency() { public Dependency() {
@@ -578,6 +580,7 @@ public class Dependency {
mEdgeBackGestureHandlerFactoryLazy::get); mEdgeBackGestureHandlerFactoryLazy::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get); mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get); mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
Dependency.setInstance(this); Dependency.setInstance(this);
} }

View File

@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.events
import android.animation.Animator import android.animation.Animator
import android.annotation.UiThread import android.annotation.UiThread
import android.graphics.Point
import android.graphics.Rect
import android.util.Log import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
@@ -31,9 +33,16 @@ import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState.SHADE import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.leak.RotationUtils
import com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE
import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
import com.android.systemui.util.leak.RotationUtils.Rotation
import java.lang.IllegalStateException import java.lang.IllegalStateException
import java.util.concurrent.Executor import java.util.concurrent.Executor
@@ -58,7 +67,8 @@ import javax.inject.Inject
class PrivacyDotViewController @Inject constructor( class PrivacyDotViewController @Inject constructor(
@Main private val mainExecutor: Executor, @Main private val mainExecutor: Executor,
private val stateController: StatusBarStateController, private val stateController: StatusBarStateController,
private val locationPublisher: StatusBarLocationPublisher, private val configurationController: ConfigurationController,
private val contentInsetsProvider: StatusBarContentInsetsProvider,
private val animationScheduler: SystemStatusAnimationScheduler private val animationScheduler: SystemStatusAnimationScheduler
) { ) {
private var sbHeightPortrait = 0 private var sbHeightPortrait = 0
@@ -84,18 +94,27 @@ class PrivacyDotViewController @Inject constructor(
// Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread // Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread
private var uiExecutor: DelayableExecutor? = null private var uiExecutor: DelayableExecutor? = null
private val marginListener: StatusBarMarginUpdatedListener =
object : StatusBarMarginUpdatedListener {
override fun onStatusBarMarginUpdated(marginLeft: Int, marginRight: Int) {
setStatusBarMargins(marginLeft, marginRight)
}
}
private val views: Sequence<View> private val views: Sequence<View>
get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl) get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
init { init {
locationPublisher.addCallback(marginListener) contentInsetsProvider.addCallback(object : StatusBarContentInsetsChangedListener {
override fun onStatusBarContentInsetsChanged() {
dlog("onStatusBarContentInsetsChanged: ")
setNewLayoutRects()
}
})
configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
override fun onLayoutDirectionChanged(isRtl: Boolean) {
synchronized(this) {
val corner = selectDesignatedCorner(nextViewState.rotation, isRtl)
nextViewState = nextViewState.copy(
layoutRtl = isRtl,
designatedCorner = corner
)
}
}
})
stateController.addCallback(object : StatusBarStateController.StateListener { stateController.addCallback(object : StatusBarStateController.StateListener {
override fun onExpandedChanged(isExpanded: Boolean) { override fun onExpandedChanged(isExpanded: Boolean) {
@@ -123,16 +142,19 @@ class PrivacyDotViewController @Inject constructor(
fun setNewRotation(rot: Int) { fun setNewRotation(rot: Int) {
dlog("updateRotation: $rot") dlog("updateRotation: $rot")
val isRtl: Boolean
synchronized(lock) { synchronized(lock) {
if (rot == nextViewState.rotation) { if (rot == nextViewState.rotation) {
return return
} }
isRtl = nextViewState.layoutRtl
} }
// If we rotated, hide all dotes until the next state resolves // If we rotated, hide all dotes until the next state resolves
setCornerVisibilities(View.INVISIBLE) setCornerVisibilities(View.INVISIBLE)
val newCorner = selectDesignatedCorner(rot) val newCorner = selectDesignatedCorner(rot, isRtl)
val index = newCorner.cornerIndex() val index = newCorner.cornerIndex()
val h = when (rot) { val h = when (rot) {
@@ -222,15 +244,77 @@ class PrivacyDotViewController @Inject constructor(
} }
} }
@UiThread
private fun setCornerSizes(state: ViewState) {
// StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
// in every rotation. The only thing we need to check is rtl
val rtl = state.layoutRtl
val size = Point()
tl.context.display.getRealSize(size)
val currentRotation = RotationUtils.getExactRotation(tl.context)
val displayWidth: Int
val displayHeight: Int
if (currentRotation == ROTATION_LANDSCAPE || currentRotation == ROTATION_SEASCAPE) {
displayWidth = size.y
displayHeight = size.x
} else {
displayWidth = size.x
displayHeight = size.y
}
var rot = activeRotationForCorner(tl, rtl)
var contentInsets = state.contentRectForRotation(rot)
(tl.layoutParams as FrameLayout.LayoutParams).apply {
height = contentInsets.height()
if (rtl) {
width = contentInsets.left
} else {
width = displayHeight - contentInsets.right
}
}
rot = activeRotationForCorner(tr, rtl)
contentInsets = state.contentRectForRotation(rot)
(tr.layoutParams as FrameLayout.LayoutParams).apply {
height = contentInsets.height()
if (rtl) {
width = contentInsets.left
} else {
width = displayWidth - contentInsets.right
}
}
rot = activeRotationForCorner(br, rtl)
contentInsets = state.contentRectForRotation(rot)
(br.layoutParams as FrameLayout.LayoutParams).apply {
height = contentInsets.height()
if (rtl) {
width = contentInsets.left
} else {
width = displayHeight - contentInsets.right
}
}
rot = activeRotationForCorner(bl, rtl)
contentInsets = state.contentRectForRotation(rot)
(bl.layoutParams as FrameLayout.LayoutParams).apply {
height = contentInsets.height()
if (rtl) {
width = contentInsets.left
} else {
width = displayWidth - contentInsets.right
}
}
}
// Designated view will be the one at statusbar's view.END // Designated view will be the one at statusbar's view.END
@UiThread @UiThread
private fun selectDesignatedCorner(r: Int): View? { private fun selectDesignatedCorner(r: Int, isRtl: Boolean): View? {
if (!this::tl.isInitialized) { if (!this::tl.isInitialized) {
return null return null
} }
val isRtl = tl.isLayoutRtl
return when (r) { return when (r) {
0 -> if (isRtl) tl else tr 0 -> if (isRtl) tl else tr
1 -> if (isRtl) tr else br 1 -> if (isRtl) tr else br
@@ -282,6 +366,17 @@ class PrivacyDotViewController @Inject constructor(
return modded return modded
} }
@Rotation
private fun activeRotationForCorner(corner: View, rtl: Boolean): Int {
// Each corner will only be visible in a single rotation, based on rtl
return when (corner) {
tr -> if (rtl) ROTATION_LANDSCAPE else ROTATION_NONE
tl -> if (rtl) ROTATION_NONE else ROTATION_SEASCAPE
br -> if (rtl) ROTATION_UPSIDE_DOWN else ROTATION_LANDSCAPE
else /* bl */ -> if (rtl) ROTATION_SEASCAPE else ROTATION_UPSIDE_DOWN
}
}
private fun widthForCorner(corner: Int, left: Int, right: Int): Int { private fun widthForCorner(corner: Int, left: Int, right: Int): Int {
return when (corner) { return when (corner) {
TOP_LEFT, BOTTOM_LEFT -> left TOP_LEFT, BOTTOM_LEFT -> left
@@ -303,15 +398,32 @@ class PrivacyDotViewController @Inject constructor(
bl = bottomLeft bl = bottomLeft
br = bottomRight br = bottomRight
val dc = selectDesignatedCorner(0) val rtl = configurationController.isLayoutRtl
val dc = selectDesignatedCorner(0, rtl)
val index = dc.cornerIndex() val index = dc.cornerIndex()
mainExecutor.execute { mainExecutor.execute {
animationScheduler.addCallback(systemStatusAnimationCallback) animationScheduler.addCallback(systemStatusAnimationCallback)
} }
val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
val bottom = contentInsetsProvider
.getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
synchronized(lock) { synchronized(lock) {
nextViewState = nextViewState.copy(designatedCorner = dc, cornerIndex = index) nextViewState = nextViewState.copy(
viewInitialized = true,
designatedCorner = dc,
cornerIndex = index,
seascapeRect = left,
portraitRect = top,
landscapeRect = right,
upsideDownRect = bottom,
layoutRtl = rtl
)
} }
} }
@@ -324,19 +436,6 @@ class PrivacyDotViewController @Inject constructor(
sbHeightLandscape = landscape sbHeightLandscape = landscape
} }
/**
* The dot view containers will fill the margin in order to position the dots correctly
*
* @param left the space between the status bar contents and the left side of the screen
* @param right space between the status bar contents and the right side of the screen
*/
private fun setStatusBarMargins(left: Int, right: Int) {
dlog("setStatusBarMargins l=$left r=$right")
synchronized(lock) {
nextViewState = nextViewState.copy(marginLeft = left, marginRight = right)
}
}
private fun updateStatusBarState() { private fun updateStatusBarState() {
synchronized(lock) { synchronized(lock) {
nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs()) nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs())
@@ -377,6 +476,11 @@ class PrivacyDotViewController @Inject constructor(
@UiThread @UiThread
private fun resolveState(state: ViewState) { private fun resolveState(state: ViewState) {
dlog("resolveState $state") dlog("resolveState $state")
if (!state.viewInitialized) {
dlog("resolveState: view is not initialized. skipping.")
return
}
if (state == currentViewState) { if (state == currentViewState) {
dlog("resolveState: skipping") dlog("resolveState: skipping")
return return
@@ -387,23 +491,15 @@ class PrivacyDotViewController @Inject constructor(
updateRotations(state.rotation) updateRotations(state.rotation)
} }
if (state.height != currentViewState.height) { if (state.needsLayout(currentViewState)) {
updateHeights(state.rotation) setCornerSizes(state)
} views.forEach { it.requestLayout() }
if (state.marginLeft != currentViewState.marginLeft ||
state.marginRight != currentViewState.marginRight) {
updateCornerSizes(state.marginLeft, state.marginRight, state.rotation)
} }
if (state.designatedCorner != currentViewState.designatedCorner) { if (state.designatedCorner != currentViewState.designatedCorner) {
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot()) updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
} }
if (state.needsLayout(currentViewState)) {
views.forEach { it.requestLayout() }
}
val shouldShow = state.shouldShowDot() val shouldShow = state.shouldShowDot()
if (shouldShow != currentViewState.shouldShowDot()) { if (shouldShow != currentViewState.shouldShowDot()) {
if (shouldShow && state.designatedCorner != null) { if (shouldShow && state.designatedCorner != null) {
@@ -441,6 +537,30 @@ class PrivacyDotViewController @Inject constructor(
} }
return -1 return -1
} }
// Returns [left, top, right, bottom] aka [seascape, none, landscape, upside-down]
private fun getLayoutRects(): List<Rect> {
val left = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_SEASCAPE)
val top = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_NONE)
val right = contentInsetsProvider.getStatusBarContentInsetsForRotation(ROTATION_LANDSCAPE)
val bottom = contentInsetsProvider
.getStatusBarContentInsetsForRotation(ROTATION_UPSIDE_DOWN)
return listOf(left, top, right, bottom)
}
private fun setNewLayoutRects() {
val rects = getLayoutRects()
synchronized(lock) {
nextViewState = nextViewState.copy(
seascapeRect = rects[0],
portraitRect = rects[1],
landscapeRect = rects[2],
upsideDownRect = rects[3]
)
}
}
} }
private fun dlog(s: String) { private fun dlog(s: String) {
@@ -461,7 +581,7 @@ const val BOTTOM_RIGHT = 2
const val BOTTOM_LEFT = 3 const val BOTTOM_LEFT = 3
private const val DURATION = 160L private const val DURATION = 160L
private const val TAG = "PrivacyDotViewController" private const val TAG = "PrivacyDotViewController"
private const val DEBUG = true private const val DEBUG = false
private const val DEBUG_VERBOSE = false private const val DEBUG_VERBOSE = false
private fun Int.toGravity(): Int { private fun Int.toGravity(): Int {
@@ -485,14 +605,20 @@ private fun Int.innerGravity(): Int {
} }
private data class ViewState( private data class ViewState(
val viewInitialized: Boolean = false,
val systemPrivacyEventIsActive: Boolean = false, val systemPrivacyEventIsActive: Boolean = false,
val shadeExpanded: Boolean = false, val shadeExpanded: Boolean = false,
val qsExpanded: Boolean = false, val qsExpanded: Boolean = false,
val portraitRect: Rect? = null,
val landscapeRect: Rect? = null,
val upsideDownRect: Rect? = null,
val seascapeRect: Rect? = null,
val layoutRtl: Boolean = false,
val rotation: Int = 0, val rotation: Int = 0,
val height: Int = 0, val height: Int = 0,
val marginLeft: Int = 0,
val marginRight: Int = 0,
val cornerIndex: Int = -1, val cornerIndex: Int = -1,
val designatedCorner: View? = null val designatedCorner: View? = null
) { ) {
@@ -502,7 +628,20 @@ private data class ViewState(
fun needsLayout(other: ViewState): Boolean { fun needsLayout(other: ViewState): Boolean {
return rotation != other.rotation || return rotation != other.rotation ||
marginRight != other.marginRight || layoutRtl != other.layoutRtl ||
height != other.height portraitRect != other.portraitRect ||
landscapeRect != other.landscapeRect ||
upsideDownRect != other.upsideDownRect ||
seascapeRect != other.seascapeRect
}
fun contentRectForRotation(@Rotation rot: Int): Rect {
return when (rot) {
ROTATION_NONE -> portraitRect!!
ROTATION_LANDSCAPE -> landscapeRect!!
ROTATION_UPSIDE_DOWN -> upsideDownRect!!
ROTATION_SEASCAPE -> seascapeRect!!
else -> throw IllegalArgumentException("not a rotation ($rot)")
}
} }
} }

View File

@@ -37,7 +37,6 @@ import android.view.ViewGroup;
import android.view.ViewStub; import android.view.ViewStub;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import com.android.systemui.Dependency;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.animation.Interpolators; import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -76,9 +75,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
public static final int FADE_IN_DURATION = 320; public static final int FADE_IN_DURATION = 320;
public static final int FADE_IN_DELAY = 50; public static final int FADE_IN_DELAY = 50;
private PhoneStatusBarView mStatusBar; private PhoneStatusBarView mStatusBar;
private StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private NetworkController mNetworkController; private final NetworkController mNetworkController;
private LinearLayout mSystemIconArea; private LinearLayout mSystemIconArea;
private View mClockView; private View mClockView;
private View mOngoingCallChip; private View mOngoingCallChip;
@@ -86,15 +85,16 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private View mCenteredIconArea; private View mCenteredIconArea;
private int mDisabled1; private int mDisabled1;
private int mDisabled2; private int mDisabled2;
private StatusBar mStatusBarComponent; private final StatusBar mStatusBarComponent;
private DarkIconManager mDarkIconManager; private DarkIconManager mDarkIconManager;
private View mOperatorNameFrame; private View mOperatorNameFrame;
private CommandQueue mCommandQueue; private final CommandQueue mCommandQueue;
private OngoingCallController mOngoingCallController; private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler; private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mLocationPublisher; private final StatusBarLocationPublisher mLocationPublisher;
private NotificationIconAreaController mNotificationIconAreaController;
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final NotificationIconAreaController mNotificationIconAreaController;
private final StatusBarIconController mStatusBarIconController;
private List<String> mBlockedIcons = new ArrayList<>(); private List<String> mBlockedIcons = new ArrayList<>();
@@ -118,23 +118,25 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
SystemStatusAnimationScheduler animationScheduler, SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher, StatusBarLocationPublisher locationPublisher,
NotificationIconAreaController notificationIconAreaController, NotificationIconAreaController notificationIconAreaController,
FeatureFlags featureFlags FeatureFlags featureFlags,
StatusBarIconController statusBarIconController,
KeyguardStateController keyguardStateController,
NetworkController networkController,
StatusBarStateController statusBarStateController,
StatusBar statusBarComponent,
CommandQueue commandQueue
) { ) {
mOngoingCallController = ongoingCallController; mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler; mAnimationScheduler = animationScheduler;
mLocationPublisher = locationPublisher; mLocationPublisher = locationPublisher;
mNotificationIconAreaController = notificationIconAreaController; mNotificationIconAreaController = notificationIconAreaController;
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
} mStatusBarIconController = statusBarIconController;
mKeyguardStateController = keyguardStateController;
@Override mNetworkController = networkController;
public void onCreate(@Nullable Bundle savedInstanceState) { mStatusBarStateController = statusBarStateController;
super.onCreate(savedInstanceState); mStatusBarComponent = statusBarComponent;
mKeyguardStateController = Dependency.get(KeyguardStateController.class); mCommandQueue = commandQueue;
mNetworkController = Dependency.get(NetworkController.class);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mStatusBarComponent = Dependency.get(StatusBar.class);
mCommandQueue = Dependency.get(CommandQueue.class);
} }
@Override @Override
@@ -160,7 +162,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock)); mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength)); mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
mDarkIconManager.setBlockList(mBlockedIcons); mDarkIconManager.setBlockList(mBlockedIcons);
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager); mStatusBarIconController.addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area); mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
mClockView = mStatusBar.findViewById(R.id.clock); mClockView = mStatusBar.findViewById(R.id.clock);
mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip); mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
@@ -199,7 +201,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager); mStatusBarIconController.removeIconGroup(mDarkIconManager);
if (mNetworkController.hasEmergencyCryptKeeperText()) { if (mNetworkController.hasEmergencyCryptKeeperText()) {
mNetworkController.removeCallback(mSignalCallback); mNetworkController.removeCallback(mSignalCallback);
} }

View File

@@ -18,6 +18,7 @@ import android.content.Context
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Configuration import android.content.res.Configuration
import android.os.LocaleList import android.os.LocaleList
import android.view.View.LAYOUT_DIRECTION_RTL
import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController
import java.util.ArrayList import java.util.ArrayList
@@ -33,6 +34,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
private var uiMode: Int = 0 private var uiMode: Int = 0
private var localeList: LocaleList? = null private var localeList: LocaleList? = null
private val context: Context private val context: Context
private var layoutDirection: Int
init { init {
val currentConfig = context.resources.configuration val currentConfig = context.resources.configuration
@@ -44,6 +46,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
Configuration.UI_MODE_TYPE_CAR Configuration.UI_MODE_TYPE_CAR
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
localeList = currentConfig.locales localeList = currentConfig.locales
layoutDirection = currentConfig.layoutDirection
} }
override fun notifyThemeChanged() { override fun notifyThemeChanged() {
@@ -101,6 +104,13 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
} }
} }
if (layoutDirection != newConfig.layoutDirection) {
layoutDirection = newConfig.layoutDirection
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onLayoutDirectionChanged(layoutDirection == LAYOUT_DIRECTION_RTL)
}
}
if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) { if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
listeners.filterForEach({ this.listeners.contains(it) }) { listeners.filterForEach({ this.listeners.contains(it) }) {
it.onOverlayChanged() it.onOverlayChanged()
@@ -116,6 +126,10 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
override fun removeCallback(listener: ConfigurationController.ConfigurationListener) { override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
listeners.remove(listener) listeners.remove(listener)
} }
override fun isLayoutRtl(): Boolean {
return layoutDirection == LAYOUT_DIRECTION_RTL
}
} }
// This could be done with a Collection.filter and Collection.forEach, but Collection.filter // This could be done with a Collection.filter and Collection.forEach, but Collection.filter

View File

@@ -23,6 +23,7 @@ import static java.lang.Float.isNaN;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.EventLog; import android.util.EventLog;
@@ -52,6 +53,7 @@ public class PhoneStatusBarView extends PanelBar {
private static final boolean DEBUG = StatusBar.DEBUG; private static final boolean DEBUG = StatusBar.DEBUG;
private static final boolean DEBUG_GESTURES = false; private static final boolean DEBUG_GESTURES = false;
private final CommandQueue mCommandQueue; private final CommandQueue mCommandQueue;
private final StatusBarContentInsetsProvider mContentInsetsProvider;
StatusBar mBar; StatusBar mBar;
@@ -85,11 +87,10 @@ public class PhoneStatusBarView extends PanelBar {
private int mCutoutSideNudge = 0; private int mCutoutSideNudge = 0;
private boolean mHeadsUpVisible; private boolean mHeadsUpVisible;
private int mRoundedCornerPadding = 0;
public PhoneStatusBarView(Context context, AttributeSet attrs) { public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
mCommandQueue = Dependency.get(CommandQueue.class); mCommandQueue = Dependency.get(CommandQueue.class);
mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
} }
public void setBar(StatusBar bar) { public void setBar(StatusBar bar) {
@@ -305,8 +306,6 @@ public class PhoneStatusBarView extends PanelBar {
public void updateResources() { public void updateResources() {
mCutoutSideNudge = getResources().getDimensionPixelSize( mCutoutSideNudge = getResources().getDimensionPixelSize(
R.dimen.display_cutout_margin_consumption); R.dimen.display_cutout_margin_consumption);
mRoundedCornerPadding = getResources().getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
updateStatusBarHeight(); updateStatusBarHeight();
} }
@@ -341,8 +340,7 @@ public class PhoneStatusBarView extends PanelBar {
private void updateLayoutForCutout() { private void updateLayoutForCutout() {
updateStatusBarHeight(); updateStatusBarHeight();
updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay())); updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()));
updateSafeInsets(StatusBarWindowView.statusBarCornerCutoutMargins(mDisplayCutout, updateSafeInsets();
getDisplay(), mRotationOrientation, mStatusBarHeight));
} }
private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) { private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) {
@@ -370,15 +368,18 @@ public class PhoneStatusBarView extends PanelBar {
lp.height = bounds.height(); lp.height = bounds.height();
} }
private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) { private void updateSafeInsets() {
// Depending on our rotation, we may have to work around a cutout in the middle of the view, Rect contentRect = mContentInsetsProvider
// or letterboxing from the right or left sides. .getStatusBarContentInsetsForRotation(RotationUtils.getExactRotation(getContext()));
Pair<Integer, Integer> padding = Point size = new Point();
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner( getDisplay().getRealSize(size);
mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom()); setPadding(
contentRect.left,
getPaddingTop(),
size.x - contentRect.right,
getPaddingBottom());
} }
public void setHeadsUpVisible(boolean headsUpVisible) { public void setHeadsUpVisible(boolean headsUpVisible) {

View File

@@ -441,6 +441,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final OngoingCallController mOngoingCallController; private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler; private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mStatusBarLocationPublisher; private final StatusBarLocationPublisher mStatusBarLocationPublisher;
private final StatusBarIconController mStatusBarIconController;
// expanded notifications // expanded notifications
// the sliding/resizing panel within the notification window // the sliding/resizing panel within the notification window
@@ -803,6 +804,7 @@ public class StatusBar extends SystemUI implements DemoMode,
OngoingCallController ongoingCallController, OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler, SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher, StatusBarLocationPublisher locationPublisher,
StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController lockscreenShadeTransitionController, LockscreenShadeTransitionController lockscreenShadeTransitionController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController, KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -889,6 +891,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mOngoingCallController = ongoingCallController; mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler; mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher; mStatusBarLocationPublisher = locationPublisher;
mStatusBarIconController = statusBarIconController;
mFeatureFlags = featureFlags; mFeatureFlags = featureFlags;
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -1190,7 +1193,14 @@ public class StatusBar extends SystemUI implements DemoMode,
mAnimationScheduler, mAnimationScheduler,
mStatusBarLocationPublisher, mStatusBarLocationPublisher,
mNotificationIconAreaController, mNotificationIconAreaController,
mFeatureFlags), mFeatureFlags,
mStatusBarIconController,
mKeyguardStateController,
mNetworkController,
mStatusBarStateController,
this,
mCommandQueue
),
CollapsedStatusBarFragment.TAG) CollapsedStatusBarFragment.TAG)
.commit(); .commit();

View File

@@ -89,6 +89,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter; import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
@@ -216,6 +217,7 @@ public interface StatusBarPhoneModule {
OngoingCallController ongoingCallController, OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler, SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher, StatusBarLocationPublisher locationPublisher,
StatusBarIconController statusBarIconController,
LockscreenShadeTransitionController transitionController, LockscreenShadeTransitionController transitionController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
KeyguardUnlockAnimationController keyguardUnlockAnimationController, KeyguardUnlockAnimationController keyguardUnlockAnimationController,
@@ -305,6 +307,7 @@ public interface StatusBarPhoneModule {
ongoingCallController, ongoingCallController,
animationScheduler, animationScheduler,
locationPublisher, locationPublisher,
statusBarIconController,
transitionController, transitionController,
featureFlags, featureFlags,
keyguardUnlockAnimationController, keyguardUnlockAnimationController,

View File

@@ -30,6 +30,9 @@ public interface ConfigurationController extends CallbackController<Configuratio
/** Alert controller of a change in between light and dark themes. */ /** Alert controller of a change in between light and dark themes. */
void notifyThemeChanged(); void notifyThemeChanged();
/** Query the current configuration's layout direction */
boolean isLayoutRtl();
interface ConfigurationListener { interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {} default void onConfigChanged(Configuration newConfig) {}
default void onDensityOrFontScaleChanged() {} default void onDensityOrFontScaleChanged() {}
@@ -38,5 +41,6 @@ public interface ConfigurationController extends CallbackController<Configuratio
default void onUiModeChanged() {} default void onUiModeChanged() {}
default void onThemeChanged() {} default void onThemeChanged() {}
default void onLocaleListChanged() {} default void onLocaleListChanged() {}
default void onLayoutDirectionChanged(boolean isLayoutRtl) {}
} }
} }

View File

@@ -39,10 +39,14 @@ import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
@@ -54,10 +58,17 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
private NotificationIconAreaController mMockNotificationAreaController; private NotificationIconAreaController mMockNotificationAreaController;
private View mNotificationAreaInner; private View mNotificationAreaInner;
private StatusBarStateController mStatusBarStateController;
private OngoingCallController mOngoingCallController; private OngoingCallController mOngoingCallController;
private SystemStatusAnimationScheduler mAnimationScheduler; private SystemStatusAnimationScheduler mAnimationScheduler;
private StatusBarLocationPublisher mLocationPublisher; private StatusBarLocationPublisher mLocationPublisher;
// Set in instantiate()
private StatusBarIconController mStatusBarIconController;
private NetworkController mNetworkController;
private StatusBarStateController mStatusBarStateController;
private KeyguardStateController mKeyguardStateController;
private final StatusBar mStatusBar = mock(StatusBar.class);
private final CommandQueue mCommandQueue = mock(CommandQueue.class);
public CollapsedStatusBarFragmentTest() { public CollapsedStatusBarFragmentTest() {
super(CollapsedStatusBarFragment.class); super(CollapsedStatusBarFragment.class);
@@ -65,12 +76,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
@Before @Before
public void setup() { public void setup() {
StatusBar statusBar = mock(StatusBar.class);
mDependency.injectTestDependency(StatusBar.class, statusBar);
mStatusBarStateController = mDependency
.injectMockDependency(StatusBarStateController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
when(statusBar.getPanelController()).thenReturn( when(mStatusBar.getPanelController()).thenReturn(
mock(NotificationPanelViewController.class)); mock(NotificationPanelViewController.class));
} }
@@ -202,6 +209,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility()); mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
} }
@Ignore("b/192618546")
@Test @Test
public void testOnDozingChanged() throws Exception { public void testOnDozingChanged() throws Exception {
mFragments.dispatchResume(); mFragments.dispatchResume();
@@ -225,13 +233,23 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mOngoingCallController = mock(OngoingCallController.class); mOngoingCallController = mock(OngoingCallController.class);
mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
mLocationPublisher = mock(StatusBarLocationPublisher.class); mLocationPublisher = mock(StatusBarLocationPublisher.class);
mStatusBarIconController = mock(StatusBarIconController.class);
mNetworkController = mock(NetworkController.class);
mStatusBarStateController = mock(StatusBarStateController.class);
mKeyguardStateController = mock(KeyguardStateController.class);
setUpNotificationIconAreaController(); setUpNotificationIconAreaController();
return new CollapsedStatusBarFragment( return new CollapsedStatusBarFragment(
mOngoingCallController, mOngoingCallController,
mAnimationScheduler, mAnimationScheduler,
mLocationPublisher, mLocationPublisher,
mMockNotificationAreaController, mMockNotificationAreaController,
mock(FeatureFlags.class)); mock(FeatureFlags.class),
mStatusBarIconController,
mKeyguardStateController,
mNetworkController,
mStatusBarStateController,
mStatusBar,
mCommandQueue);
} }
private void setUpNotificationIconAreaController() { private void setUpNotificationIconAreaController() {

View File

@@ -269,6 +269,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private OngoingCallController mOngoingCallController; @Mock private OngoingCallController mOngoingCallController;
@Mock private SystemStatusAnimationScheduler mAnimationScheduler; @Mock private SystemStatusAnimationScheduler mAnimationScheduler;
@Mock private StatusBarLocationPublisher mLocationPublisher; @Mock private StatusBarLocationPublisher mLocationPublisher;
@Mock private StatusBarIconController mIconController;
@Mock private LockscreenShadeTransitionController mLockscreenTransitionController; @Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
@Mock private FeatureFlags mFeatureFlags; @Mock private FeatureFlags mFeatureFlags;
@Mock private IWallpaperManager mWallpaperManager; @Mock private IWallpaperManager mWallpaperManager;
@@ -442,6 +443,7 @@ public class StatusBarTest extends SysuiTestCase {
mOngoingCallController, mOngoingCallController,
mAnimationScheduler, mAnimationScheduler,
mLocationPublisher, mLocationPublisher,
mIconController,
mLockscreenTransitionController, mLockscreenTransitionController,
mFeatureFlags, mFeatureFlags,
mKeyguardUnlockAnimationController, mKeyguardUnlockAnimationController,

View File

@@ -33,4 +33,9 @@ public class FakeConfigurationController
@Override @Override
public void notifyThemeChanged() { public void notifyThemeChanged() {
} }
@Override
public boolean isLayoutRtl() {
return false;
}
} }