1 /* 2 * Copyright (C) 2011 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; 18 19 import android.content.Context; 20 import android.util.AttributeSet; 21 import android.util.Log; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.view.accessibility.AccessibilityEvent; 25 import android.widget.ImageView; 26 import android.widget.LinearLayout; 27 28 import com.android.systemui.R; 29 import com.android.systemui.statusbar.policy.NetworkControllerImpl; 30 import com.android.systemui.statusbar.policy.SecurityController; 31 32 // Intimately tied to the design of res/layout/signal_cluster_view.xml 33 public class SignalClusterView 34 extends LinearLayout 35 implements NetworkControllerImpl.SignalCluster, 36 SecurityController.SecurityControllerCallback { 37 38 static final String TAG = "SignalClusterView"; 39 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 40 41 NetworkControllerImpl mNC; 42 SecurityController mSC; 43 44 private boolean mVpnVisible = false; 45 private boolean mWifiVisible = false; 46 private int mWifiStrengthId = 0; 47 private boolean mMobileVisible = false; 48 private int mMobileStrengthId = 0, mMobileTypeId = 0; 49 private boolean mIsAirplaneMode = false; 50 private int mAirplaneIconId = 0; 51 private String mWifiDescription, mMobileDescription, mMobileTypeDescription; 52 private boolean mRoaming; 53 private boolean mIsMobileTypeIconWide; 54 55 ViewGroup mWifiGroup, mMobileGroup; 56 ImageView mVpn, mWifi, mMobile, mMobileType, mAirplane; 57 View mWifiAirplaneSpacer; 58 View mWifiSignalSpacer; 59 60 private int mWideTypeIconStartPadding; 61 62 public SignalClusterView(Context context) { 63 this(context, null); 64 } 65 66 public SignalClusterView(Context context, AttributeSet attrs) { 67 this(context, attrs, 0); 68 } 69 70 public SignalClusterView(Context context, AttributeSet attrs, int defStyle) { 71 super(context, attrs, defStyle); 72 } 73 74 public void setNetworkController(NetworkControllerImpl nc) { 75 if (DEBUG) Log.d(TAG, "NetworkController=" + nc); 76 mNC = nc; 77 } 78 79 public void setSecurityController(SecurityController sc) { 80 if (DEBUG) Log.d(TAG, "SecurityController=" + sc); 81 mSC = sc; 82 mSC.addCallback(this); 83 mVpnVisible = mSC.isVpnEnabled(); 84 } 85 86 @Override 87 protected void onFinishInflate() { 88 super.onFinishInflate(); 89 mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize( 90 R.dimen.wide_type_icon_start_padding); 91 } 92 93 @Override 94 protected void onAttachedToWindow() { 95 super.onAttachedToWindow(); 96 97 mVpn = (ImageView) findViewById(R.id.vpn); 98 mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo); 99 mWifi = (ImageView) findViewById(R.id.wifi_signal); 100 mMobileGroup = (ViewGroup) findViewById(R.id.mobile_combo); 101 mMobile = (ImageView) findViewById(R.id.mobile_signal); 102 mMobileType = (ImageView) findViewById(R.id.mobile_type); 103 mAirplane = (ImageView) findViewById(R.id.airplane); 104 mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer); 105 mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer); 106 107 apply(); 108 } 109 110 @Override 111 protected void onDetachedFromWindow() { 112 mVpn = null; 113 mWifiGroup = null; 114 mWifi = null; 115 mMobileGroup = null; 116 mMobile = null; 117 mMobileType = null; 118 mAirplane = null; 119 120 super.onDetachedFromWindow(); 121 } 122 123 // From SecurityController. 124 @Override 125 public void onStateChanged() { 126 post(new Runnable() { 127 @Override 128 public void run() { 129 mVpnVisible = mSC.isVpnEnabled(); 130 apply(); 131 } 132 }); 133 } 134 135 @Override 136 public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) { 137 mWifiVisible = visible; 138 mWifiStrengthId = strengthIcon; 139 mWifiDescription = contentDescription; 140 141 apply(); 142 } 143 144 @Override 145 public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, 146 String contentDescription, String typeContentDescription, boolean roaming, 147 boolean isTypeIconWide) { 148 mMobileVisible = visible; 149 mMobileStrengthId = strengthIcon; 150 mMobileTypeId = typeIcon; 151 mMobileDescription = contentDescription; 152 mMobileTypeDescription = typeContentDescription; 153 mRoaming = roaming; 154 mIsMobileTypeIconWide = isTypeIconWide; 155 156 apply(); 157 } 158 159 @Override 160 public void setIsAirplaneMode(boolean is, int airplaneIconId) { 161 mIsAirplaneMode = is; 162 mAirplaneIconId = airplaneIconId; 163 164 apply(); 165 } 166 167 @Override 168 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 169 // Standard group layout onPopulateAccessibilityEvent() implementations 170 // ignore content description, so populate manually 171 if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null) 172 event.getText().add(mWifiGroup.getContentDescription()); 173 if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) 174 event.getText().add(mMobileGroup.getContentDescription()); 175 return super.dispatchPopulateAccessibilityEvent(event); 176 } 177 178 @Override 179 public void onRtlPropertiesChanged(int layoutDirection) { 180 super.onRtlPropertiesChanged(layoutDirection); 181 182 if (mWifi != null) { 183 mWifi.setImageDrawable(null); 184 } 185 186 if (mMobile != null) { 187 mMobile.setImageDrawable(null); 188 } 189 190 if (mMobileType != null) { 191 mMobileType.setImageDrawable(null); 192 } 193 194 if(mAirplane != null) { 195 mAirplane.setImageDrawable(null); 196 } 197 198 apply(); 199 } 200 201 @Override 202 public boolean hasOverlappingRendering() { 203 return false; 204 } 205 206 // Run after each indicator change. 207 private void apply() { 208 if (mWifiGroup == null) return; 209 210 mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE); 211 if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE")); 212 if (mWifiVisible) { 213 mWifi.setImageResource(mWifiStrengthId); 214 mWifiGroup.setContentDescription(mWifiDescription); 215 mWifiGroup.setVisibility(View.VISIBLE); 216 } else { 217 mWifiGroup.setVisibility(View.GONE); 218 } 219 220 if (DEBUG) Log.d(TAG, 221 String.format("wifi: %s sig=%d", 222 (mWifiVisible ? "VISIBLE" : "GONE"), 223 mWifiStrengthId)); 224 225 if (mMobileVisible && !mIsAirplaneMode) { 226 mMobile.setImageResource(mMobileStrengthId); 227 mMobileType.setImageResource(mMobileTypeId); 228 mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); 229 mMobileGroup.setVisibility(View.VISIBLE); 230 } else { 231 mMobileGroup.setVisibility(View.GONE); 232 } 233 234 if (mIsAirplaneMode) { 235 mAirplane.setImageResource(mAirplaneIconId); 236 mAirplane.setVisibility(View.VISIBLE); 237 } else { 238 mAirplane.setVisibility(View.GONE); 239 } 240 241 if (mIsAirplaneMode && mWifiVisible) { 242 mWifiAirplaneSpacer.setVisibility(View.VISIBLE); 243 } else { 244 mWifiAirplaneSpacer.setVisibility(View.GONE); 245 } 246 247 if (mRoaming && mMobileVisible && mWifiVisible) { 248 mWifiSignalSpacer.setVisibility(View.VISIBLE); 249 } else { 250 mWifiSignalSpacer.setVisibility(View.GONE); 251 } 252 253 mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0); 254 255 if (DEBUG) Log.d(TAG, 256 String.format("mobile: %s sig=%d typ=%d", 257 (mMobileVisible ? "VISIBLE" : "GONE"), 258 mMobileStrengthId, mMobileTypeId)); 259 260 mMobileType.setVisibility((mRoaming || mMobileTypeId != 0) ? View.VISIBLE : View.GONE); 261 } 262 } 263 264