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