1 /*
2  * Copyright (C) 2023 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.shade.carrier;
18 
19 import android.annotation.StyleRes;
20 import android.content.Context;
21 import android.content.res.ColorStateList;
22 import android.content.res.Configuration;
23 import android.text.TextUtils;
24 import android.util.AttributeSet;
25 import android.view.View;
26 import android.widget.ImageView;
27 import android.widget.LinearLayout;
28 import android.widget.TextView;
29 
30 import androidx.annotation.Nullable;
31 import androidx.annotation.VisibleForTesting;
32 
33 import com.android.settingslib.Utils;
34 import com.android.settingslib.graph.SignalDrawable;
35 import com.android.systemui.FontSizeUtils;
36 import com.android.systemui.res.R;
37 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView;
38 import com.android.systemui.util.LargeScreenUtils;
39 
40 import java.util.Objects;
41 
42 public class ShadeCarrier extends LinearLayout {
43 
44     private View mMobileGroup;
45     private TextView mCarrierText;
46     private ImageView mMobileSignal;
47     private ImageView mMobileRoaming;
48     private ModernShadeCarrierGroupMobileView mModernMobileView;
49     private View mSpacer;
50     @Nullable
51     private CellSignalState mLastSignalState;
52     private boolean mMobileSignalInitialized = false;
53     private boolean mIsSingleCarrier;
54 
ShadeCarrier(Context context)55     public ShadeCarrier(Context context) {
56         super(context);
57     }
58 
ShadeCarrier(Context context, AttributeSet attrs)59     public ShadeCarrier(Context context, AttributeSet attrs) {
60         super(context, attrs);
61     }
62 
ShadeCarrier(Context context, AttributeSet attrs, int defStyleAttr)63     public ShadeCarrier(Context context, AttributeSet attrs, int defStyleAttr) {
64         super(context, attrs, defStyleAttr);
65     }
66 
ShadeCarrier(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)67     public ShadeCarrier(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
68         super(context, attrs, defStyleAttr, defStyleRes);
69     }
70 
71     @Override
onFinishInflate()72     protected void onFinishInflate() {
73         super.onFinishInflate();
74         mMobileGroup = findViewById(R.id.mobile_combo);
75         mMobileRoaming = findViewById(R.id.mobile_roaming);
76         mMobileSignal = findViewById(R.id.mobile_signal);
77         mCarrierText = findViewById(R.id.shade_carrier_text);
78         mSpacer = findViewById(R.id.spacer);
79         updateResources();
80     }
81 
82     /** Removes a ModernStatusBarMobileView from the ViewGroup. */
removeModernMobileView()83     public void removeModernMobileView() {
84         if (mModernMobileView != null) {
85             removeView(mModernMobileView);
86             mModernMobileView = null;
87         }
88     }
89 
90     /** Adds a ModernStatusBarMobileView to the ViewGroup. */
addModernMobileView(ModernShadeCarrierGroupMobileView mobileView)91     public void addModernMobileView(ModernShadeCarrierGroupMobileView mobileView) {
92         mModernMobileView = mobileView;
93         mMobileGroup.setVisibility(View.GONE);
94         mSpacer.setVisibility(View.GONE);
95         mCarrierText.setVisibility(View.GONE);
96         addView(mobileView);
97     }
98 
99     /**
100      * Update the state of this view
101      * @param state the current state of the signal for this view
102      * @param isSingleCarrier whether there is a single carrier being shown in the container
103      * @return true if the state was actually changed
104      */
updateState(CellSignalState state, boolean isSingleCarrier)105     public boolean updateState(CellSignalState state, boolean isSingleCarrier) {
106         if (Objects.equals(state, mLastSignalState) && isSingleCarrier == mIsSingleCarrier) {
107             return false;
108         }
109         mLastSignalState = state;
110         mIsSingleCarrier = isSingleCarrier;
111         final boolean visible = state.visible && !isSingleCarrier;
112         mMobileGroup.setVisibility(visible ? View.VISIBLE : View.GONE);
113         mSpacer.setVisibility(isSingleCarrier ? View.VISIBLE : View.GONE);
114         if (visible) {
115             mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
116             ColorStateList colorStateList = Utils.getColorAttr(mContext,
117                     android.R.attr.textColorPrimary);
118             mMobileRoaming.setImageTintList(colorStateList);
119             mMobileSignal.setImageTintList(colorStateList);
120 
121             if (!mMobileSignalInitialized) {
122                 mMobileSignalInitialized = true;
123                 mMobileSignal.setImageDrawable(new SignalDrawable(mContext));
124             }
125             mMobileSignal.setImageLevel(state.mobileSignalIconId);
126             StringBuilder contentDescription = new StringBuilder();
127             if (state.contentDescription != null) {
128                 contentDescription.append(state.contentDescription).append(", ");
129             }
130             if (state.roaming) {
131                 contentDescription
132                         .append(mContext.getString(R.string.data_connection_roaming))
133                         .append(", ");
134             }
135             // TODO: show mobile data off/no internet text for 5 seconds before carrier text
136             if (hasValidTypeContentDescription(state.typeContentDescription)) {
137                 contentDescription.append(state.typeContentDescription);
138             }
139             mMobileSignal.setContentDescription(contentDescription);
140         }
141         return true;
142     }
143 
hasValidTypeContentDescription(@ullable String typeContentDescription)144     private boolean hasValidTypeContentDescription(@Nullable String typeContentDescription) {
145         return TextUtils.equals(typeContentDescription,
146                 mContext.getString(R.string.data_connection_no_internet))
147                 || TextUtils.equals(typeContentDescription,
148                 mContext.getString(
149                         com.android.settingslib.R.string.cell_data_off_content_description))
150                 || TextUtils.equals(typeContentDescription,
151                 mContext.getString(
152                         com.android.settingslib.R.string.not_default_data_content_description));
153     }
154 
155     @VisibleForTesting
getRSSIView()156     View getRSSIView() {
157         return mMobileGroup;
158     }
159 
setCarrierText(CharSequence text)160     public void setCarrierText(CharSequence text) {
161         mCarrierText.setText(text);
162     }
163 
updateTextAppearance(@tyleRes int resId)164     public void updateTextAppearance(@StyleRes int resId) {
165         FontSizeUtils.updateFontSizeFromStyle(mCarrierText, resId);
166     }
167 
168     @Override
onConfigurationChanged(Configuration newConfig)169     protected void onConfigurationChanged(Configuration newConfig) {
170         super.onConfigurationChanged(newConfig);
171         updateResources();
172     }
173 
updateResources()174     private void updateResources() {
175         boolean useLargeScreenHeader =
176                 LargeScreenUtils.shouldUseLargeScreenShadeHeader(getResources());
177         mCarrierText.setMaxEms(
178                 useLargeScreenHeader
179                         ? Integer.MAX_VALUE
180                         : getResources().getInteger(R.integer.shade_carrier_max_em)
181         );
182     }
183 }
184