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 android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.content.res.Resources; 24 import android.graphics.Color; 25 import android.icu.text.NumberFormat; 26 27 import androidx.annotation.VisibleForTesting; 28 29 import com.android.settingslib.Utils; 30 import com.android.systemui.R; 31 import com.android.systemui.broadcast.BroadcastDispatcher; 32 import com.android.systemui.dagger.qualifiers.Main; 33 import com.android.systemui.plugins.statusbar.StatusBarStateController; 34 import com.android.systemui.statusbar.policy.BatteryController; 35 import com.android.systemui.util.ViewController; 36 37 import java.util.Locale; 38 import java.util.Objects; 39 import java.util.TimeZone; 40 41 /** 42 * Controller for an AnimatableClockView on the keyguard. Instantiated by 43 * {@link KeyguardClockSwitchController}. 44 */ 45 public class AnimatableClockController extends ViewController<AnimatableClockView> { 46 private static final int FORMAT_NUMBER = 1234567890; 47 48 private final StatusBarStateController mStatusBarStateController; 49 private final BroadcastDispatcher mBroadcastDispatcher; 50 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 51 private final BatteryController mBatteryController; 52 private final int mDozingColor = Color.WHITE; 53 private int mLockScreenColor; 54 55 private boolean mIsDozing; 56 private boolean mIsCharging; 57 private float mDozeAmount; 58 boolean mKeyguardShowing; 59 private Locale mLocale; 60 61 private final NumberFormat mBurmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my")); 62 private final String mBurmeseNumerals; 63 private final float mBurmeseLineSpacing; 64 private final float mDefaultLineSpacing; 65 AnimatableClockController( AnimatableClockView view, StatusBarStateController statusBarStateController, BroadcastDispatcher broadcastDispatcher, BatteryController batteryController, KeyguardUpdateMonitor keyguardUpdateMonitor, @Main Resources resources )66 public AnimatableClockController( 67 AnimatableClockView view, 68 StatusBarStateController statusBarStateController, 69 BroadcastDispatcher broadcastDispatcher, 70 BatteryController batteryController, 71 KeyguardUpdateMonitor keyguardUpdateMonitor, 72 @Main Resources resources 73 ) { 74 super(view); 75 mStatusBarStateController = statusBarStateController; 76 mBroadcastDispatcher = broadcastDispatcher; 77 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 78 mBatteryController = batteryController; 79 80 mBurmeseNumerals = mBurmeseNf.format(FORMAT_NUMBER); 81 mBurmeseLineSpacing = resources.getFloat( 82 R.dimen.keyguard_clock_line_spacing_scale_burmese); 83 mDefaultLineSpacing = resources.getFloat( 84 R.dimen.keyguard_clock_line_spacing_scale); 85 } 86 reset()87 private void reset() { 88 mView.animateDoze(mIsDozing, false); 89 } 90 91 private final BatteryController.BatteryStateChangeCallback mBatteryCallback = 92 new BatteryController.BatteryStateChangeCallback() { 93 @Override 94 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { 95 if (mKeyguardShowing && !mIsCharging && charging) { 96 mView.animateCharge(mStatusBarStateController::isDozing); 97 } 98 mIsCharging = charging; 99 } 100 }; 101 102 private final BroadcastReceiver mLocaleBroadcastReceiver = new BroadcastReceiver() { 103 @Override 104 public void onReceive(Context context, Intent intent) { 105 updateLocale(); 106 } 107 }; 108 109 private final StatusBarStateController.StateListener mStatusBarStateListener = 110 new StatusBarStateController.StateListener() { 111 @Override 112 public void onDozeAmountChanged(float linear, float eased) { 113 boolean noAnimation = (mDozeAmount == 0f && linear == 1f) 114 || (mDozeAmount == 1f && linear == 0f); 115 boolean isDozing = linear > mDozeAmount; 116 mDozeAmount = linear; 117 if (mIsDozing != isDozing) { 118 mIsDozing = isDozing; 119 mView.animateDoze(mIsDozing, !noAnimation); 120 } 121 } 122 }; 123 124 private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = 125 new KeyguardUpdateMonitorCallback() { 126 @Override 127 public void onKeyguardVisibilityChanged(boolean showing) { 128 mKeyguardShowing = showing; 129 if (!mKeyguardShowing) { 130 // reset state (ie: after weight animations) 131 reset(); 132 } 133 } 134 }; 135 136 @Override onInit()137 protected void onInit() { 138 mIsDozing = mStatusBarStateController.isDozing(); 139 } 140 141 @Override onViewAttached()142 protected void onViewAttached() { 143 updateLocale(); 144 mBroadcastDispatcher.registerReceiver(mLocaleBroadcastReceiver, 145 new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); 146 mDozeAmount = mStatusBarStateController.getDozeAmount(); 147 mIsDozing = mStatusBarStateController.isDozing() || mDozeAmount != 0; 148 mBatteryController.addCallback(mBatteryCallback); 149 mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); 150 151 mStatusBarStateController.addCallback(mStatusBarStateListener); 152 153 refreshTime(); 154 initColors(); 155 mView.animateDoze(mIsDozing, false); 156 } 157 158 @Override onViewDetached()159 protected void onViewDetached() { 160 mBroadcastDispatcher.unregisterReceiver(mLocaleBroadcastReceiver); 161 mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback); 162 mBatteryController.removeCallback(mBatteryCallback); 163 mStatusBarStateController.removeCallback(mStatusBarStateListener); 164 } 165 166 /** Animate the clock appearance */ animateAppear()167 public void animateAppear() { 168 if (!mIsDozing) mView.animateAppearOnLockscreen(); 169 } 170 171 /** 172 * Updates the time for the view. 173 */ refreshTime()174 public void refreshTime() { 175 mView.refreshTime(); 176 } 177 178 /** 179 * Updates the timezone for the view. 180 */ onTimeZoneChanged(TimeZone timeZone)181 public void onTimeZoneChanged(TimeZone timeZone) { 182 mView.onTimeZoneChanged(timeZone); 183 } 184 185 /** 186 * Trigger a time format update 187 */ refreshFormat()188 public void refreshFormat() { 189 mView.refreshFormat(); 190 } 191 192 /** 193 * Return locallly stored dozing state. 194 */ 195 @VisibleForTesting isDozing()196 public boolean isDozing() { 197 return mIsDozing; 198 } 199 updateLocale()200 private void updateLocale() { 201 Locale currLocale = Locale.getDefault(); 202 if (!Objects.equals(currLocale, mLocale)) { 203 mLocale = currLocale; 204 NumberFormat nf = NumberFormat.getInstance(mLocale); 205 if (nf.format(FORMAT_NUMBER).equals(mBurmeseNumerals)) { 206 mView.setLineSpacingScale(mBurmeseLineSpacing); 207 } else { 208 mView.setLineSpacingScale(mDefaultLineSpacing); 209 } 210 mView.refreshFormat(); 211 } 212 } 213 initColors()214 private void initColors() { 215 mLockScreenColor = Utils.getColorAttrDefaultColor(getContext(), 216 com.android.systemui.R.attr.wallpaperTextColorAccent); 217 mView.setColors(mDozingColor, mLockScreenColor); 218 mView.animateDoze(mIsDozing, false); 219 } 220 } 221