Hook up the sysui backend for status bar content rects
StatusBarContentInsetsProvider provides the sysui backend for the windowmanager api to communicate the location of the privacy indicators to apps. This CL hooks up that backend to the dot view controller and the PhoneStatusBarView, which provides us with a stronger guarantee that things are working and codifies the places where status bar content layout can be changed. Also in this CL is a better dot positioning algorithm that will ensure there is no flickering when the dot needs to rotate. Test: manual Bug 187973222 Change-Id: I3dba7719ac4c4d178c9ec5265865961dbd0450f9
This commit is contained in:
@@ -99,6 +99,7 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
|
||||
import com.android.systemui.statusbar.phone.ManagedProfileController;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarWindowController;
|
||||
import com.android.systemui.statusbar.policy.AccessibilityController;
|
||||
@@ -371,6 +372,7 @@ public class Dependency {
|
||||
@Inject Lazy<PrivacyDotViewController> mPrivacyDotViewControllerLazy;
|
||||
@Inject Provider<EdgeBackGestureHandler> mEdgeBackGestureHandlerProvider;
|
||||
@Inject Lazy<UiEventLogger> mUiEventLogger;
|
||||
@Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
|
||||
@Inject Lazy<InternetDialogFactory> mInternetDialogFactory;
|
||||
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
|
||||
|
||||
@@ -587,6 +589,7 @@ public class Dependency {
|
||||
mProviders.put(EDGE_BACK_GESTURE_HANDLER_PROVIDER, () -> mEdgeBackGestureHandlerProvider);
|
||||
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
|
||||
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
|
||||
mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
|
||||
|
||||
Dependency.setInstance(this);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.events
|
||||
|
||||
import android.animation.Animator
|
||||
import android.annotation.UiThread
|
||||
import android.graphics.Point
|
||||
import android.graphics.Rect
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
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.statusbar.StatusBarState.SHADE
|
||||
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher
|
||||
import com.android.systemui.statusbar.phone.StatusBarMarginUpdatedListener
|
||||
import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
|
||||
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.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.util.concurrent.Executor
|
||||
@@ -58,9 +67,10 @@ import javax.inject.Inject
|
||||
class PrivacyDotViewController @Inject constructor(
|
||||
@Main private val mainExecutor: Executor,
|
||||
private val stateController: StatusBarStateController,
|
||||
private val locationPublisher: StatusBarLocationPublisher,
|
||||
private val configurationController: ConfigurationController,
|
||||
private val contentInsetsProvider: StatusBarContentInsetsProvider,
|
||||
private val animationScheduler: SystemStatusAnimationScheduler
|
||||
) {
|
||||
) : StatusBarContentInsetsChangedListener {
|
||||
private var sbHeightPortrait = 0
|
||||
private var sbHeightLandscape = 0
|
||||
|
||||
@@ -84,18 +94,22 @@ class PrivacyDotViewController @Inject constructor(
|
||||
// Privacy dots are created in ScreenDecoration's UiThread, which is not the main thread
|
||||
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>
|
||||
get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
|
||||
|
||||
init {
|
||||
locationPublisher.addCallback(marginListener)
|
||||
contentInsetsProvider.addCallback(this)
|
||||
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 {
|
||||
override fun onExpandedChanged(isExpanded: Boolean) {
|
||||
@@ -123,16 +137,19 @@ class PrivacyDotViewController @Inject constructor(
|
||||
fun setNewRotation(rot: Int) {
|
||||
dlog("updateRotation: $rot")
|
||||
|
||||
val isRtl: Boolean
|
||||
synchronized(lock) {
|
||||
if (rot == nextViewState.rotation) {
|
||||
return
|
||||
}
|
||||
|
||||
isRtl = nextViewState.layoutRtl
|
||||
}
|
||||
|
||||
// If we rotated, hide all dotes until the next state resolves
|
||||
setCornerVisibilities(View.INVISIBLE)
|
||||
|
||||
val newCorner = selectDesignatedCorner(rot)
|
||||
val newCorner = selectDesignatedCorner(rot, isRtl)
|
||||
val index = newCorner.cornerIndex()
|
||||
|
||||
val h = when (rot) {
|
||||
@@ -222,15 +239,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
|
||||
@UiThread
|
||||
private fun selectDesignatedCorner(r: Int): View? {
|
||||
private fun selectDesignatedCorner(r: Int, isRtl: Boolean): View? {
|
||||
if (!this::tl.isInitialized) {
|
||||
return null
|
||||
}
|
||||
|
||||
val isRtl = tl.isLayoutRtl
|
||||
|
||||
return when (r) {
|
||||
0 -> if (isRtl) tl else tr
|
||||
1 -> if (isRtl) tr else br
|
||||
@@ -282,6 +361,17 @@ class PrivacyDotViewController @Inject constructor(
|
||||
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 {
|
||||
return when (corner) {
|
||||
TOP_LEFT, BOTTOM_LEFT -> left
|
||||
@@ -303,15 +393,32 @@ class PrivacyDotViewController @Inject constructor(
|
||||
bl = bottomLeft
|
||||
br = bottomRight
|
||||
|
||||
val dc = selectDesignatedCorner(0)
|
||||
val rtl = configurationController.isLayoutRtl
|
||||
val dc = selectDesignatedCorner(0, rtl)
|
||||
|
||||
val index = dc.cornerIndex()
|
||||
|
||||
mainExecutor.execute {
|
||||
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) {
|
||||
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 +431,6 @@ class PrivacyDotViewController @Inject constructor(
|
||||
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() {
|
||||
synchronized(lock) {
|
||||
nextViewState = nextViewState.copy(shadeExpanded = isShadeInQs())
|
||||
@@ -377,6 +471,11 @@ class PrivacyDotViewController @Inject constructor(
|
||||
@UiThread
|
||||
private fun resolveState(state: ViewState) {
|
||||
dlog("resolveState $state")
|
||||
if (!state.viewInitialized) {
|
||||
dlog("resolveState: view is not initialized. skipping")
|
||||
return
|
||||
}
|
||||
|
||||
if (state == currentViewState) {
|
||||
dlog("resolveState: skipping")
|
||||
return
|
||||
@@ -387,23 +486,15 @@ class PrivacyDotViewController @Inject constructor(
|
||||
updateRotations(state.rotation)
|
||||
}
|
||||
|
||||
if (state.height != currentViewState.height) {
|
||||
updateHeights(state.rotation)
|
||||
}
|
||||
|
||||
if (state.marginLeft != currentViewState.marginLeft ||
|
||||
state.marginRight != currentViewState.marginRight) {
|
||||
updateCornerSizes(state.marginLeft, state.marginRight, state.rotation)
|
||||
if (state.needsLayout(currentViewState)) {
|
||||
setCornerSizes(state)
|
||||
views.forEach { it.requestLayout() }
|
||||
}
|
||||
|
||||
if (state.designatedCorner != currentViewState.designatedCorner) {
|
||||
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
|
||||
}
|
||||
|
||||
if (state.needsLayout(currentViewState)) {
|
||||
views.forEach { it.requestLayout() }
|
||||
}
|
||||
|
||||
val shouldShow = state.shouldShowDot()
|
||||
if (shouldShow != currentViewState.shouldShowDot()) {
|
||||
if (shouldShow && state.designatedCorner != null) {
|
||||
@@ -441,6 +532,35 @@ class PrivacyDotViewController @Inject constructor(
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun onStatusBarContentInsetsChanged() {
|
||||
Log.d(TAG, "onStatusBarContentInsetsChanged: ")
|
||||
setNewLayoutRects()
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@@ -461,7 +581,7 @@ const val BOTTOM_RIGHT = 2
|
||||
const val BOTTOM_LEFT = 3
|
||||
private const val DURATION = 160L
|
||||
private const val TAG = "PrivacyDotViewController"
|
||||
private const val DEBUG = true
|
||||
private const val DEBUG = false
|
||||
private const val DEBUG_VERBOSE = false
|
||||
|
||||
private fun Int.toGravity(): Int {
|
||||
@@ -485,14 +605,20 @@ private fun Int.innerGravity(): Int {
|
||||
}
|
||||
|
||||
private data class ViewState(
|
||||
val viewInitialized: Boolean = false,
|
||||
|
||||
val systemPrivacyEventIsActive: Boolean = false,
|
||||
val shadeExpanded: 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 height: Int = 0,
|
||||
val marginLeft: Int = 0,
|
||||
val marginRight: Int = 0,
|
||||
val cornerIndex: Int = -1,
|
||||
val designatedCorner: View? = null
|
||||
) {
|
||||
@@ -502,7 +628,20 @@ private data class ViewState(
|
||||
|
||||
fun needsLayout(other: ViewState): Boolean {
|
||||
return rotation != other.rotation ||
|
||||
marginRight != other.marginRight ||
|
||||
height != other.height
|
||||
layoutRtl != other.layoutRtl ||
|
||||
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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import android.view.ViewGroup;
|
||||
import android.view.ViewStub;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
@@ -79,9 +78,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
public static final int FADE_IN_DURATION = 320;
|
||||
public static final int FADE_IN_DELAY = 50;
|
||||
private PhoneStatusBarView mStatusBar;
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
private KeyguardStateController mKeyguardStateController;
|
||||
private NetworkController mNetworkController;
|
||||
private final StatusBarStateController mStatusBarStateController;
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final NetworkController mNetworkController;
|
||||
private LinearLayout mSystemIconArea;
|
||||
private View mClockView;
|
||||
private View mOngoingCallChip;
|
||||
@@ -92,12 +91,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
private Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
|
||||
private DarkIconManager mDarkIconManager;
|
||||
private View mOperatorNameFrame;
|
||||
private CommandQueue mCommandQueue;
|
||||
private OngoingCallController mOngoingCallController;
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final OngoingCallController mOngoingCallController;
|
||||
private final SystemStatusAnimationScheduler mAnimationScheduler;
|
||||
private final StatusBarLocationPublisher mLocationPublisher;
|
||||
private NotificationIconAreaController mNotificationIconAreaController;
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
private final NotificationIconAreaController mNotificationIconAreaController;
|
||||
private final StatusBarIconController mStatusBarIconController;
|
||||
|
||||
private List<String> mBlockedIcons = new ArrayList<>();
|
||||
|
||||
@@ -122,23 +122,24 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
StatusBarLocationPublisher locationPublisher,
|
||||
NotificationIconAreaController notificationIconAreaController,
|
||||
FeatureFlags featureFlags,
|
||||
Lazy<Optional<StatusBar>> statusBarOptionalLazy
|
||||
StatusBarIconController statusBarIconController,
|
||||
KeyguardStateController keyguardStateController,
|
||||
NetworkController networkController,
|
||||
StatusBarStateController statusBarStateController,
|
||||
Lazy<Optional<StatusBar>> statusBarOptionalLazy,
|
||||
CommandQueue commandQueue
|
||||
) {
|
||||
mOngoingCallController = ongoingCallController;
|
||||
mAnimationScheduler = animationScheduler;
|
||||
mLocationPublisher = locationPublisher;
|
||||
mNotificationIconAreaController = notificationIconAreaController;
|
||||
mFeatureFlags = featureFlags;
|
||||
mStatusBarIconController = statusBarIconController;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mNetworkController = networkController;
|
||||
mStatusBarStateController = statusBarStateController;
|
||||
mStatusBarOptionalLazy = statusBarOptionalLazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
|
||||
mNetworkController = Dependency.get(NetworkController.class);
|
||||
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
|
||||
mCommandQueue = Dependency.get(CommandQueue.class);
|
||||
mCommandQueue = commandQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,7 +165,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_call_strength));
|
||||
mDarkIconManager.setBlockList(mBlockedIcons);
|
||||
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
|
||||
mStatusBarIconController.addIconGroup(mDarkIconManager);
|
||||
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
|
||||
mClockView = mStatusBar.findViewById(R.id.clock);
|
||||
mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
|
||||
@@ -203,7 +204,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
|
||||
mStatusBarIconController.removeIconGroup(mDarkIconManager);
|
||||
if (mNetworkController.hasEmergencyCryptKeeperText()) {
|
||||
mNetworkController.removeCallback(mSignalCallback);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import android.content.Context
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.os.LocaleList
|
||||
import android.view.View.LAYOUT_DIRECTION_RTL
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
|
||||
import java.util.ArrayList
|
||||
@@ -33,6 +34,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
|
||||
private var uiMode: Int = 0
|
||||
private var localeList: LocaleList? = null
|
||||
private val context: Context
|
||||
private var layoutDirection: Int
|
||||
|
||||
init {
|
||||
val currentConfig = context.resources.configuration
|
||||
@@ -44,6 +46,7 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
|
||||
Configuration.UI_MODE_TYPE_CAR
|
||||
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||
localeList = currentConfig.locales
|
||||
layoutDirection = currentConfig.layoutDirection
|
||||
}
|
||||
|
||||
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) {
|
||||
listeners.filterForEach({ this.listeners.contains(it) }) {
|
||||
it.onOverlayChanged()
|
||||
@@ -116,6 +126,10 @@ class ConfigurationControllerImpl(context: Context) : ConfigurationController {
|
||||
override fun removeCallback(listener: ConfigurationController.ConfigurationListener) {
|
||||
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
|
||||
|
||||
@@ -23,6 +23,7 @@ import static java.lang.Float.isNaN;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
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_GESTURES = false;
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final StatusBarContentInsetsProvider mContentInsetsProvider;
|
||||
|
||||
StatusBar mBar;
|
||||
|
||||
@@ -85,11 +87,10 @@ public class PhoneStatusBarView extends PanelBar {
|
||||
private int mCutoutSideNudge = 0;
|
||||
private boolean mHeadsUpVisible;
|
||||
|
||||
private int mRoundedCornerPadding = 0;
|
||||
|
||||
public PhoneStatusBarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mCommandQueue = Dependency.get(CommandQueue.class);
|
||||
mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
|
||||
}
|
||||
|
||||
public void setBar(StatusBar bar) {
|
||||
@@ -305,8 +306,6 @@ public class PhoneStatusBarView extends PanelBar {
|
||||
public void updateResources() {
|
||||
mCutoutSideNudge = getResources().getDimensionPixelSize(
|
||||
R.dimen.display_cutout_margin_consumption);
|
||||
mRoundedCornerPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.rounded_corner_content_padding);
|
||||
|
||||
updateStatusBarHeight();
|
||||
}
|
||||
@@ -341,8 +340,7 @@ public class PhoneStatusBarView extends PanelBar {
|
||||
private void updateLayoutForCutout() {
|
||||
updateStatusBarHeight();
|
||||
updateCutoutLocation(StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()));
|
||||
updateSafeInsets(StatusBarWindowView.statusBarCornerCutoutMargins(mDisplayCutout,
|
||||
getDisplay(), mRotationOrientation, mStatusBarHeight));
|
||||
updateSafeInsets();
|
||||
}
|
||||
|
||||
private void updateCutoutLocation(Pair<Integer, Integer> cornerCutoutMargins) {
|
||||
@@ -370,15 +368,18 @@ public class PhoneStatusBarView extends PanelBar {
|
||||
lp.height = bounds.height();
|
||||
}
|
||||
|
||||
private void updateSafeInsets(Pair<Integer, Integer> cornerCutoutMargins) {
|
||||
// Depending on our rotation, we may have to work around a cutout in the middle of the view,
|
||||
// or letterboxing from the right or left sides.
|
||||
private void updateSafeInsets() {
|
||||
Rect contentRect = mContentInsetsProvider
|
||||
.getStatusBarContentInsetsForRotation(RotationUtils.getExactRotation(getContext()));
|
||||
|
||||
Pair<Integer, Integer> padding =
|
||||
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
|
||||
mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
|
||||
Point size = new Point();
|
||||
getDisplay().getRealSize(size);
|
||||
|
||||
setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom());
|
||||
setPadding(
|
||||
contentRect.left,
|
||||
getPaddingTop(),
|
||||
size.x - contentRect.right,
|
||||
getPaddingBottom());
|
||||
}
|
||||
|
||||
public void setHeadsUpVisible(boolean headsUpVisible) {
|
||||
|
||||
@@ -442,6 +442,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
private final OngoingCallController mOngoingCallController;
|
||||
private final SystemStatusAnimationScheduler mAnimationScheduler;
|
||||
private final StatusBarLocationPublisher mStatusBarLocationPublisher;
|
||||
private final StatusBarIconController mStatusBarIconController;
|
||||
|
||||
// expanded notifications
|
||||
// the sliding/resizing panel within the notification window
|
||||
@@ -804,6 +805,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
OngoingCallController ongoingCallController,
|
||||
SystemStatusAnimationScheduler animationScheduler,
|
||||
StatusBarLocationPublisher locationPublisher,
|
||||
StatusBarIconController statusBarIconController,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
FeatureFlags featureFlags,
|
||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||
@@ -890,6 +892,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mOngoingCallController = ongoingCallController;
|
||||
mAnimationScheduler = animationScheduler;
|
||||
mStatusBarLocationPublisher = locationPublisher;
|
||||
mStatusBarIconController = statusBarIconController;
|
||||
mFeatureFlags = featureFlags;
|
||||
mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
|
||||
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
|
||||
@@ -1193,7 +1196,13 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mStatusBarLocationPublisher,
|
||||
mNotificationIconAreaController,
|
||||
mFeatureFlags,
|
||||
() -> Optional.of(this)),
|
||||
mStatusBarIconController,
|
||||
mKeyguardStateController,
|
||||
mNetworkController,
|
||||
mStatusBarStateController,
|
||||
() -> Optional.of(this),
|
||||
mCommandQueue
|
||||
),
|
||||
CollapsedStatusBarFragment.TAG)
|
||||
.commit();
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
|
||||
import com.android.systemui.statusbar.phone.ScrimController;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
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.StatusBarLocationPublisher;
|
||||
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
|
||||
@@ -216,6 +217,7 @@ public interface StatusBarPhoneModule {
|
||||
OngoingCallController ongoingCallController,
|
||||
SystemStatusAnimationScheduler animationScheduler,
|
||||
StatusBarLocationPublisher locationPublisher,
|
||||
StatusBarIconController statusBarIconController,
|
||||
LockscreenShadeTransitionController transitionController,
|
||||
FeatureFlags featureFlags,
|
||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||
@@ -305,6 +307,7 @@ public interface StatusBarPhoneModule {
|
||||
ongoingCallController,
|
||||
animationScheduler,
|
||||
locationPublisher,
|
||||
statusBarIconController,
|
||||
transitionController,
|
||||
featureFlags,
|
||||
keyguardUnlockAnimationController,
|
||||
|
||||
@@ -30,6 +30,9 @@ public interface ConfigurationController extends CallbackController<Configuratio
|
||||
/** Alert controller of a change in between light and dark themes. */
|
||||
void notifyThemeChanged();
|
||||
|
||||
/** Query the current configuration's layout direction */
|
||||
boolean isLayoutRtl();
|
||||
|
||||
interface ConfigurationListener {
|
||||
default void onConfigChanged(Configuration newConfig) {}
|
||||
default void onDensityOrFontScaleChanged() {}
|
||||
@@ -38,5 +41,6 @@ public interface ConfigurationController extends CallbackController<Configuratio
|
||||
default void onUiModeChanged() {}
|
||||
default void onThemeChanged() {}
|
||||
default void onLocaleListChanged() {}
|
||||
default void onLayoutDirectionChanged(boolean isLayoutRtl) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,15 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiBaseFragmentTest;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
|
||||
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.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
@@ -54,21 +58,28 @@ import java.util.Optional;
|
||||
@SmallTest
|
||||
public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
|
||||
private StatusBar mStatusBar;
|
||||
private NotificationIconAreaController mMockNotificationAreaController;
|
||||
private View mNotificationAreaInner;
|
||||
private StatusBarStateController mStatusBarStateController;
|
||||
private OngoingCallController mOngoingCallController;
|
||||
private SystemStatusAnimationScheduler mAnimationScheduler;
|
||||
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() {
|
||||
super(CollapsedStatusBarFragment.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mStatusBar = mock(StatusBar.class);
|
||||
mStatusBarStateController = mDependency
|
||||
.injectMockDependency(StatusBarStateController.class);
|
||||
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
|
||||
@@ -204,6 +215,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
|
||||
}
|
||||
|
||||
@Ignore("b/192618546")
|
||||
@Test
|
||||
public void testOnDozingChanged() throws Exception {
|
||||
mFragments.dispatchResume();
|
||||
@@ -227,6 +239,10 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
mOngoingCallController = mock(OngoingCallController.class);
|
||||
mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
|
||||
mLocationPublisher = mock(StatusBarLocationPublisher.class);
|
||||
mStatusBarIconController = mock(StatusBarIconController.class);
|
||||
mNetworkController = mock(NetworkController.class);
|
||||
mStatusBarStateController = mock(StatusBarStateController.class);
|
||||
mKeyguardStateController = mock(KeyguardStateController.class);
|
||||
setUpNotificationIconAreaController();
|
||||
return new CollapsedStatusBarFragment(
|
||||
mOngoingCallController,
|
||||
@@ -234,9 +250,15 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
|
||||
mLocationPublisher,
|
||||
mMockNotificationAreaController,
|
||||
mock(FeatureFlags.class),
|
||||
() -> Optional.of(mStatusBar));
|
||||
mStatusBarIconController,
|
||||
mKeyguardStateController,
|
||||
mNetworkController,
|
||||
mStatusBarStateController,
|
||||
() -> Optional.of(mStatusBar),
|
||||
mCommandQueue);
|
||||
}
|
||||
|
||||
|
||||
private void setUpNotificationIconAreaController() {
|
||||
mMockNotificationAreaController = mock(NotificationIconAreaController.class);
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ public class StatusBarTest extends SysuiTestCase {
|
||||
@Mock private OngoingCallController mOngoingCallController;
|
||||
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
|
||||
@Mock private StatusBarLocationPublisher mLocationPublisher;
|
||||
@Mock private StatusBarIconController mIconController;
|
||||
@Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private IWallpaperManager mWallpaperManager;
|
||||
@@ -442,6 +443,7 @@ public class StatusBarTest extends SysuiTestCase {
|
||||
mOngoingCallController,
|
||||
mAnimationScheduler,
|
||||
mLocationPublisher,
|
||||
mIconController,
|
||||
mLockscreenTransitionController,
|
||||
mFeatureFlags,
|
||||
mKeyguardUnlockAnimationController,
|
||||
|
||||
@@ -33,4 +33,9 @@ public class FakeConfigurationController
|
||||
@Override
|
||||
public void notifyThemeChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLayoutRtl() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user