• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.statusbar.phone;
18 
19 import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
20 import static com.android.systemui.util.Utils.getStatusBarHeaderHeightKeyguard;
21 
22 import android.annotation.ColorInt;
23 import android.content.Context;
24 import android.content.res.Configuration;
25 import android.content.res.Resources;
26 import android.graphics.Color;
27 import android.graphics.Insets;
28 import android.graphics.Rect;
29 import android.graphics.drawable.Drawable;
30 import android.os.Trace;
31 import android.util.AttributeSet;
32 import android.util.TypedValue;
33 import android.view.DisplayCutout;
34 import android.view.Gravity;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.view.WindowInsets;
38 import android.widget.ImageView;
39 import android.widget.LinearLayout;
40 import android.widget.RelativeLayout;
41 import android.widget.TextView;
42 
43 import androidx.annotation.Nullable;
44 import androidx.annotation.VisibleForTesting;
45 
46 import com.android.settingslib.Utils;
47 import com.android.systemui.battery.BatteryMeterView;
48 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
49 import com.android.systemui.res.R;
50 import com.android.systemui.statusbar.core.NewStatusBarIcons;
51 import com.android.systemui.statusbar.layout.StatusBarContentInsetsProvider;
52 import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange;
53 import com.android.systemui.statusbar.phone.ui.TintedIconManager;
54 import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
55 import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
56 import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
57 
58 import kotlinx.coroutines.flow.FlowKt;
59 import kotlinx.coroutines.flow.MutableStateFlow;
60 import kotlinx.coroutines.flow.StateFlow;
61 import kotlinx.coroutines.flow.StateFlowKt;
62 
63 import java.io.PrintWriter;
64 import java.util.ArrayList;
65 import java.util.Objects;
66 
67 /**
68  * The header group on Keyguard.
69  */
70 public class KeyguardStatusBarView extends RelativeLayout {
71 
72     private static final int LAYOUT_NONE = 0;
73     private static final int LAYOUT_CUTOUT = 1;
74     private static final int LAYOUT_NO_CUTOUT = 2;
75 
76     private final ArrayList<Rect> mEmptyTintRect = new ArrayList<>();
77 
78     private boolean mShowPercentAvailable;
79     private boolean mBatteryCharging;
80 
81     private TextView mCarrierLabel;
82     private ImageView mMultiUserAvatar;
83     @Nullable private BatteryMeterView mBatteryView;
84     private StatusIconContainer mStatusIconContainer;
85     private StatusBarUserSwitcherContainer mUserSwitcherContainer;
86 
87     private boolean mKeyguardUserSwitcherEnabled;
88     private boolean mKeyguardUserAvatarEnabled;
89 
90     private boolean mIsPrivacyDotEnabled;
91     private int mSystemIconsSwitcherHiddenExpandedMargin;
92     private int mStatusBarPaddingEnd;
93     private int mMinDotWidth;
94     private View mSystemIconsContainer;
95     private View mSystemIcons;
96     private final MutableStateFlow<DarkChange> mDarkChange = StateFlowKt.MutableStateFlow(
97             DarkChange.EMPTY);
98 
99     private View mCutoutSpace;
100     private ViewGroup mStatusIconArea;
101     private int mLayoutState = LAYOUT_NONE;
102 
103     /**
104      * Draw this many pixels into the left/right side of the cutout to optimally use the space
105      */
106     private int mCutoutSideNudge = 0;
107 
108     @Nullable
109     private WindowInsets mPreviousInsets = null;
110 
111     private DisplayCutout mDisplayCutout;
112     private int mRoundedCornerPadding = 0;
113     // right and left padding applied to this view to account for cutouts and rounded corners
114     private Insets mPadding = Insets.of(0, 0, 0, 0);
115 
116     /**
117      * The clipping on the top
118      */
119     private int mTopClipping;
120     private final Rect mClipRect = new Rect(0, 0, 0, 0);
121     private boolean mIsUserSwitcherEnabled;
122 
KeyguardStatusBarView(Context context, AttributeSet attrs)123     public KeyguardStatusBarView(Context context, AttributeSet attrs) {
124         super(context, attrs);
125     }
126 
127     @Override
onFinishInflate()128     protected void onFinishInflate() {
129         super.onFinishInflate();
130         mSystemIconsContainer = findViewById(R.id.system_icons_container);
131         mSystemIcons = findViewById(R.id.system_icons);
132         mMultiUserAvatar = findViewById(R.id.multi_user_avatar);
133         mCarrierLabel = findViewById(R.id.keyguard_carrier_text);
134         mBatteryView = mSystemIconsContainer.findViewById(R.id.battery);
135         if (NewStatusBarIcons.isEnabled()) {
136             // When this flag is rolled forward, this whole view can be removed
137             mBatteryView.setVisibility(View.GONE);
138             mBatteryView = null;
139         }
140         mCutoutSpace = findViewById(R.id.cutout_space_view);
141         mStatusIconArea = findViewById(R.id.status_icon_area);
142         mStatusIconContainer = findViewById(R.id.statusIcons);
143         mUserSwitcherContainer = findViewById(R.id.user_switcher_container);
144         mIsPrivacyDotEnabled = mContext.getResources().getBoolean(R.bool.config_enablePrivacyDot);
145         loadDimens();
146     }
147 
148     /**
149      * Should only be called from {@link KeyguardStatusBarViewController}
150      * @param viewModel view model for the status bar user chip
151      */
init(StatusBarUserChipViewModel viewModel)152     void init(StatusBarUserChipViewModel viewModel) {
153         StatusBarUserChipViewBinder.bind(mUserSwitcherContainer, viewModel);
154     }
155 
156     @Override
onConfigurationChanged(Configuration newConfig)157     protected void onConfigurationChanged(Configuration newConfig) {
158         super.onConfigurationChanged(newConfig);
159         loadDimens();
160 
161         MarginLayoutParams lp = (MarginLayoutParams) mMultiUserAvatar.getLayoutParams();
162         lp.width = lp.height = getResources().getDimensionPixelSize(
163                 R.dimen.multi_user_avatar_keyguard_size);
164         mMultiUserAvatar.setLayoutParams(lp);
165 
166         // System icons
167         updateSystemIconsLayoutParams();
168 
169         // mStatusIconArea
170         mStatusIconArea.setPaddingRelative(
171                 mStatusIconArea.getPaddingStart(),
172                 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_top),
173                 mStatusIconArea.getPaddingEnd(),
174                 mStatusIconArea.getPaddingBottom()
175         );
176 
177         // mStatusIconContainer
178         mStatusIconContainer.setPaddingRelative(
179                 mStatusIconContainer.getPaddingStart(),
180                 mStatusIconContainer.getPaddingTop(),
181                 getResources().getDimensionPixelSize(R.dimen.signal_cluster_battery_padding),
182                 mStatusIconContainer.getPaddingBottom()
183         );
184 
185         mSystemIcons.setPaddingRelative(
186                 getResources().getDimensionPixelSize(R.dimen.status_bar_icons_padding_start),
187                 getResources().getDimensionPixelSize(R.dimen.status_bar_icons_padding_top),
188                 getResources().getDimensionPixelSize(R.dimen.status_bar_icons_padding_end),
189                 getResources().getDimensionPixelSize(R.dimen.status_bar_icons_padding_bottom)
190         );
191 
192         // Respect font size setting.
193         mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
194                 getResources().getDimensionPixelSize(
195                         com.android.internal.R.dimen.text_size_small_material));
196         updateCarrierLabelMargin();
197 
198         updateKeyguardStatusBarHeight();
199     }
200 
setUserSwitcherEnabled(boolean enabled)201     public void setUserSwitcherEnabled(boolean enabled) {
202         mIsUserSwitcherEnabled = enabled;
203     }
204 
updateKeyguardStatusBarHeight()205     private void updateKeyguardStatusBarHeight() {
206         ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) getLayoutParams();
207         lp.height = getStatusBarHeaderHeightKeyguard(mContext);
208         setLayoutParams(lp);
209     }
210 
updateCarrierLabelMargin()211     private void updateCarrierLabelMargin() {
212         MarginLayoutParams lp = (MarginLayoutParams) mCarrierLabel.getLayoutParams();
213         int marginStart = calculateMargin(
214                 getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin),
215                 mPadding.left);
216         lp.setMarginStart(marginStart);
217         mCarrierLabel.setLayoutParams(lp);
218     }
219 
loadDimens()220     void loadDimens() {
221         Resources res = getResources();
222         mSystemIconsSwitcherHiddenExpandedMargin = res.getDimensionPixelSize(
223                 R.dimen.system_icons_switcher_hidden_expanded_margin);
224         mStatusBarPaddingEnd = res.getDimensionPixelSize(
225                 R.dimen.status_bar_padding_end);
226         mMinDotWidth = res.getDimensionPixelSize(
227                 R.dimen.ongoing_appops_dot_min_padding);
228         mCutoutSideNudge = getResources().getDimensionPixelSize(
229                 R.dimen.display_cutout_margin_consumption);
230         mShowPercentAvailable = getContext().getResources().getBoolean(
231                 com.android.internal.R.bool.config_battery_percentage_setting_available);
232         mRoundedCornerPadding = res.getDimensionPixelSize(
233                 R.dimen.rounded_corner_content_padding);
234     }
235 
updateVisibilities()236     private void updateVisibilities() {
237         // Multi user avatar is disabled in favor of the user switcher chip
238         if (!mKeyguardUserAvatarEnabled) {
239             if (mMultiUserAvatar.getParent() == mStatusIconArea) {
240                 mStatusIconArea.removeView(mMultiUserAvatar);
241             } else if (mMultiUserAvatar.getParent() != null) {
242                 getOverlay().remove(mMultiUserAvatar);
243             }
244 
245             return;
246         }
247 
248         if (mMultiUserAvatar.getParent() != mStatusIconArea
249                 && !mKeyguardUserSwitcherEnabled) {
250             if (mMultiUserAvatar.getParent() != null) {
251                 getOverlay().remove(mMultiUserAvatar);
252             }
253             mStatusIconArea.addView(mMultiUserAvatar, 0);
254         } else if (mMultiUserAvatar.getParent() == mStatusIconArea
255                 && mKeyguardUserSwitcherEnabled) {
256             mStatusIconArea.removeView(mMultiUserAvatar);
257         }
258         if (!mKeyguardUserSwitcherEnabled) {
259             // If we have no keyguard switcher, the screen width is under 600dp. In this case,
260             // we only show the multi-user switch if it's enabled through UserManager as well as
261             // by the user.
262             if (mIsUserSwitcherEnabled) {
263                 mMultiUserAvatar.setVisibility(View.VISIBLE);
264             } else {
265                 mMultiUserAvatar.setVisibility(View.GONE);
266             }
267         }
268 
269         if (mBatteryView != null) {
270             mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable);
271         }
272     }
273 
updateSystemIconsLayoutParams()274     private void updateSystemIconsLayoutParams() {
275         LinearLayout.LayoutParams lp =
276                 (LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
277 
278         // Use status_bar_padding_end to replace original
279         // system_icons_super_container_avatarless_margin_end to prevent different end alignment
280         // between PhoneStatusBarView and KeyguardStatusBarView
281         int baseMarginEnd = mStatusBarPaddingEnd;
282         int marginEnd =
283                 mKeyguardUserSwitcherEnabled ? mSystemIconsSwitcherHiddenExpandedMargin
284                         : baseMarginEnd;
285 
286         // Align PhoneStatusBar right margin/padding, only use
287         // 1. status bar layout: mPadding(consider round_corner + privacy dot)
288         // 2. icon container: R.dimen.status_bar_padding_end
289 
290         if (marginEnd != lp.getMarginEnd()) {
291             lp.setMarginEnd(marginEnd);
292             mSystemIconsContainer.setLayoutParams(lp);
293         }
294     }
295 
296     /** Should only be called from {@link KeyguardStatusBarViewController}. */
updateWindowInsets( WindowInsets insets, StatusBarContentInsetsProvider insetsProvider)297     WindowInsets updateWindowInsets(
298             WindowInsets insets,
299             StatusBarContentInsetsProvider insetsProvider) {
300         if (!Objects.equals(mPreviousInsets, insets)) {
301             mLayoutState = LAYOUT_NONE;
302             if (updateLayoutConsideringCutout(insetsProvider)) {
303                 requestLayout();
304             }
305             mPreviousInsets = new WindowInsets(insets);
306         }
307         return super.onApplyWindowInsets(insets);
308     }
309 
updateLayoutConsideringCutout(StatusBarContentInsetsProvider insetsProvider)310     private boolean updateLayoutConsideringCutout(StatusBarContentInsetsProvider insetsProvider) {
311         return setDisplayCutout(
312                 getRootWindowInsets().getDisplayCutout(),
313                 insetsProvider);
314     }
315 
316     /** Sets the {@link DisplayCutout}, updating the view to render around the cutout. */
setDisplayCutout( @ullable DisplayCutout displayCutout, StatusBarContentInsetsProvider insetsProvider)317     public boolean setDisplayCutout(
318             @Nullable DisplayCutout displayCutout,
319             StatusBarContentInsetsProvider insetsProvider) {
320         mDisplayCutout = displayCutout;
321         updateKeyguardStatusBarHeight();
322         updatePadding(insetsProvider);
323         if (mDisplayCutout == null || insetsProvider.currentRotationHasCornerCutout()) {
324             return updateLayoutParamsNoCutout();
325         } else {
326             return updateLayoutParamsForCutout();
327         }
328     }
329 
updatePadding(StatusBarContentInsetsProvider insetsProvider)330     private void updatePadding(StatusBarContentInsetsProvider insetsProvider) {
331         final int waterfallTop =
332                 mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
333         mPadding = insetsProvider.getStatusBarContentInsetsForCurrentRotation();
334 
335         // consider privacy dot space
336         final int minLeft = (isLayoutRtl() && mIsPrivacyDotEnabled)
337                 ? Math.max(mMinDotWidth, mPadding.left) : mPadding.left;
338         final int minRight = (!isLayoutRtl() && mIsPrivacyDotEnabled)
339                 ? Math.max(mMinDotWidth, mPadding.right) : mPadding.right;
340 
341         int top = waterfallTop + mPadding.top;
342         setPadding(minLeft, top, minRight, 0);
343     }
344 
updateLayoutParamsNoCutout()345     private boolean updateLayoutParamsNoCutout() {
346         if (mLayoutState == LAYOUT_NO_CUTOUT) {
347             return false;
348         }
349         mLayoutState = LAYOUT_NO_CUTOUT;
350 
351         if (mCutoutSpace != null) {
352             mCutoutSpace.setVisibility(View.GONE);
353         }
354 
355         RelativeLayout.LayoutParams lp = (LayoutParams) mCarrierLabel.getLayoutParams();
356         lp.addRule(RelativeLayout.START_OF, R.id.status_icon_area);
357         updateCarrierLabelMargin();
358 
359         lp = (LayoutParams) mStatusIconArea.getLayoutParams();
360         lp.removeRule(RelativeLayout.RIGHT_OF);
361         lp.width = LayoutParams.WRAP_CONTENT;
362         lp.setMarginStart(getResources().getDimensionPixelSize(
363                 R.dimen.system_icons_super_container_margin_start));
364         return true;
365     }
366 
updateLayoutParamsForCutout()367     private boolean updateLayoutParamsForCutout() {
368         if (mLayoutState == LAYOUT_CUTOUT) {
369             return false;
370         }
371         mLayoutState = LAYOUT_CUTOUT;
372 
373         if (mCutoutSpace == null) {
374             updateLayoutParamsNoCutout();
375         }
376 
377         Rect bounds = new Rect();
378         boundsFromDirection(mDisplayCutout, Gravity.TOP, bounds);
379 
380         mCutoutSpace.setVisibility(View.VISIBLE);
381         RelativeLayout.LayoutParams lp = (LayoutParams) mCutoutSpace.getLayoutParams();
382         bounds.left = bounds.left + mCutoutSideNudge;
383         bounds.right = bounds.right - mCutoutSideNudge;
384         lp.width = bounds.width();
385         lp.height = bounds.height();
386         lp.addRule(RelativeLayout.CENTER_IN_PARENT);
387 
388         lp = (LayoutParams) mCarrierLabel.getLayoutParams();
389         lp.addRule(RelativeLayout.START_OF, R.id.cutout_space_view);
390         updateCarrierLabelMargin();
391 
392         lp = (LayoutParams) mStatusIconArea.getLayoutParams();
393         lp.addRule(RelativeLayout.RIGHT_OF, R.id.cutout_space_view);
394         lp.width = LayoutParams.MATCH_PARENT;
395         lp.setMarginStart(0);
396         return true;
397     }
398 
399     /** Should only be called from {@link KeyguardStatusBarViewController}. */
onUserInfoChanged(Drawable picture)400     void onUserInfoChanged(Drawable picture) {
401         mMultiUserAvatar.setImageDrawable(picture);
402     }
403 
404     /**
405      * Should only be called from {@link KeyguardStatusBarViewController} or
406      * {@link com.android.systemui.statusbar.ui.binder.KeyguardStatusBarViewBinder}.
407      */
onBatteryChargingChanged(boolean charging)408     public void onBatteryChargingChanged(boolean charging) {
409         if (mBatteryCharging != charging) {
410             mBatteryCharging = charging;
411             updateVisibilities();
412         }
413     }
414 
415     /**
416      * Should only be called from {@link KeyguardStatusBarViewController} or
417      * {@link com.android.systemui.statusbar.ui.binder.KeyguardStatusBarViewBinder}.
418      */
setKeyguardUserSwitcherEnabled(boolean enabled)419     public void setKeyguardUserSwitcherEnabled(boolean enabled) {
420         mKeyguardUserSwitcherEnabled = enabled;
421     }
422 
setKeyguardUserAvatarEnabled(boolean enabled)423     void setKeyguardUserAvatarEnabled(boolean enabled) {
424         mKeyguardUserAvatarEnabled = enabled;
425         updateVisibilities();
426     }
427 
428     @VisibleForTesting
isKeyguardUserAvatarEnabled()429     boolean isKeyguardUserAvatarEnabled() {
430         return mKeyguardUserAvatarEnabled;
431     }
432 
433     @Override
setVisibility(int visibility)434     public void setVisibility(int visibility) {
435         super.setVisibility(visibility);
436         if (visibility != View.VISIBLE) {
437             mSystemIconsContainer.animate().cancel();
438             mSystemIconsContainer.setTranslationX(0);
439             mMultiUserAvatar.animate().cancel();
440             mMultiUserAvatar.setAlpha(1f);
441         } else {
442             updateVisibilities();
443             updateSystemIconsLayoutParams();
444         }
445     }
446 
447     @Override
hasOverlappingRendering()448     public boolean hasOverlappingRendering() {
449         return false;
450     }
451 
452     /** Should only be called from {@link KeyguardStatusBarViewController}. */
onThemeChanged(TintedIconManager iconManager)453     void onThemeChanged(TintedIconManager iconManager) {
454         if (mBatteryView != null) {
455             mBatteryView.setColorsFromContext(mContext);
456         }
457         updateIconsAndTextColors(iconManager);
458     }
459 
460     /** Should only be called from {@link KeyguardStatusBarViewController}. */
onOverlayChanged()461     void onOverlayChanged() {
462         final int carrierTheme = R.style.TextAppearance_StatusBar_Default;
463         mCarrierLabel.setTextAppearance(carrierTheme);
464         if (mBatteryView != null) {
465             mBatteryView.updatePercentView();
466         }
467 
468         final int userSwitcherTheme = R.style.TextAppearance_StatusBar_UserChip;
469         TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
470         if (userSwitcherName != null) {
471             userSwitcherName.setTextAppearance(userSwitcherTheme);
472         }
473     }
474 
updateIconsAndTextColors(TintedIconManager iconManager)475     private void updateIconsAndTextColors(TintedIconManager iconManager) {
476         @ColorInt int textColor = Utils.getColorAttrDefaultColor(mContext,
477                 R.attr.wallpaperTextColor);
478         float luminance = Color.luminance(textColor);
479         @ColorInt int iconColor = Utils.getColorStateListDefaultColor(mContext,
480                     luminance < 0.5
481                         ? com.android.settingslib.R.color.dark_mode_icon_color_single_tone
482                         : com.android.settingslib.R.color.light_mode_icon_color_single_tone);
483         @ColorInt int contrastColor = luminance < 0.5
484                 ? DarkIconDispatcherImpl.DEFAULT_ICON_TINT
485                 : DarkIconDispatcherImpl.DEFAULT_INVERSE_ICON_TINT;
486         float intensity = textColor == Color.WHITE ? 0 : 1;
487         mCarrierLabel.setTextColor(iconColor);
488 
489         TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
490         if (userSwitcherName != null) {
491             userSwitcherName.setTextColor(Utils.getColorStateListDefaultColor(
492                     mContext,
493                     com.android.settingslib.R.color.light_mode_icon_color_single_tone));
494         }
495 
496         if (iconManager != null) {
497             iconManager.setTint(iconColor, contrastColor);
498         }
499 
500         mDarkChange.setValue(new DarkChange(mEmptyTintRect, intensity, iconColor));
501         applyDarkness(R.id.battery, mEmptyTintRect, intensity, iconColor);
502         applyDarkness(R.id.clock, mEmptyTintRect, intensity, iconColor);
503     }
504 
505     private void applyDarkness(int id, ArrayList<Rect> tintAreas, float intensity, int color) {
506         View v = findViewById(id);
507         if (v instanceof DarkReceiver) {
508             ((DarkReceiver) v).onDarkChanged(tintAreas, intensity, color);
509         }
510     }
511 
512     /**
513      * Calculates the margin that isn't already accounted for in the view's padding.
514      */
515     private int calculateMargin(int margin, int padding) {
516         if (padding >= margin) {
517             return 0;
518         } else {
519             return margin - padding;
520         }
521     }
522 
523     /** Should only be called from {@link KeyguardStatusBarViewController}. */
524     void dump(PrintWriter pw, String[] args) {
525         pw.println("KeyguardStatusBarView:");
526         pw.println("  mBatteryCharging: " + mBatteryCharging);
527         pw.println("  mLayoutState: " + mLayoutState);
528         pw.println("  mKeyguardUserSwitcherEnabled: " + mKeyguardUserSwitcherEnabled);
529         if (mBatteryView != null) {
530             mBatteryView.dump(pw, args);
531         }
532     }
533 
534     @Override
535     protected void onLayout(boolean changed, int l, int t, int r, int b) {
536         super.onLayout(changed, l, t, r, b);
537         updateClipping();
538     }
539 
540     /**
541      * Set the clipping on the top of the view.
542      *
543      * Should only be called from {@link KeyguardStatusBarViewController}.
544      */
545     void setTopClipping(int topClipping) {
546         if (topClipping != mTopClipping) {
547             mTopClipping = topClipping;
548             updateClipping();
549         }
550     }
551 
552     private void updateClipping() {
553         mClipRect.set(0, mTopClipping, getWidth(), getHeight());
554         setClipBounds(mClipRect);
555     }
556 
557     @Override
558     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
559         Trace.beginSection("KeyguardStatusBarView#onMeasure");
560         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
561         Trace.endSection();
562     }
563 
564     public StateFlow<DarkChange> darkChangeFlow() {
565         return FlowKt.asStateFlow(mDarkChange);
566     }
567 }
568