1/*
2 * Copyright (C) 2018 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
17package com.android.systemui.statusbar;
18
19import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
20import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
21import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
22import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
23import static com.android.systemui.statusbar.policy.DarkIconDispatcher.isInArea;
24
25import android.content.Context;
26import android.content.res.ColorStateList;
27import android.graphics.Color;
28import android.graphics.Rect;
29import android.util.AttributeSet;
30import android.util.Log;
31import android.view.Gravity;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.widget.FrameLayout;
35import android.widget.ImageView;
36
37import android.widget.LinearLayout;
38import com.android.internal.annotations.VisibleForTesting;
39import com.android.keyguard.AlphaOptimizedLinearLayout;
40import com.android.settingslib.graph.SignalDrawable;
41import com.android.systemui.R;
42import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
43import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
44
45public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
46        StatusIconDisplayable {
47    private static final String TAG = "StatusBarMobileView";
48
49    /// Used to show etc dots
50    private StatusBarIconView mDotView;
51    /// The main icon view
52    private LinearLayout mMobileGroup;
53    private String mSlot;
54    private MobileIconState mState;
55    private SignalDrawable mMobileDrawable;
56    private View mInoutContainer;
57    private ImageView mIn;
58    private ImageView mOut;
59    private ImageView mMobile, mMobileType, mMobileRoaming;
60    private View mMobileRoamingSpace;
61    private int mVisibleState = -1;
62
63    public static StatusBarMobileView fromContext(Context context, String slot) {
64        LayoutInflater inflater = LayoutInflater.from(context);
65        StatusBarMobileView v = (StatusBarMobileView)
66                inflater.inflate(R.layout.status_bar_mobile_signal_group, null);
67
68        v.setSlot(slot);
69        v.init();
70        v.setVisibleState(STATE_ICON);
71        return v;
72    }
73
74    public StatusBarMobileView(Context context) {
75        super(context);
76    }
77
78    public StatusBarMobileView(Context context, AttributeSet attrs) {
79        super(context, attrs);
80    }
81
82    public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr) {
83        super(context, attrs, defStyleAttr);
84    }
85
86    public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr,
87            int defStyleRes) {
88        super(context, attrs, defStyleAttr, defStyleRes);
89    }
90
91    @Override
92    public void getDrawingRect(Rect outRect) {
93        super.getDrawingRect(outRect);
94        float translationX = getTranslationX();
95        float translationY = getTranslationY();
96        outRect.left += translationX;
97        outRect.right += translationX;
98        outRect.top += translationY;
99        outRect.bottom += translationY;
100    }
101
102    private void init() {
103        mMobileGroup = findViewById(R.id.mobile_group);
104        mMobile = findViewById(R.id.mobile_signal);
105        mMobileType = findViewById(R.id.mobile_type);
106        mMobileRoaming = findViewById(R.id.mobile_roaming);
107        mMobileRoamingSpace = findViewById(R.id.mobile_roaming_space);
108        mIn = findViewById(R.id.mobile_in);
109        mOut = findViewById(R.id.mobile_out);
110        mInoutContainer = findViewById(R.id.inout_container);
111
112        mMobileDrawable = new SignalDrawable(getContext());
113        mMobile.setImageDrawable(mMobileDrawable);
114
115        initDotView();
116    }
117
118    private void initDotView() {
119        mDotView = new StatusBarIconView(mContext, mSlot, null);
120        mDotView.setVisibleState(STATE_DOT);
121
122        int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size);
123        LayoutParams lp = new LayoutParams(width, width);
124        lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
125        addView(mDotView, lp);
126    }
127
128    public void applyMobileState(MobileIconState state) {
129        if (state == null) {
130            setVisibility(View.GONE);
131            mState = null;
132            return;
133        }
134
135        if (mState == null) {
136            mState = state.copy();
137            initViewState();
138            return;
139        }
140
141        if (!mState.equals(state)) {
142            updateState(state.copy());
143        }
144    }
145
146    private void initViewState() {
147        setContentDescription(mState.contentDescription);
148        if (!mState.visible) {
149            mMobileGroup.setVisibility(View.GONE);
150        } else {
151            mMobileGroup.setVisibility(View.VISIBLE);
152        }
153        mMobileDrawable.setLevel(mState.strengthId);
154        if (mState.typeId > 0) {
155            mMobileType.setContentDescription(mState.typeContentDescription);
156            mMobileType.setImageResource(mState.typeId);
157            mMobileType.setVisibility(View.VISIBLE);
158        } else {
159            mMobileType.setVisibility(View.GONE);
160        }
161
162        mMobileRoaming.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
163        mMobileRoamingSpace.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
164        mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
165        mOut.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
166        mInoutContainer.setVisibility((mState.activityIn || mState.activityOut)
167                ? View.VISIBLE : View.GONE);
168    }
169
170    private void updateState(MobileIconState state) {
171        setContentDescription(state.contentDescription);
172        if (mState.visible != state.visible) {
173            mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
174        }
175        if (mState.strengthId != state.strengthId) {
176            mMobileDrawable.setLevel(state.strengthId);
177        }
178        if (mState.typeId != state.typeId) {
179            if (state.typeId != 0) {
180                mMobileType.setContentDescription(state.typeContentDescription);
181                mMobileType.setImageResource(state.typeId);
182                mMobileType.setVisibility(View.VISIBLE);
183            } else {
184                mMobileType.setVisibility(View.GONE);
185            }
186        }
187
188        mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
189        mMobileRoamingSpace.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
190        mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
191        mOut.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
192        mInoutContainer.setVisibility((state.activityIn || state.activityOut)
193                ? View.VISIBLE : View.GONE);
194
195        mState = state;
196    }
197
198    @Override
199    public void onDarkChanged(Rect area, float darkIntensity, int tint) {
200        if (!isInArea(area, this)) {
201            return;
202        }
203        mMobileDrawable.setDarkIntensity(darkIntensity);
204        ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
205        mIn.setImageTintList(color);
206        mOut.setImageTintList(color);
207        mMobileType.setImageTintList(color);
208        mMobileRoaming.setImageTintList(color);
209        mDotView.setDecorColor(tint);
210        mDotView.setIconColor(tint, false);
211    }
212
213    @Override
214    public String getSlot() {
215        return mSlot;
216    }
217
218    public void setSlot(String slot) {
219        mSlot = slot;
220    }
221
222    @Override
223    public void setStaticDrawableColor(int color) {
224        ColorStateList list = ColorStateList.valueOf(color);
225        float intensity = color == Color.WHITE ? 0 : 1;
226        mMobileDrawable.setDarkIntensity(intensity);
227
228        mIn.setImageTintList(list);
229        mOut.setImageTintList(list);
230        mMobileType.setImageTintList(list);
231        mMobileRoaming.setImageTintList(list);
232        mDotView.setDecorColor(color);
233    }
234
235    @Override
236    public void setDecorColor(int color) {
237        mDotView.setDecorColor(color);
238    }
239
240    @Override
241    public boolean isIconVisible() {
242        return mState.visible;
243    }
244
245    @Override
246    public void setVisibleState(int state) {
247        if (state == mVisibleState) {
248            return;
249        }
250
251        mVisibleState = state;
252        switch (state) {
253            case STATE_ICON:
254                mMobileGroup.setVisibility(View.VISIBLE);
255                mDotView.setVisibility(View.GONE);
256                break;
257            case STATE_DOT:
258                mMobileGroup.setVisibility(View.INVISIBLE);
259                mDotView.setVisibility(View.VISIBLE);
260                break;
261            case STATE_HIDDEN:
262            default:
263                mMobileGroup.setVisibility(View.INVISIBLE);
264                mDotView.setVisibility(View.INVISIBLE);
265                break;
266        }
267    }
268
269    @Override
270    public int getVisibleState() {
271        return mVisibleState;
272    }
273
274    @VisibleForTesting
275    public MobileIconState getState() {
276        return mState;
277    }
278
279    @Override
280    public String toString() {
281        return "StatusBarMobileView(slot=" + mSlot + " state=" + mState + ")";
282    }
283}
284