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.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.graphics.drawable.Icon;
23 import android.os.UserHandle;
24 
25 import com.android.internal.statusbar.StatusBarIcon;
26 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
27 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 
32 /**
33  * Wraps {@link com.android.internal.statusbar.StatusBarIcon} so we can still have a uniform list
34  */
35 public class StatusBarIconHolder {
36     public static final int TYPE_ICON = 0;
37     /**
38      * TODO (b/249790733): address this once the new pipeline is in place
39      * This type exists so that the new pipeline (see {@link MobileIconViewModel}) can be used
40      * to inform the old view system about changes to the data set (the list of mobile icons). The
41      * design of the new pipeline should allow for removal of this icon holder type, and obsolete
42      * the need for this entire class.
43      *
44      * @deprecated This field only exists so the new status bar pipeline can interface with the
45      * view holder system.
46      */
47     @Deprecated
48     public static final int TYPE_MOBILE_NEW = 3;
49 
50     /**
51      * TODO (b/238425913): address this once the new pipeline is in place
52      * This type exists so that the new wifi pipeline can be used to inform the old view system
53      * about the existence of the wifi icon. The design of the new pipeline should allow for removal
54      * of this icon holder type, and obsolete the need for this entire class.
55      *
56      * @deprecated This field only exists so the new status bar pipeline can interface with the
57      * view holder system.
58      */
59     @Deprecated
60     public static final int TYPE_WIFI_NEW = 4;
61 
62     @IntDef({
63             TYPE_ICON,
64             TYPE_MOBILE_NEW,
65             TYPE_WIFI_NEW
66     })
67     @Retention(RetentionPolicy.SOURCE)
68     @interface IconType {}
69 
70     private StatusBarIcon mIcon;
71     private @IconType int mType = TYPE_ICON;
72     private int mTag = 0;
73 
74     /** Returns a human-readable string representing the given type. */
getTypeString(@conType int type)75     public static String getTypeString(@IconType int type) {
76         switch(type) {
77             case TYPE_ICON: return "ICON";
78             case TYPE_MOBILE_NEW: return "MOBILE_NEW";
79             case TYPE_WIFI_NEW: return "WIFI_NEW";
80             default: return "UNKNOWN";
81         }
82     }
83 
StatusBarIconHolder()84     private StatusBarIconHolder() {
85     }
86 
fromIcon(StatusBarIcon icon)87     public static StatusBarIconHolder fromIcon(StatusBarIcon icon) {
88         StatusBarIconHolder wrapper = new StatusBarIconHolder();
89         wrapper.mIcon = icon;
90 
91         return wrapper;
92     }
93 
94     /** Creates a new holder with for the new wifi icon. */
forNewWifiIcon()95     public static StatusBarIconHolder forNewWifiIcon() {
96         StatusBarIconHolder holder = new StatusBarIconHolder();
97         holder.mType = TYPE_WIFI_NEW;
98         return holder;
99     }
100 
101     /**
102      * ONLY for use with the new connectivity pipeline, where we only need a subscriptionID to
103      * determine icon ordering and building the correct view model
104      */
fromSubIdForModernMobileIcon(int subId)105     public static StatusBarIconHolder fromSubIdForModernMobileIcon(int subId) {
106         StatusBarIconHolder holder = new StatusBarIconHolder();
107         holder.mType = TYPE_MOBILE_NEW;
108         holder.mTag = subId;
109 
110         return holder;
111     }
112 
113     /**
114      * Creates a new StatusBarIconHolder from a CallIndicatorIconState.
115      */
fromCallIndicatorState( Context context, CallIndicatorIconState state)116     public static StatusBarIconHolder fromCallIndicatorState(
117             Context context,
118             CallIndicatorIconState state) {
119         StatusBarIconHolder holder = new StatusBarIconHolder();
120         int resId = state.isNoCalling ? state.noCallingResId : state.callStrengthResId;
121         String contentDescription = state.isNoCalling
122                 ? state.noCallingDescription : state.callStrengthDescription;
123         holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
124                 Icon.createWithResource(context, resId), 0, 0, contentDescription);
125         holder.mTag = state.subId;
126         return holder;
127     }
128 
getType()129     public @IconType int getType() {
130         return mType;
131     }
132 
133     @Nullable
getIcon()134     public StatusBarIcon getIcon() {
135         return mIcon;
136     }
137 
setIcon(StatusBarIcon icon)138     public void setIcon(StatusBarIcon icon) {
139         mIcon = icon;
140     }
141 
isVisible()142     public boolean isVisible() {
143         switch (mType) {
144             case TYPE_ICON:
145                 return mIcon.visible;
146             case TYPE_MOBILE_NEW:
147             case TYPE_WIFI_NEW:
148                 // The new pipeline controls visibilities via the view model and view binder, so
149                 // this is effectively an unused return value.
150                 return true;
151             default:
152                 return true;
153         }
154     }
155 
setVisible(boolean visible)156     public void setVisible(boolean visible) {
157         if (isVisible() == visible) {
158             return;
159         }
160 
161         switch (mType) {
162             case TYPE_ICON:
163                 mIcon.visible = visible;
164                 break;
165 
166             case TYPE_MOBILE_NEW:
167             case TYPE_WIFI_NEW:
168                 // The new pipeline controls visibilities via the view model and view binder, so
169                 // ignore setVisible.
170                 break;
171         }
172     }
173 
getTag()174     public int getTag() {
175         return mTag;
176     }
177 
178     @Override
toString()179     public String toString() {
180         return "StatusBarIconHolder(type=" + getTypeString(mType)
181                 + " tag=" + getTag()
182                 + " visible=" + isVisible() + ")";
183     }
184 }
185