Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2017 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.content.Context;
     20 import android.graphics.drawable.Icon;
     21 import android.os.Bundle;
     22 import android.os.UserHandle;
     23 import android.util.ArraySet;
     24 import android.view.ViewGroup;
     25 import android.widget.LinearLayout;
     26 
     27 import com.android.internal.statusbar.StatusBarIcon;
     28 import com.android.systemui.Dependency;
     29 import com.android.systemui.Dumpable;
     30 import com.android.systemui.R;
     31 import com.android.systemui.SysUiServiceProvider;
     32 import com.android.systemui.statusbar.CommandQueue;
     33 import com.android.systemui.statusbar.StatusBarIconView;
     34 import com.android.systemui.statusbar.policy.ConfigurationController;
     35 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
     36 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
     37 import com.android.systemui.statusbar.policy.IconLogger;
     38 import com.android.systemui.tuner.TunerService;
     39 import com.android.systemui.tuner.TunerService.Tunable;
     40 
     41 import java.io.FileDescriptor;
     42 import java.io.PrintWriter;
     43 import java.util.ArrayList;
     44 
     45 /**
     46  * Receives the callbacks from CommandQueue related to icons and tracks the state of
     47  * all the icons. Dispatches this state to any IconManagers that are currently
     48  * registered with it.
     49  */
     50 public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
     51         ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
     52 
     53     private final DarkIconDispatcher mDarkIconDispatcher;
     54 
     55     private Context mContext;
     56     private DemoStatusIcons mDemoStatusIcons;
     57 
     58     private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
     59 
     60     private final ArraySet<String> mIconBlacklist = new ArraySet<>();
     61     private final IconLogger mIconLogger = Dependency.get(IconLogger.class);
     62 
     63     public StatusBarIconControllerImpl(Context context) {
     64         super(context.getResources().getStringArray(
     65                 com.android.internal.R.array.config_statusBarIcons));
     66         Dependency.get(ConfigurationController.class).addCallback(this);
     67         mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
     68         mContext = context;
     69 
     70         loadDimens();
     71 
     72         SysUiServiceProvider.getComponent(context, CommandQueue.class)
     73                 .addCallbacks(this);
     74         Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
     75     }
     76 
     77     @Override
     78     public void addIconGroup(IconManager group) {
     79         mIconGroups.add(group);
     80         for (int i = 0; i < mIcons.size(); i++) {
     81             StatusBarIcon icon = mIcons.get(i);
     82             if (icon != null) {
     83                 String slot = mSlots.get(i);
     84                 boolean blocked = mIconBlacklist.contains(slot);
     85                 group.onIconAdded(getViewIndex(getSlotIndex(slot)), slot, blocked, icon);
     86             }
     87         }
     88     }
     89 
     90     @Override
     91     public void removeIconGroup(IconManager group) {
     92         group.destroy();
     93         mIconGroups.remove(group);
     94     }
     95 
     96     @Override
     97     public void onTuningChanged(String key, String newValue) {
     98         if (!ICON_BLACKLIST.equals(key)) {
     99             return;
    100         }
    101         mIconBlacklist.clear();
    102         mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
    103         ArrayList<StatusBarIcon> current = new ArrayList<>(mIcons);
    104         ArrayList<String> currentSlots = new ArrayList<>(mSlots);
    105         // Remove all the icons.
    106         for (int i = current.size() - 1; i >= 0; i--) {
    107             removeIcon(currentSlots.get(i));
    108         }
    109         // Add them all back
    110         for (int i = 0; i < current.size(); i++) {
    111             setIcon(currentSlots.get(i), current.get(i));
    112         }
    113     }
    114 
    115     private void loadDimens() {
    116     }
    117 
    118     private void addSystemIcon(int index, StatusBarIcon icon) {
    119         String slot = getSlot(index);
    120         int viewIndex = getViewIndex(index);
    121         boolean blocked = mIconBlacklist.contains(slot);
    122 
    123         mIconLogger.onIconVisibility(getSlot(index), icon.visible);
    124         mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, icon));
    125     }
    126 
    127     @Override
    128     public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
    129         int index = getSlotIndex(slot);
    130         StatusBarIcon icon = getIcon(index);
    131         if (icon == null) {
    132             icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
    133                     Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
    134             setIcon(slot, icon);
    135         } else {
    136             icon.icon = Icon.createWithResource(mContext, resourceId);
    137             icon.contentDescription = contentDescription;
    138             handleSet(index, icon);
    139         }
    140     }
    141 
    142     @Override
    143     public void setExternalIcon(String slot) {
    144         int viewIndex = getViewIndex(getSlotIndex(slot));
    145         int height = mContext.getResources().getDimensionPixelSize(
    146                 R.dimen.status_bar_icon_drawing_size);
    147         mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
    148     }
    149 
    150     @Override
    151     public void setIcon(String slot, StatusBarIcon icon) {
    152         setIcon(getSlotIndex(slot), icon);
    153     }
    154 
    155     @Override
    156     public void removeIcon(String slot) {
    157         int index = getSlotIndex(slot);
    158         removeIcon(index);
    159     }
    160 
    161     public void setIconVisibility(String slot, boolean visibility) {
    162         int index = getSlotIndex(slot);
    163         StatusBarIcon icon = getIcon(index);
    164         if (icon == null || icon.visible == visibility) {
    165             return;
    166         }
    167         icon.visible = visibility;
    168         handleSet(index, icon);
    169     }
    170 
    171     @Override
    172     public void removeIcon(int index) {
    173         if (getIcon(index) == null) {
    174             return;
    175         }
    176         mIconLogger.onIconHidden(getSlot(index));
    177         super.removeIcon(index);
    178         int viewIndex = getViewIndex(index);
    179         mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
    180     }
    181 
    182     @Override
    183     public void setIcon(int index, StatusBarIcon icon) {
    184         if (icon == null) {
    185             removeIcon(index);
    186             return;
    187         }
    188         boolean isNew = getIcon(index) == null;
    189         super.setIcon(index, icon);
    190         if (isNew) {
    191             addSystemIcon(index, icon);
    192         } else {
    193             handleSet(index, icon);
    194         }
    195     }
    196 
    197     private void handleSet(int index, StatusBarIcon icon) {
    198         int viewIndex = getViewIndex(index);
    199         mIconLogger.onIconVisibility(getSlot(index), icon.visible);
    200         mIconGroups.forEach(l -> l.onSetIcon(viewIndex, icon));
    201     }
    202 
    203     @Override
    204     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    205         // TODO: Dump info about all icon groups?
    206         ViewGroup statusIcons = mIconGroups.get(0).mGroup;
    207         int N = statusIcons.getChildCount();
    208         pw.println("  icon views: " + N);
    209         for (int i = 0; i < N; i++) {
    210             StatusBarIconView ic = (StatusBarIconView) statusIcons.getChildAt(i);
    211             pw.println("    [" + i + "] icon=" + ic);
    212         }
    213         super.dump(pw);
    214     }
    215 
    216     public void dispatchDemoCommand(String command, Bundle args) {
    217         if (mDemoStatusIcons == null) {
    218             // TODO: Rework how we handle demo mode.
    219             int iconSize = mContext.getResources().getDimensionPixelSize(
    220                     com.android.internal.R.dimen.status_bar_icon_size);
    221             mDemoStatusIcons = new DemoStatusIcons((LinearLayout) mIconGroups.get(0).mGroup,
    222                     iconSize);
    223         }
    224         mDemoStatusIcons.dispatchDemoCommand(command, args);
    225     }
    226 
    227     @Override
    228     public void onDensityOrFontScaleChanged() {
    229         loadDimens();
    230     }
    231 }
    232