1 /*
2  * Copyright (C) 2015 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 android.animation.ArgbEvaluator;
20 import android.animation.ValueAnimator;
21 import android.content.Context;
22 import android.content.res.ColorStateList;
23 import android.content.res.Resources;
24 import android.graphics.Color;
25 import android.graphics.Rect;
26 import android.graphics.drawable.Icon;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.os.SystemClock;
30 import android.os.UserHandle;
31 import android.text.TextUtils;
32 import android.util.ArraySet;
33 import android.util.TypedValue;
34 import android.view.Gravity;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.widget.ImageView;
38 import android.widget.LinearLayout;
39 import android.widget.TextView;
40 import com.android.internal.statusbar.StatusBarIcon;
41 import com.android.systemui.BatteryMeterView;
42 import com.android.systemui.FontSizeUtils;
43 import com.android.systemui.Interpolators;
44 import com.android.systemui.R;
45 import com.android.systemui.SystemUIFactory;
46 import com.android.systemui.statusbar.NotificationData;
47 import com.android.systemui.statusbar.SignalClusterView;
48 import com.android.systemui.statusbar.StatusBarIconView;
49 import com.android.systemui.tuner.TunerService;
50 import com.android.systemui.tuner.TunerService.Tunable;
51 
52 import java.io.PrintWriter;
53 import java.util.ArrayList;
54 
55 /**
56  * Controls everything regarding the icons in the status bar and on Keyguard, including, but not
57  * limited to: notification icons, signal cluster, additional status icons, and clock in the status
58  * bar.
59  */
60 public class StatusBarIconController extends StatusBarIconList implements Tunable {
61 
62     public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
63     public static final String ICON_BLACKLIST = "icon_blacklist";
64     public static final int DEFAULT_ICON_TINT = Color.WHITE;
65 
66     private Context mContext;
67     private PhoneStatusBar mPhoneStatusBar;
68     private DemoStatusIcons mDemoStatusIcons;
69 
70     private LinearLayout mSystemIconArea;
71     private LinearLayout mStatusIcons;
72     private SignalClusterView mSignalCluster;
73     private LinearLayout mStatusIconsKeyguard;
74 
75     private NotificationIconAreaController mNotificationIconAreaController;
76     private View mNotificationIconAreaInner;
77 
78     private BatteryMeterView mBatteryMeterView;
79     private BatteryMeterView mBatteryMeterViewKeyguard;
80     private TextView mClock;
81 
82     private int mIconSize;
83     private int mIconHPadding;
84 
85     private int mIconTint = DEFAULT_ICON_TINT;
86     private float mDarkIntensity;
87     private final Rect mTintArea = new Rect();
88     private static final Rect sTmpRect = new Rect();
89     private static final int[] sTmpInt2 = new int[2];
90 
91     private boolean mTransitionPending;
92     private boolean mTintChangePending;
93     private float mPendingDarkIntensity;
94     private ValueAnimator mTintAnimator;
95 
96     private int mDarkModeIconColorSingleTone;
97     private int mLightModeIconColorSingleTone;
98 
99     private final Handler mHandler;
100     private boolean mTransitionDeferring;
101     private long mTransitionDeferringStartTime;
102     private long mTransitionDeferringDuration;
103 
104     private final ArraySet<String> mIconBlacklist = new ArraySet<>();
105 
106     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
107         @Override
108         public void run() {
109             mTransitionDeferring = false;
110         }
111     };
112 
StatusBarIconController(Context context, View statusBar, View keyguardStatusBar, PhoneStatusBar phoneStatusBar)113     public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
114             PhoneStatusBar phoneStatusBar) {
115         mContext = context;
116         mPhoneStatusBar = phoneStatusBar;
117         mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
118         mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
119         mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
120 
121         mNotificationIconAreaController = SystemUIFactory.getInstance()
122                 .createNotificationIconAreaController(context, phoneStatusBar);
123         mNotificationIconAreaInner =
124                 mNotificationIconAreaController.getNotificationInnerAreaView();
125 
126         ViewGroup notificationIconArea =
127                 (ViewGroup) statusBar.findViewById(R.id.notification_icon_area);
128         notificationIconArea.addView(mNotificationIconAreaInner);
129 
130         mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
131 
132         mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
133         mBatteryMeterViewKeyguard = (BatteryMeterView) keyguardStatusBar.findViewById(R.id.battery);
134         scaleBatteryMeterViews(context);
135 
136         mClock = (TextView) statusBar.findViewById(R.id.clock);
137         mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
138         mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
139         mHandler = new Handler();
140         defineSlots();
141         loadDimens();
142 
143         TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
144     }
145 
setSignalCluster(SignalClusterView signalCluster)146     public void setSignalCluster(SignalClusterView signalCluster) {
147         mSignalCluster = signalCluster;
148     }
149 
150     /**
151      * Looks up the scale factor for status bar icons and scales the battery view by that amount.
152      */
scaleBatteryMeterViews(Context context)153     private void scaleBatteryMeterViews(Context context) {
154         Resources res = context.getResources();
155         TypedValue typedValue = new TypedValue();
156 
157         res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
158         float iconScaleFactor = typedValue.getFloat();
159 
160         int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
161         int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
162         int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
163 
164         LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
165                 (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
166         scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom);
167 
168         mBatteryMeterView.setLayoutParams(scaledLayoutParams);
169         mBatteryMeterViewKeyguard.setLayoutParams(scaledLayoutParams);
170     }
171 
172     @Override
onTuningChanged(String key, String newValue)173     public void onTuningChanged(String key, String newValue) {
174         if (!ICON_BLACKLIST.equals(key)) {
175             return;
176         }
177         mIconBlacklist.clear();
178         mIconBlacklist.addAll(getIconBlacklist(newValue));
179         ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
180         // Get all the current views.
181         for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
182             views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
183         }
184         // Remove all the icons.
185         for (int i = views.size() - 1; i >= 0; i--) {
186             removeIcon(views.get(i).getSlot());
187         }
188         // Add them all back
189         for (int i = 0; i < views.size(); i++) {
190             setIcon(views.get(i).getSlot(), views.get(i).getStatusBarIcon());
191         }
192     }
loadDimens()193     private void loadDimens() {
194         mIconSize = mContext.getResources().getDimensionPixelSize(
195                 com.android.internal.R.dimen.status_bar_icon_size);
196         mIconHPadding = mContext.getResources().getDimensionPixelSize(
197                 R.dimen.status_bar_icon_padding);
198     }
199 
defineSlots()200     public void defineSlots() {
201         defineSlots(mContext.getResources().getStringArray(
202                 com.android.internal.R.array.config_statusBarIcons));
203     }
204 
addSystemIcon(int index, StatusBarIcon icon)205     private void addSystemIcon(int index, StatusBarIcon icon) {
206         String slot = getSlot(index);
207         int viewIndex = getViewIndex(index);
208         boolean blocked = mIconBlacklist.contains(slot);
209         StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
210         view.set(icon);
211 
212         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
213                 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
214         lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
215         mStatusIcons.addView(view, viewIndex, lp);
216 
217         view = new StatusBarIconView(mContext, slot, null, blocked);
218         view.set(icon);
219         mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
220                 ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
221         applyIconTint();
222     }
223 
setIcon(String slot, int resourceId, CharSequence contentDescription)224     public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
225         int index = getSlotIndex(slot);
226         StatusBarIcon icon = getIcon(index);
227         if (icon == null) {
228             icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
229                     Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
230             setIcon(slot, icon);
231         } else {
232             icon.icon = Icon.createWithResource(mContext, resourceId);
233             icon.contentDescription = contentDescription;
234             handleSet(index, icon);
235         }
236     }
237 
setExternalIcon(String slot)238     public void setExternalIcon(String slot) {
239         int viewIndex = getViewIndex(getSlotIndex(slot));
240         int height = mContext.getResources().getDimensionPixelSize(
241                 R.dimen.status_bar_icon_drawing_size);
242         ImageView imageView = (ImageView) mStatusIcons.getChildAt(viewIndex);
243         imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
244         imageView.setAdjustViewBounds(true);
245         setHeightAndCenter(imageView, height);
246         imageView = (ImageView) mStatusIconsKeyguard.getChildAt(viewIndex);
247         imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
248         imageView.setAdjustViewBounds(true);
249         setHeightAndCenter(imageView, height);
250     }
251 
setHeightAndCenter(ImageView imageView, int height)252     private void setHeightAndCenter(ImageView imageView, int height) {
253         ViewGroup.LayoutParams params = imageView.getLayoutParams();
254         params.height = height;
255         if (params instanceof LinearLayout.LayoutParams) {
256             ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
257         }
258         imageView.setLayoutParams(params);
259     }
260 
setIcon(String slot, StatusBarIcon icon)261     public void setIcon(String slot, StatusBarIcon icon) {
262         setIcon(getSlotIndex(slot), icon);
263     }
264 
removeIcon(String slot)265     public void removeIcon(String slot) {
266         int index = getSlotIndex(slot);
267         removeIcon(index);
268     }
269 
setIconVisibility(String slot, boolean visibility)270     public void setIconVisibility(String slot, boolean visibility) {
271         int index = getSlotIndex(slot);
272         StatusBarIcon icon = getIcon(index);
273         if (icon == null || icon.visible == visibility) {
274             return;
275         }
276         icon.visible = visibility;
277         handleSet(index, icon);
278     }
279 
280     @Override
removeIcon(int index)281     public void removeIcon(int index) {
282         if (getIcon(index) == null) {
283             return;
284         }
285         super.removeIcon(index);
286         int viewIndex = getViewIndex(index);
287         mStatusIcons.removeViewAt(viewIndex);
288         mStatusIconsKeyguard.removeViewAt(viewIndex);
289     }
290 
291     @Override
setIcon(int index, StatusBarIcon icon)292     public void setIcon(int index, StatusBarIcon icon) {
293         if (icon == null) {
294             removeIcon(index);
295             return;
296         }
297         boolean isNew = getIcon(index) == null;
298         super.setIcon(index, icon);
299         if (isNew) {
300             addSystemIcon(index, icon);
301         } else {
302             handleSet(index, icon);
303         }
304     }
305 
handleSet(int index, StatusBarIcon icon)306     private void handleSet(int index, StatusBarIcon icon) {
307         int viewIndex = getViewIndex(index);
308         StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
309         view.set(icon);
310         view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
311         view.set(icon);
312         applyIconTint();
313     }
314 
updateNotificationIcons(NotificationData notificationData)315     public void updateNotificationIcons(NotificationData notificationData) {
316         mNotificationIconAreaController.updateNotificationIcons(notificationData);
317     }
318 
hideSystemIconArea(boolean animate)319     public void hideSystemIconArea(boolean animate) {
320         animateHide(mSystemIconArea, animate);
321     }
322 
showSystemIconArea(boolean animate)323     public void showSystemIconArea(boolean animate) {
324         animateShow(mSystemIconArea, animate);
325     }
326 
hideNotificationIconArea(boolean animate)327     public void hideNotificationIconArea(boolean animate) {
328         animateHide(mNotificationIconAreaInner, animate);
329     }
330 
showNotificationIconArea(boolean animate)331     public void showNotificationIconArea(boolean animate) {
332         animateShow(mNotificationIconAreaInner, animate);
333     }
334 
setClockVisibility(boolean visible)335     public void setClockVisibility(boolean visible) {
336         mClock.setVisibility(visible ? View.VISIBLE : View.GONE);
337     }
338 
dump(PrintWriter pw)339     public void dump(PrintWriter pw) {
340         int N = mStatusIcons.getChildCount();
341         pw.println("  system icons: " + N);
342         for (int i=0; i<N; i++) {
343             StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
344             pw.println("    [" + i + "] icon=" + ic);
345         }
346     }
347 
dispatchDemoCommand(String command, Bundle args)348     public void dispatchDemoCommand(String command, Bundle args) {
349         if (mDemoStatusIcons == null) {
350             mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize);
351         }
352         mDemoStatusIcons.dispatchDemoCommand(command, args);
353     }
354 
355     /**
356      * Hides a view.
357      */
animateHide(final View v, boolean animate)358     private void animateHide(final View v, boolean animate) {
359         v.animate().cancel();
360         if (!animate) {
361             v.setAlpha(0f);
362             v.setVisibility(View.INVISIBLE);
363             return;
364         }
365         v.animate()
366                 .alpha(0f)
367                 .setDuration(160)
368                 .setStartDelay(0)
369                 .setInterpolator(Interpolators.ALPHA_OUT)
370                 .withEndAction(new Runnable() {
371                     @Override
372                     public void run() {
373                         v.setVisibility(View.INVISIBLE);
374                     }
375                 });
376     }
377 
378     /**
379      * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
380      */
animateShow(View v, boolean animate)381     private void animateShow(View v, boolean animate) {
382         v.animate().cancel();
383         v.setVisibility(View.VISIBLE);
384         if (!animate) {
385             v.setAlpha(1f);
386             return;
387         }
388         v.animate()
389                 .alpha(1f)
390                 .setDuration(320)
391                 .setInterpolator(Interpolators.ALPHA_IN)
392                 .setStartDelay(50)
393 
394                 // We need to clean up any pending end action from animateHide if we call
395                 // both hide and show in the same frame before the animation actually gets started.
396                 // cancel() doesn't really remove the end action.
397                 .withEndAction(null);
398 
399         // Synchronize the motion with the Keyguard fading if necessary.
400         if (mPhoneStatusBar.isKeyguardFadingAway()) {
401             v.animate()
402                     .setDuration(mPhoneStatusBar.getKeyguardFadingAwayDuration())
403                     .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
404                     .setStartDelay(mPhoneStatusBar.getKeyguardFadingAwayDelay())
405                     .start();
406         }
407     }
408 
409     /**
410      * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
411      *
412      * @param darkArea the area in which icons should change it's tint, in logical screen
413      *                 coordinates
414      */
setIconsDarkArea(Rect darkArea)415     public void setIconsDarkArea(Rect darkArea) {
416         if (darkArea == null && mTintArea.isEmpty()) {
417             return;
418         }
419         if (darkArea == null) {
420             mTintArea.setEmpty();
421         } else {
422             mTintArea.set(darkArea);
423         }
424         applyIconTint();
425         mNotificationIconAreaController.setTintArea(darkArea);
426     }
427 
setIconsDark(boolean dark, boolean animate)428     public void setIconsDark(boolean dark, boolean animate) {
429         if (!animate) {
430             setIconTintInternal(dark ? 1.0f : 0.0f);
431         } else if (mTransitionPending) {
432             deferIconTintChange(dark ? 1.0f : 0.0f);
433         } else if (mTransitionDeferring) {
434             animateIconTint(dark ? 1.0f : 0.0f,
435                     Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
436                     mTransitionDeferringDuration);
437         } else {
438             animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
439         }
440     }
441 
animateIconTint(float targetDarkIntensity, long delay, long duration)442     private void animateIconTint(float targetDarkIntensity, long delay,
443             long duration) {
444         if (mTintAnimator != null) {
445             mTintAnimator.cancel();
446         }
447         if (mDarkIntensity == targetDarkIntensity) {
448             return;
449         }
450         mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
451         mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
452             @Override
453             public void onAnimationUpdate(ValueAnimator animation) {
454                 setIconTintInternal((Float) animation.getAnimatedValue());
455             }
456         });
457         mTintAnimator.setDuration(duration);
458         mTintAnimator.setStartDelay(delay);
459         mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
460         mTintAnimator.start();
461     }
462 
setIconTintInternal(float darkIntensity)463     private void setIconTintInternal(float darkIntensity) {
464         mDarkIntensity = darkIntensity;
465         mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
466                 mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
467         mNotificationIconAreaController.setIconTint(mIconTint);
468         applyIconTint();
469     }
470 
deferIconTintChange(float darkIntensity)471     private void deferIconTintChange(float darkIntensity) {
472         if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
473             return;
474         }
475         mTintChangePending = true;
476         mPendingDarkIntensity = darkIntensity;
477     }
478 
479     /**
480      * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
481      *         the screen {@param tintArea} in which to apply that tint
482      */
getTint(Rect tintArea, View view, int color)483     public static int getTint(Rect tintArea, View view, int color) {
484         if (isInArea(tintArea, view)) {
485             return color;
486         } else {
487             return DEFAULT_ICON_TINT;
488         }
489     }
490 
491     /**
492      * @return the dark intensity to apply to {@param view} depending on the desired dark
493      *         {@param intensity} and the screen {@param tintArea} in which to apply that intensity
494      */
getDarkIntensity(Rect tintArea, View view, float intensity)495     public static float getDarkIntensity(Rect tintArea, View view, float intensity) {
496         if (isInArea(tintArea, view)) {
497             return intensity;
498         } else {
499             return 0f;
500         }
501     }
502 
503     /**
504      * @return true if more than half of the {@param view} area are in {@param area}, false
505      *         otherwise
506      */
isInArea(Rect area, View view)507     private static boolean isInArea(Rect area, View view) {
508         if (area.isEmpty()) {
509             return true;
510         }
511         sTmpRect.set(area);
512         view.getLocationOnScreen(sTmpInt2);
513         int left = sTmpInt2[0];
514 
515         int intersectStart = Math.max(left, area.left);
516         int intersectEnd = Math.min(left + view.getWidth(), area.right);
517         int intersectAmount = Math.max(0, intersectEnd - intersectStart);
518 
519         boolean coversFullStatusBar = area.top <= 0;
520         boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
521         return majorityOfWidth && coversFullStatusBar;
522     }
523 
applyIconTint()524     private void applyIconTint() {
525         for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
526             StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
527             v.setImageTintList(ColorStateList.valueOf(getTint(mTintArea, v, mIconTint)));
528         }
529         mSignalCluster.setIconTint(mIconTint, mDarkIntensity, mTintArea);
530         mBatteryMeterView.setDarkIntensity(
531                 isInArea(mTintArea, mBatteryMeterView) ? mDarkIntensity : 0);
532         mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
533     }
534 
appTransitionPending()535     public void appTransitionPending() {
536         mTransitionPending = true;
537     }
538 
appTransitionCancelled()539     public void appTransitionCancelled() {
540         if (mTransitionPending && mTintChangePending) {
541             mTintChangePending = false;
542             animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
543         }
544         mTransitionPending = false;
545     }
546 
appTransitionStarting(long startTime, long duration)547     public void appTransitionStarting(long startTime, long duration) {
548         if (mTransitionPending && mTintChangePending) {
549             mTintChangePending = false;
550             animateIconTint(mPendingDarkIntensity,
551                     Math.max(0, startTime - SystemClock.uptimeMillis()),
552                     duration);
553 
554         } else if (mTransitionPending) {
555 
556             // If we don't have a pending tint change yet, the change might come in the future until
557             // startTime is reached.
558             mTransitionDeferring = true;
559             mTransitionDeferringStartTime = startTime;
560             mTransitionDeferringDuration = duration;
561             mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
562             mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
563         }
564         mTransitionPending = false;
565     }
566 
getIconBlacklist(String blackListStr)567     public static ArraySet<String> getIconBlacklist(String blackListStr) {
568         ArraySet<String> ret = new ArraySet<String>();
569         if (blackListStr == null) {
570             blackListStr = "rotate,headset";
571         }
572         String[] blacklist = blackListStr.split(",");
573         for (String slot : blacklist) {
574             if (!TextUtils.isEmpty(slot)) {
575                 ret.add(slot);
576             }
577         }
578         return ret;
579     }
580 
onDensityOrFontScaleChanged()581     public void onDensityOrFontScaleChanged() {
582         loadDimens();
583         mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
584         updateClock();
585         for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
586             View child = mStatusIcons.getChildAt(i);
587             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
588                     ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
589             lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
590             child.setLayoutParams(lp);
591         }
592         for (int i = 0; i < mStatusIconsKeyguard.getChildCount(); i++) {
593             View child = mStatusIconsKeyguard.getChildAt(i);
594             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
595                     ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
596             child.setLayoutParams(lp);
597         }
598         scaleBatteryMeterViews(mContext);
599     }
600 
updateClock()601     private void updateClock() {
602         FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size);
603         mClock.setPaddingRelative(
604                 mContext.getResources().getDimensionPixelSize(
605                         R.dimen.status_bar_clock_starting_padding),
606                 0,
607                 mContext.getResources().getDimensionPixelSize(
608                         R.dimen.status_bar_clock_end_padding),
609                 0);
610     }
611 }
612