CarrierText.java revision 25807936e8e4ca2c811bb4121725e1dd87e18efd
1/* 2 * Copyright (C) 2012 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.keyguard; 18 19import android.content.Context; 20import android.content.res.TypedArray; 21import android.text.method.SingleLineTransformationMethod; 22import android.text.TextUtils; 23import android.util.AttributeSet; 24import android.view.View; 25import android.widget.TextView; 26 27import com.android.internal.telephony.IccCardConstants; 28import com.android.internal.telephony.IccCardConstants.State; 29import com.android.internal.widget.LockPatternUtils; 30 31import java.util.Locale; 32 33public class CarrierText extends TextView { 34 private static CharSequence mSeparator; 35 36 private LockPatternUtils mLockPatternUtils; 37 38 private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { 39 private CharSequence mPlmn; 40 private CharSequence mSpn; 41 private State mSimState; 42 43 @Override 44 public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { 45 mPlmn = plmn; 46 mSpn = spn; 47 updateCarrierText(mSimState, mPlmn, mSpn); 48 } 49 50 @Override 51 public void onSimStateChanged(IccCardConstants.State simState) { 52 mSimState = simState; 53 updateCarrierText(mSimState, mPlmn, mSpn); 54 } 55 56 public void onScreenTurnedOff(int why) { 57 setSelected(false); 58 }; 59 60 public void onScreenTurnedOn() { 61 setSelected(true); 62 }; 63 }; 64 /** 65 * The status of this lock screen. Primarily used for widgets on LockScreen. 66 */ 67 private static enum StatusMode { 68 Normal, // Normal case (sim card present, it's not locked) 69 NetworkLocked, // SIM card is 'network locked'. 70 SimMissing, // SIM card is missing. 71 SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access 72 SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times 73 SimLocked, // SIM card is currently locked 74 SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure 75 SimNotReady; // SIM is not ready yet. May never be on devices w/o a SIM. 76 } 77 78 public CarrierText(Context context) { 79 this(context, null); 80 } 81 82 public CarrierText(Context context, AttributeSet attrs) { 83 super(context, attrs); 84 mLockPatternUtils = new LockPatternUtils(mContext); 85 boolean useAllCaps; 86 TypedArray a = context.getTheme().obtainStyledAttributes( 87 attrs, R.styleable.CarrierText, 0, 0); 88 try { 89 useAllCaps = a.getBoolean(R.styleable.CarrierText_allCaps, false); 90 } finally { 91 a.recycle(); 92 } 93 setTransformationMethod(new CarrierTextTransformationMethod(mContext, useAllCaps)); 94 } 95 96 protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) { 97 setText(getCarrierTextForSimState(simState, plmn, spn)); 98 } 99 100 @Override 101 protected void onFinishInflate() { 102 super.onFinishInflate(); 103 mSeparator = getResources().getString(R.string.kg_text_message_separator); 104 final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); 105 setSelected(screenOn); // Allow marquee to work. 106 } 107 108 @Override 109 protected void onAttachedToWindow() { 110 super.onAttachedToWindow(); 111 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback); 112 } 113 114 @Override 115 protected void onDetachedFromWindow() { 116 super.onDetachedFromWindow(); 117 KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback); 118 } 119 120 /** 121 * Top-level function for creating carrier text. Makes text based on simState, PLMN 122 * and SPN as well as device capabilities, such as being emergency call capable. 123 * 124 * @param simState 125 * @param plmn 126 * @param spn 127 * @return 128 */ 129 private CharSequence getCarrierTextForSimState(IccCardConstants.State simState, 130 CharSequence plmn, CharSequence spn) { 131 CharSequence carrierText = null; 132 StatusMode status = getStatusForIccState(simState); 133 switch (status) { 134 case Normal: 135 carrierText = concatenate(plmn, spn); 136 break; 137 138 case SimNotReady: 139 carrierText = null; // nothing to display yet. 140 break; 141 142 case NetworkLocked: 143 carrierText = makeCarrierStringOnEmergencyCapable( 144 mContext.getText(R.string.keyguard_network_locked_message), plmn); 145 break; 146 147 case SimMissing: 148 // Shows "No SIM card | Emergency calls only" on devices that are voice-capable. 149 // This depends on mPlmn containing the text "Emergency calls only" when the radio 150 // has some connectivity. Otherwise, it should be null or empty and just show 151 // "No SIM card" 152 carrierText = makeCarrierStringOnEmergencyCapable( 153 getContext().getText(R.string.keyguard_missing_sim_message_short), 154 plmn); 155 break; 156 157 case SimPermDisabled: 158 carrierText = getContext().getText( 159 R.string.keyguard_permanent_disabled_sim_message_short); 160 break; 161 162 case SimMissingLocked: 163 carrierText = makeCarrierStringOnEmergencyCapable( 164 getContext().getText(R.string.keyguard_missing_sim_message_short), 165 plmn); 166 break; 167 168 case SimLocked: 169 carrierText = makeCarrierStringOnEmergencyCapable( 170 getContext().getText(R.string.keyguard_sim_locked_message), 171 plmn); 172 break; 173 174 case SimPukLocked: 175 carrierText = makeCarrierStringOnEmergencyCapable( 176 getContext().getText(R.string.keyguard_sim_puk_locked_message), 177 plmn); 178 break; 179 } 180 181 return carrierText; 182 } 183 184 /* 185 * Add emergencyCallMessage to carrier string only if phone supports emergency calls. 186 */ 187 private CharSequence makeCarrierStringOnEmergencyCapable( 188 CharSequence simMessage, CharSequence emergencyCallMessage) { 189 if (mLockPatternUtils.isEmergencyCallCapable()) { 190 return concatenate(simMessage, emergencyCallMessage); 191 } 192 return simMessage; 193 } 194 195 /** 196 * Determine the current status of the lock screen given the SIM state and other stuff. 197 */ 198 private StatusMode getStatusForIccState(IccCardConstants.State simState) { 199 // Since reading the SIM may take a while, we assume it is present until told otherwise. 200 if (simState == null) { 201 return StatusMode.Normal; 202 } 203 204 final boolean missingAndNotProvisioned = 205 !KeyguardUpdateMonitor.getInstance(mContext).isDeviceProvisioned() 206 && (simState == IccCardConstants.State.ABSENT || 207 simState == IccCardConstants.State.PERM_DISABLED); 208 209 // Assume we're NETWORK_LOCKED if not provisioned 210 simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState; 211 switch (simState) { 212 case ABSENT: 213 return StatusMode.SimMissing; 214 case NETWORK_LOCKED: 215 return StatusMode.SimMissingLocked; 216 case NOT_READY: 217 return StatusMode.SimNotReady; 218 case PIN_REQUIRED: 219 return StatusMode.SimLocked; 220 case PUK_REQUIRED: 221 return StatusMode.SimPukLocked; 222 case READY: 223 return StatusMode.Normal; 224 case PERM_DISABLED: 225 return StatusMode.SimPermDisabled; 226 case UNKNOWN: 227 return StatusMode.SimMissing; 228 } 229 return StatusMode.SimMissing; 230 } 231 232 private static CharSequence concatenate(CharSequence plmn, CharSequence spn) { 233 final boolean plmnValid = !TextUtils.isEmpty(plmn); 234 final boolean spnValid = !TextUtils.isEmpty(spn); 235 if (plmnValid && spnValid) { 236 return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString(); 237 } else if (plmnValid) { 238 return plmn; 239 } else if (spnValid) { 240 return spn; 241 } else { 242 return ""; 243 } 244 } 245 246 private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState, 247 String plmn, String spn) { 248 int carrierHelpTextId = 0; 249 StatusMode status = getStatusForIccState(simState); 250 switch (status) { 251 case NetworkLocked: 252 carrierHelpTextId = R.string.keyguard_instructions_when_pattern_disabled; 253 break; 254 255 case SimMissing: 256 carrierHelpTextId = R.string.keyguard_missing_sim_instructions_long; 257 break; 258 259 case SimPermDisabled: 260 carrierHelpTextId = R.string.keyguard_permanent_disabled_sim_instructions; 261 break; 262 263 case SimMissingLocked: 264 carrierHelpTextId = R.string.keyguard_missing_sim_instructions; 265 break; 266 267 case Normal: 268 case SimLocked: 269 case SimPukLocked: 270 break; 271 } 272 273 return mContext.getText(carrierHelpTextId); 274 } 275 276 private class CarrierTextTransformationMethod extends SingleLineTransformationMethod { 277 private final Locale mLocale; 278 private final boolean mAllCaps; 279 280 public CarrierTextTransformationMethod(Context context, boolean allCaps) { 281 mLocale = context.getResources().getConfiguration().locale; 282 mAllCaps = allCaps; 283 } 284 285 @Override 286 public CharSequence getTransformation(CharSequence source, View view) { 287 source = super.getTransformation(source, view); 288 289 if (mAllCaps && source != null) { 290 source = source.toString().toUpperCase(mLocale); 291 } 292 293 return source; 294 } 295 } 296} 297