1 /* 2 * Copyright (C) 2020 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.keyguard; 18 19 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 20 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 21 22 import static com.android.keyguard.KeyguardClockSwitch.LARGE; 23 import static com.android.keyguard.KeyguardClockSwitch.SMALL; 24 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; 25 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; 26 27 import android.annotation.Nullable; 28 import android.database.ContentObserver; 29 import android.os.UserHandle; 30 import android.provider.Settings; 31 import android.text.TextUtils; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.FrameLayout; 35 import android.widget.LinearLayout; 36 37 import androidx.annotation.NonNull; 38 import androidx.annotation.VisibleForTesting; 39 40 import com.android.systemui.Dumpable; 41 import com.android.systemui.R; 42 import com.android.systemui.dagger.qualifiers.Main; 43 import com.android.systemui.dump.DumpManager; 44 import com.android.systemui.flags.FeatureFlags; 45 import com.android.systemui.keyguard.KeyguardUnlockAnimationController; 46 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; 47 import com.android.systemui.log.LogBuffer; 48 import com.android.systemui.log.core.LogLevel; 49 import com.android.systemui.log.dagger.KeyguardClockLog; 50 import com.android.systemui.plugins.ClockController; 51 import com.android.systemui.plugins.statusbar.StatusBarStateController; 52 import com.android.systemui.shared.clocks.ClockRegistry; 53 import com.android.systemui.shared.regionsampling.RegionSampler; 54 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; 55 import com.android.systemui.statusbar.notification.AnimatableProperty; 56 import com.android.systemui.statusbar.notification.PropertyAnimator; 57 import com.android.systemui.statusbar.notification.stack.AnimationProperties; 58 import com.android.systemui.statusbar.phone.NotificationIconAreaController; 59 import com.android.systemui.statusbar.phone.NotificationIconContainer; 60 import com.android.systemui.util.ViewController; 61 import com.android.systemui.util.concurrency.DelayableExecutor; 62 import com.android.systemui.util.settings.SecureSettings; 63 64 import java.io.PrintWriter; 65 import java.util.Locale; 66 import java.util.function.Consumer; 67 68 import javax.inject.Inject; 69 70 /** 71 * Injectable controller for {@link KeyguardClockSwitch}. 72 */ 73 public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch> 74 implements Dumpable { 75 private static final String TAG = "KeyguardClockSwitchController"; 76 77 private final StatusBarStateController mStatusBarStateController; 78 private final ClockRegistry mClockRegistry; 79 private final KeyguardSliceViewController mKeyguardSliceViewController; 80 private final NotificationIconAreaController mNotificationIconAreaController; 81 private final LockscreenSmartspaceController mSmartspaceController; 82 private final SecureSettings mSecureSettings; 83 private final DumpManager mDumpManager; 84 private final ClockEventController mClockEventController; 85 private final LogBuffer mLogBuffer; 86 87 private FrameLayout mSmallClockFrame; // top aligned clock 88 private FrameLayout mLargeClockFrame; // centered clock 89 90 @KeyguardClockSwitch.ClockSize 91 private int mCurrentClockSize = SMALL; 92 93 private int mKeyguardSmallClockTopMargin = 0; 94 private int mKeyguardLargeClockTopMargin = 0; 95 private int mKeyguardDateWeatherViewInvisibility = View.INVISIBLE; 96 private final ClockRegistry.ClockChangeListener mClockChangedListener; 97 98 private ViewGroup mStatusArea; 99 100 // If the SMARTSPACE flag is set, keyguard_slice_view is replaced by the following views. 101 private ViewGroup mDateWeatherView; 102 private View mWeatherView; 103 private View mSmartspaceView; 104 105 private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; 106 107 private boolean mShownOnSecondaryDisplay = false; 108 private boolean mOnlyClock = false; 109 private boolean mIsActiveDreamLockscreenHosted = false; 110 private FeatureFlags mFeatureFlags; 111 private KeyguardInteractor mKeyguardInteractor; 112 private final DelayableExecutor mUiExecutor; 113 private boolean mCanShowDoubleLineClock = true; 114 @VisibleForTesting 115 final Consumer<Boolean> mIsActiveDreamLockscreenHostedCallback = 116 (Boolean isLockscreenHosted) -> { 117 if (mIsActiveDreamLockscreenHosted == isLockscreenHosted) { 118 return; 119 } 120 mIsActiveDreamLockscreenHosted = isLockscreenHosted; 121 updateKeyguardStatusAreaVisibility(); 122 }; 123 private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) { 124 @Override 125 public void onChange(boolean change) { 126 updateDoubleLineClock(); 127 } 128 }; 129 private final ContentObserver mShowWeatherObserver = new ContentObserver(null) { 130 @Override 131 public void onChange(boolean change) { 132 setWeatherVisibility(); 133 } 134 }; 135 136 private final KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener 137 mKeyguardUnlockAnimationListener = 138 new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() { 139 @Override 140 public void onUnlockAnimationFinished() { 141 // For performance reasons, reset this once the unlock animation ends. 142 setClipChildrenForUnlock(true); 143 } 144 }; 145 146 @Inject KeyguardClockSwitchController( KeyguardClockSwitch keyguardClockSwitch, StatusBarStateController statusBarStateController, ClockRegistry clockRegistry, KeyguardSliceViewController keyguardSliceViewController, NotificationIconAreaController notificationIconAreaController, LockscreenSmartspaceController smartspaceController, KeyguardUnlockAnimationController keyguardUnlockAnimationController, SecureSettings secureSettings, @Main DelayableExecutor uiExecutor, DumpManager dumpManager, ClockEventController clockEventController, @KeyguardClockLog LogBuffer logBuffer, KeyguardInteractor keyguardInteractor, FeatureFlags featureFlags)147 public KeyguardClockSwitchController( 148 KeyguardClockSwitch keyguardClockSwitch, 149 StatusBarStateController statusBarStateController, 150 ClockRegistry clockRegistry, 151 KeyguardSliceViewController keyguardSliceViewController, 152 NotificationIconAreaController notificationIconAreaController, 153 LockscreenSmartspaceController smartspaceController, 154 KeyguardUnlockAnimationController keyguardUnlockAnimationController, 155 SecureSettings secureSettings, 156 @Main DelayableExecutor uiExecutor, 157 DumpManager dumpManager, 158 ClockEventController clockEventController, 159 @KeyguardClockLog LogBuffer logBuffer, 160 KeyguardInteractor keyguardInteractor, 161 FeatureFlags featureFlags) { 162 super(keyguardClockSwitch); 163 mStatusBarStateController = statusBarStateController; 164 mClockRegistry = clockRegistry; 165 mKeyguardSliceViewController = keyguardSliceViewController; 166 mNotificationIconAreaController = notificationIconAreaController; 167 mSmartspaceController = smartspaceController; 168 mSecureSettings = secureSettings; 169 mUiExecutor = uiExecutor; 170 mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; 171 mDumpManager = dumpManager; 172 mClockEventController = clockEventController; 173 mLogBuffer = logBuffer; 174 mView.setLogBuffer(mLogBuffer); 175 mFeatureFlags = featureFlags; 176 mKeyguardInteractor = keyguardInteractor; 177 178 mClockChangedListener = new ClockRegistry.ClockChangeListener() { 179 @Override 180 public void onCurrentClockChanged() { 181 setClock(mClockRegistry.createCurrentClock()); 182 } 183 @Override 184 public void onAvailableClocksChanged() { } 185 }; 186 } 187 188 /** 189 * When set, limits the information shown in an external display. 190 */ setShownOnSecondaryDisplay(boolean shownOnSecondaryDisplay)191 public void setShownOnSecondaryDisplay(boolean shownOnSecondaryDisplay) { 192 mShownOnSecondaryDisplay = shownOnSecondaryDisplay; 193 } 194 195 /** 196 * Mostly used for alternate displays, limit the information shown 197 * 198 * @deprecated use {@link KeyguardClockSwitchController#setShownOnSecondaryDisplay} 199 */ 200 @Deprecated setOnlyClock(boolean onlyClock)201 public void setOnlyClock(boolean onlyClock) { 202 mOnlyClock = onlyClock; 203 } 204 205 /** 206 * Used for status view to pass the screen offset from parent view 207 */ setLockscreenClockY(int clockY)208 public void setLockscreenClockY(int clockY) { 209 if (mView.screenOffsetYPadding != clockY) { 210 mView.screenOffsetYPadding = clockY; 211 mView.updateClockTargetRegions(); 212 } 213 } 214 215 /** 216 * Attach the controller to the view it relates to. 217 */ 218 @Override onInit()219 protected void onInit() { 220 mKeyguardSliceViewController.init(); 221 222 mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view); 223 mLargeClockFrame = mView.findViewById(R.id.lockscreen_clock_view_large); 224 225 if (!mOnlyClock) { 226 mDumpManager.unregisterDumpable(getClass().toString()); // unregister previous clocks 227 mDumpManager.registerDumpable(getClass().toString(), this); 228 } 229 230 if (mFeatureFlags.isEnabled(LOCKSCREEN_WALLPAPER_DREAM_ENABLED)) { 231 mStatusArea = mView.findViewById(R.id.keyguard_status_area); 232 collectFlow(mStatusArea, mKeyguardInteractor.isActiveDreamLockscreenHosted(), 233 mIsActiveDreamLockscreenHostedCallback); 234 } 235 } 236 hideSliceViewAndNotificationIconContainer()237 private void hideSliceViewAndNotificationIconContainer() { 238 View ksv = mView.findViewById(R.id.keyguard_slice_view); 239 ksv.setVisibility(View.GONE); 240 241 View nic = mView.findViewById( 242 R.id.left_aligned_notification_icon_container); 243 nic.setVisibility(View.GONE); 244 } 245 246 @Override onViewAttached()247 protected void onViewAttached() { 248 mClockRegistry.registerClockChangeListener(mClockChangedListener); 249 setClock(mClockRegistry.createCurrentClock()); 250 mClockEventController.registerListeners(mView); 251 mKeyguardSmallClockTopMargin = 252 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); 253 mKeyguardLargeClockTopMargin = 254 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); 255 mKeyguardDateWeatherViewInvisibility = 256 mView.getResources().getInteger(R.integer.keyguard_date_weather_view_invisibility); 257 258 if (mShownOnSecondaryDisplay) { 259 mView.setLargeClockOnSecondaryDisplay(true); 260 displayClock(LARGE, /* animate= */ false); 261 hideSliceViewAndNotificationIconContainer(); 262 return; 263 } 264 265 if (mOnlyClock) { 266 hideSliceViewAndNotificationIconContainer(); 267 return; 268 } 269 updateAodIcons(); 270 mStatusArea = mView.findViewById(R.id.keyguard_status_area); 271 272 mSecureSettings.registerContentObserverForUser( 273 Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 274 false, /* notifyForDescendants */ 275 mDoubleLineClockObserver, 276 UserHandle.USER_ALL 277 ); 278 279 mSecureSettings.registerContentObserverForUser( 280 Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED, 281 false, /* notifyForDescendants */ 282 mShowWeatherObserver, 283 UserHandle.USER_ALL 284 ); 285 updateDoubleLineClock(); 286 287 mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener( 288 mKeyguardUnlockAnimationListener); 289 290 if (mSmartspaceController.isEnabled()) { 291 View ksv = mView.findViewById(R.id.keyguard_slice_view); 292 int viewIndex = mStatusArea.indexOfChild(ksv); 293 ksv.setVisibility(View.GONE); 294 295 removeViewsFromStatusArea(); 296 addSmartspaceView(); 297 // TODO(b/261757708): add content observer for the Settings toggle and add/remove 298 // weather according to the Settings. 299 if (mSmartspaceController.isDateWeatherDecoupled()) { 300 addDateWeatherView(); 301 } 302 } 303 304 setDateWeatherVisibility(); 305 setWeatherVisibility(); 306 } 307 getNotificationIconAreaHeight()308 int getNotificationIconAreaHeight() { 309 return mNotificationIconAreaController.getHeight(); 310 } 311 312 @Override onViewDetached()313 protected void onViewDetached() { 314 mClockRegistry.unregisterClockChangeListener(mClockChangedListener); 315 mClockEventController.unregisterListeners(); 316 setClock(null); 317 318 mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver); 319 mSecureSettings.unregisterContentObserver(mShowWeatherObserver); 320 321 mKeyguardUnlockAnimationController.removeKeyguardUnlockAnimationListener( 322 mKeyguardUnlockAnimationListener); 323 } 324 onLocaleListChanged()325 void onLocaleListChanged() { 326 if (mSmartspaceController.isEnabled()) { 327 removeViewsFromStatusArea(); 328 addSmartspaceView(); 329 if (mSmartspaceController.isDateWeatherDecoupled()) { 330 mDateWeatherView.removeView(mWeatherView); 331 addDateWeatherView(); 332 setDateWeatherVisibility(); 333 setWeatherVisibility(); 334 } 335 } 336 } 337 addDateWeatherView()338 private void addDateWeatherView() { 339 mDateWeatherView = (ViewGroup) mSmartspaceController.buildAndConnectDateView(mView); 340 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 341 MATCH_PARENT, WRAP_CONTENT); 342 mStatusArea.addView(mDateWeatherView, 0, lp); 343 int startPadding = getContext().getResources().getDimensionPixelSize( 344 R.dimen.below_clock_padding_start); 345 int endPadding = getContext().getResources().getDimensionPixelSize( 346 R.dimen.below_clock_padding_end); 347 mDateWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0); 348 349 addWeatherView(); 350 } 351 addWeatherView()352 private void addWeatherView() { 353 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 354 WRAP_CONTENT, WRAP_CONTENT); 355 mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView); 356 // Place weather right after the date, before the extras 357 final int index = mDateWeatherView.getChildCount() == 0 ? 0 : 1; 358 mDateWeatherView.addView(mWeatherView, index, lp); 359 mWeatherView.setPaddingRelative(0, 0, 4, 0); 360 } 361 addSmartspaceView()362 private void addSmartspaceView() { 363 mSmartspaceView = mSmartspaceController.buildAndConnectView(mView); 364 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 365 MATCH_PARENT, WRAP_CONTENT); 366 mStatusArea.addView(mSmartspaceView, 0, lp); 367 int startPadding = getContext().getResources().getDimensionPixelSize( 368 R.dimen.below_clock_padding_start); 369 int endPadding = getContext().getResources().getDimensionPixelSize( 370 R.dimen.below_clock_padding_end); 371 mSmartspaceView.setPaddingRelative(startPadding, 0, endPadding, 0); 372 373 mKeyguardUnlockAnimationController.setLockscreenSmartspace(mSmartspaceView); 374 mView.setSmartspace(mSmartspaceView); 375 } 376 377 /** 378 * Apply dp changes on configuration change 379 */ onConfigChanged()380 public void onConfigChanged() { 381 mView.onConfigChanged(); 382 mKeyguardSmallClockTopMargin = 383 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin); 384 mKeyguardLargeClockTopMargin = 385 mView.getResources().getDimensionPixelSize(R.dimen.keyguard_large_clock_top_margin); 386 mKeyguardDateWeatherViewInvisibility = 387 mView.getResources().getInteger(R.integer.keyguard_date_weather_view_invisibility); 388 mView.updateClockTargetRegions(); 389 setDateWeatherVisibility(); 390 } 391 392 /** 393 * Enable or disable split shade center specific positioning 394 */ setSplitShadeCentered(boolean splitShadeCentered)395 public void setSplitShadeCentered(boolean splitShadeCentered) { 396 mView.setSplitShadeCentered(splitShadeCentered); 397 } 398 399 /** 400 * Set if the split shade is enabled 401 */ setSplitShadeEnabled(boolean splitShadeEnabled)402 public void setSplitShadeEnabled(boolean splitShadeEnabled) { 403 mSmartspaceController.setSplitShadeEnabled(splitShadeEnabled); 404 } 405 406 /** 407 * Set which clock should be displayed on the keyguard. The other one will be automatically 408 * hidden. 409 */ displayClock(@eyguardClockSwitch.ClockSize int clockSize, boolean animate)410 public void displayClock(@KeyguardClockSwitch.ClockSize int clockSize, boolean animate) { 411 if (!mCanShowDoubleLineClock && clockSize == KeyguardClockSwitch.LARGE) { 412 return; 413 } 414 415 mCurrentClockSize = clockSize; 416 setDateWeatherVisibility(); 417 418 ClockController clock = getClock(); 419 boolean appeared = mView.switchToClock(clockSize, animate); 420 if (clock != null && animate && appeared && clockSize == LARGE) { 421 mUiExecutor.executeDelayed(() -> clock.getLargeClock().getAnimations().enter(), 422 KeyguardClockSwitch.CLOCK_IN_START_DELAY_MILLIS); 423 } 424 } 425 426 /** 427 * Animates the clock view between folded and unfolded states 428 */ animateFoldToAod(float foldFraction)429 public void animateFoldToAod(float foldFraction) { 430 ClockController clock = getClock(); 431 if (clock != null) { 432 clock.getSmallClock().getAnimations().fold(foldFraction); 433 clock.getLargeClock().getAnimations().fold(foldFraction); 434 } 435 } 436 437 /** 438 * Refresh clock. Called in response to TIME_TICK broadcasts. 439 */ refresh()440 void refresh() { 441 mLogBuffer.log(TAG, LogLevel.INFO, "refresh"); 442 if (mSmartspaceController != null) { 443 mSmartspaceController.requestSmartspaceUpdate(); 444 } 445 ClockController clock = getClock(); 446 if (clock != null) { 447 clock.getSmallClock().getEvents().onTimeTick(); 448 clock.getLargeClock().getEvents().onTimeTick(); 449 } 450 } 451 452 /** 453 * Update position of the view, with optional animation. Move the slice view and the clock 454 * slightly towards the center in order to prevent burn-in. Y positioning occurs at the 455 * view parent level. The large clock view will scale instead of using x position offsets, to 456 * keep the clock centered. 457 */ updatePosition(int x, float scale, AnimationProperties props, boolean animate)458 void updatePosition(int x, float scale, AnimationProperties props, boolean animate) { 459 x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x; 460 461 PropertyAnimator.setProperty(mSmallClockFrame, AnimatableProperty.TRANSLATION_X, 462 x, props, animate); 463 PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X, 464 scale, props, animate); 465 PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_Y, 466 scale, props, animate); 467 468 if (mStatusArea != null) { 469 PropertyAnimator.setProperty(mStatusArea, KeyguardStatusAreaView.TRANSLATE_X_AOD, 470 x, props, animate); 471 } 472 } 473 474 /** 475 * Get y-bottom position of the currently visible clock on the keyguard. 476 * We can't directly getBottom() because clock changes positions in AOD for burn-in 477 */ getClockBottom(int statusBarHeaderHeight)478 int getClockBottom(int statusBarHeaderHeight) { 479 ClockController clock = getClock(); 480 if (clock == null) { 481 return 0; 482 } 483 484 if (mLargeClockFrame.getVisibility() == View.VISIBLE) { 485 // This gets the expected clock bottom if mLargeClockFrame had a top margin, but it's 486 // top margin only contributed to height and didn't move the top of the view (as this 487 // was the computation previously). As we no longer have a margin, we add this back 488 // into the computation manually. 489 int frameHeight = mLargeClockFrame.getHeight(); 490 int clockHeight = clock.getLargeClock().getView().getHeight(); 491 return frameHeight / 2 + clockHeight / 2 + mKeyguardLargeClockTopMargin / -2; 492 } else { 493 int clockHeight = clock.getSmallClock().getView().getHeight(); 494 return clockHeight + statusBarHeaderHeight + mKeyguardSmallClockTopMargin; 495 } 496 } 497 498 /** 499 * Get the height of the currently visible clock on the keyguard. 500 */ getClockHeight()501 int getClockHeight() { 502 ClockController clock = getClock(); 503 if (clock == null) { 504 return 0; 505 } 506 507 if (mLargeClockFrame.getVisibility() == View.VISIBLE) { 508 return clock.getLargeClock().getView().getHeight(); 509 } else { 510 return clock.getSmallClock().getView().getHeight(); 511 } 512 } 513 isClockTopAligned()514 boolean isClockTopAligned() { 515 return mLargeClockFrame.getVisibility() != View.VISIBLE; 516 } 517 updateAodIcons()518 private void updateAodIcons() { 519 NotificationIconContainer nic = (NotificationIconContainer) 520 mView.findViewById( 521 com.android.systemui.R.id.left_aligned_notification_icon_container); 522 mNotificationIconAreaController.setupAodIcons(nic); 523 } 524 setClock(ClockController clock)525 private void setClock(ClockController clock) { 526 if (clock != null && mLogBuffer != null) { 527 mLogBuffer.log(TAG, LogLevel.INFO, "New Clock"); 528 } 529 530 mClockEventController.setClock(clock); 531 mView.setClock(clock, mStatusBarStateController.getState()); 532 setDateWeatherVisibility(); 533 } 534 535 @Nullable getClock()536 public ClockController getClock() { 537 return mClockEventController.getClock(); 538 } 539 getCurrentLayoutDirection()540 private int getCurrentLayoutDirection() { 541 return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()); 542 } 543 updateDoubleLineClock()544 private void updateDoubleLineClock() { 545 mCanShowDoubleLineClock = mSecureSettings.getIntForUser( 546 Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1, 547 UserHandle.USER_CURRENT) != 0; 548 549 if (!mCanShowDoubleLineClock) { 550 mUiExecutor.execute(() -> displayClock(KeyguardClockSwitch.SMALL, /* animate */ true)); 551 } 552 } 553 setDateWeatherVisibility()554 private void setDateWeatherVisibility() { 555 if (mDateWeatherView != null) { 556 mUiExecutor.execute(() -> { 557 mDateWeatherView.setVisibility(clockHasCustomWeatherDataDisplay() 558 ? mKeyguardDateWeatherViewInvisibility 559 : View.VISIBLE); 560 }); 561 } 562 } 563 setWeatherVisibility()564 private void setWeatherVisibility() { 565 if (mWeatherView != null) { 566 mUiExecutor.execute(() -> { 567 mWeatherView.setVisibility( 568 mSmartspaceController.isWeatherEnabled() ? View.VISIBLE : View.GONE); 569 }); 570 } 571 } 572 updateKeyguardStatusAreaVisibility()573 private void updateKeyguardStatusAreaVisibility() { 574 if (mStatusArea != null) { 575 mUiExecutor.execute(() -> { 576 mStatusArea.setVisibility( 577 mIsActiveDreamLockscreenHosted ? View.INVISIBLE : View.VISIBLE); 578 }); 579 } 580 } 581 582 /** 583 * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of 584 * bounds during the unlock transition. 585 */ setClipChildrenForUnlock(boolean clip)586 private void setClipChildrenForUnlock(boolean clip) { 587 if (mStatusArea != null) { 588 mStatusArea.setClipChildren(clip); 589 } 590 } 591 592 @Override dump(@onNull PrintWriter pw, @NonNull String[] args)593 public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { 594 pw.println("currentClockSizeLarge: " + (mCurrentClockSize == LARGE)); 595 pw.println("mCanShowDoubleLineClock: " + mCanShowDoubleLineClock); 596 mView.dump(pw, args); 597 mClockRegistry.dump(pw, args); 598 ClockController clock = getClock(); 599 if (clock != null) { 600 clock.dump(pw); 601 } 602 final RegionSampler smallRegionSampler = mClockEventController.getSmallRegionSampler(); 603 if (smallRegionSampler != null) { 604 smallRegionSampler.dump(pw); 605 } 606 final RegionSampler largeRegionSampler = mClockEventController.getLargeRegionSampler(); 607 if (largeRegionSampler != null) { 608 largeRegionSampler.dump(pw); 609 } 610 } 611 612 /** Returns true if the clock handles the display of weather information */ clockHasCustomWeatherDataDisplay()613 private boolean clockHasCustomWeatherDataDisplay() { 614 ClockController clock = getClock(); 615 if (clock == null) { 616 return false; 617 } 618 619 return ((mCurrentClockSize == LARGE) ? clock.getLargeClock() : clock.getSmallClock()) 620 .getConfig().getHasCustomWeatherDataDisplay(); 621 } 622 removeViewsFromStatusArea()623 private void removeViewsFromStatusArea() { 624 for (int i = mStatusArea.getChildCount() - 1; i >= 0; i--) { 625 final View childView = mStatusArea.getChildAt(i); 626 if (childView.getTag(R.id.tag_smartspace_view) != null) { 627 mStatusArea.removeViewAt(i); 628 } 629 } 630 } 631 } 632