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 17 package com.android.phone; 18 19 import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR; 20 21 import android.app.AlertDialog; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.res.TypedArray; 25 import android.os.AsyncResult; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.Message; 29 import android.text.method.DigitsKeyListener; 30 import android.text.method.PasswordTransformationMethod; 31 import android.util.AttributeSet; 32 import android.util.Log; 33 import android.view.View; 34 import android.widget.EditText; 35 import android.widget.TextView; 36 import android.widget.Toast; 37 38 import com.android.internal.telephony.CommandsInterface; 39 import com.android.internal.telephony.CommandException; 40 import com.android.internal.telephony.Phone; 41 import com.android.internal.telephony.PhoneFactory; 42 import com.android.phone.settings.fdn.EditPinPreference; 43 44 import java.lang.ref.WeakReference; 45 46 /** 47 * This preference represents the status of call barring options, enabling/disabling 48 * the call barring option will prompt the user for the current password. 49 */ 50 public class CallBarringEditPreference extends EditPinPreference { 51 private static final String LOG_TAG = "CallBarringEditPreference"; 52 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); 53 54 private String mFacility; 55 boolean mIsActivated = false; 56 private CharSequence mEnableText; 57 private CharSequence mDisableText; 58 private CharSequence mSummaryOn; 59 private CharSequence mSummaryOff; 60 private int mButtonClicked; 61 private final MyHandler mHandler = new MyHandler(this); 62 private Phone mPhone; 63 private TimeConsumingPreferenceListener mTcpListener; 64 65 private static final int PW_LENGTH = 4; 66 67 /** 68 * CallBarringEditPreference constructor. 69 * 70 * @param context The context of view. 71 * @param attrs The attributes of the XML tag that is inflating EditTextPreference. 72 */ CallBarringEditPreference(Context context, AttributeSet attrs)73 public CallBarringEditPreference(Context context, AttributeSet attrs) { 74 super(context, attrs); 75 // Get the summary settings, use CheckBoxPreference as the standard. 76 TypedArray typedArray = context.obtainStyledAttributes(attrs, 77 android.R.styleable.CheckBoxPreference, 0, 0); 78 mSummaryOn = typedArray.getString(android.R.styleable.CheckBoxPreference_summaryOn); 79 mSummaryOff = typedArray.getString(android.R.styleable.CheckBoxPreference_summaryOff); 80 mDisableText = context.getText(R.string.disable); 81 mEnableText = context.getText(R.string.enable); 82 typedArray.recycle(); 83 84 // Get default phone 85 mPhone = PhoneFactory.getDefaultPhone(); 86 87 typedArray = context.obtainStyledAttributes(attrs, 88 R.styleable.CallBarringEditPreference, 0, R.style.EditPhoneNumberPreference); 89 mFacility = typedArray.getString(R.styleable.CallBarringEditPreference_facility); 90 typedArray.recycle(); 91 } 92 93 /** 94 * CallBarringEditPreference constructor. 95 * 96 * @param context The context of view. 97 */ CallBarringEditPreference(Context context)98 public CallBarringEditPreference(Context context) { 99 this(context, null); 100 } 101 init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone)102 void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) { 103 if (DBG) { 104 Log.d(LOG_TAG, "init: phone id = " + phone.getPhoneId()); 105 } 106 mPhone = phone; 107 108 mTcpListener = listener; 109 if (!skipReading) { 110 // Query call barring status 111 mPhone.getCallBarring(mFacility, "", mHandler.obtainMessage( 112 MyHandler.MESSAGE_GET_CALL_BARRING), CommandsInterface.SERVICE_CLASS_VOICE); 113 if (mTcpListener != null) { 114 mTcpListener.onStarted(this, true); 115 } 116 } 117 } 118 119 @Override onClick(DialogInterface dialog, int which)120 public void onClick(DialogInterface dialog, int which) { 121 super.onClick(dialog, which); 122 mButtonClicked = which; 123 } 124 125 @Override showDialog(Bundle state)126 protected void showDialog(Bundle state) { 127 setDialogMessage(getContext().getString(R.string.messageCallBarring)); 128 super.showDialog(state); 129 } 130 131 @Override onBindView(View view)132 protected void onBindView(View view) { 133 super.onBindView(view); 134 135 // Sync the summary view 136 TextView summaryView = (TextView) view.findViewById(android.R.id.summary); 137 if (summaryView != null) { 138 CharSequence sum; 139 int vis; 140 141 // Set summary depending upon mode 142 if (mIsActivated) { 143 sum = (mSummaryOn == null) ? getSummary() : mSummaryOn; 144 } else { 145 sum = (mSummaryOff == null) ? getSummary() : mSummaryOff; 146 } 147 148 if (sum != null) { 149 summaryView.setText(sum); 150 vis = View.VISIBLE; 151 } else { 152 vis = View.GONE; 153 } 154 155 if (vis != summaryView.getVisibility()) { 156 summaryView.setVisibility(vis); 157 } 158 } 159 } 160 161 @Override onPrepareDialogBuilder(AlertDialog.Builder builder)162 protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 163 builder.setPositiveButton(null, null); 164 builder.setNeutralButton(mIsActivated ? mDisableText : mEnableText, this); 165 } 166 167 @Override onBindDialogView(View view)168 protected void onBindDialogView(View view) { 169 super.onBindDialogView(view); 170 // Default the button clicked to be the cancel button. 171 mButtonClicked = DialogInterface.BUTTON_NEGATIVE; 172 173 final EditText editText = (EditText) view.findViewById(android.R.id.edit); 174 if (editText != null) { 175 editText.setSingleLine(true); 176 editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); 177 editText.setKeyListener(DigitsKeyListener.getInstance()); 178 179 editText.setVisibility(View.VISIBLE); 180 } 181 } 182 183 @Override onDialogClosed(boolean positiveResult)184 protected void onDialogClosed(boolean positiveResult) { 185 super.onDialogClosed(positiveResult); 186 if (DBG) { 187 Log.d(LOG_TAG, "onDialogClosed: mButtonClicked=" + mButtonClicked + ", positiveResult=" 188 + positiveResult); 189 } 190 if (mButtonClicked != DialogInterface.BUTTON_NEGATIVE) { 191 String password = getEditText().getText().toString(); 192 193 // Check if the password is valid. 194 if (password == null || password.length() != PW_LENGTH) { 195 Toast.makeText(getContext(), 196 getContext().getString(R.string.call_barring_right_pwd_number), 197 Toast.LENGTH_SHORT).show(); 198 return; 199 } 200 201 if (DBG) { 202 Log.d(LOG_TAG, "onDialogClosed: password=" + password); 203 } 204 // Send set call barring message to RIL layer. 205 mPhone.setCallBarring(mFacility, !mIsActivated, password, 206 mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_BARRING), 207 CommandsInterface.SERVICE_CLASS_VOICE); 208 if (mTcpListener != null) { 209 mTcpListener.onStarted(this, false); 210 } 211 } 212 } 213 handleCallBarringResult(boolean status)214 void handleCallBarringResult(boolean status) { 215 mIsActivated = status; 216 if (DBG) { 217 Log.d(LOG_TAG, "handleCallBarringResult: mIsActivated=" + mIsActivated); 218 } 219 } 220 updateSummaryText()221 void updateSummaryText() { 222 notifyChanged(); 223 notifyDependencyChange(shouldDisableDependents()); 224 } 225 226 @Override shouldDisableDependents()227 public boolean shouldDisableDependents() { 228 return mIsActivated; 229 } 230 231 // Message protocol: 232 // what: get vs. set 233 // arg1: action -- register vs. disable 234 // arg2: get vs. set for the preceding request 235 private static class MyHandler extends Handler { 236 private static final int MESSAGE_GET_CALL_BARRING = 0; 237 private static final int MESSAGE_SET_CALL_BARRING = 1; 238 239 private final WeakReference<CallBarringEditPreference> mCallBarringEditPreference; 240 MyHandler(CallBarringEditPreference callBarringEditPreference)241 private MyHandler(CallBarringEditPreference callBarringEditPreference) { 242 mCallBarringEditPreference = 243 new WeakReference<CallBarringEditPreference>(callBarringEditPreference); 244 } 245 246 @Override handleMessage(Message msg)247 public void handleMessage(Message msg) { 248 switch (msg.what) { 249 case MESSAGE_GET_CALL_BARRING: 250 handleGetCallBarringResponse(msg); 251 break; 252 case MESSAGE_SET_CALL_BARRING: 253 handleSetCallBarringResponse(msg); 254 break; 255 default: 256 break; 257 } 258 } 259 260 // Handle the response message for query CB status. handleGetCallBarringResponse(Message msg)261 private void handleGetCallBarringResponse(Message msg) { 262 final CallBarringEditPreference pref = mCallBarringEditPreference.get(); 263 if (pref == null) { 264 return; 265 } 266 267 if (DBG) { 268 Log.d(LOG_TAG, "handleGetCallBarringResponse: done"); 269 } 270 271 AsyncResult ar = (AsyncResult) msg.obj; 272 273 if (msg.arg2 == MESSAGE_SET_CALL_BARRING) { 274 pref.mTcpListener.onFinished(pref, false); 275 } else { 276 pref.mTcpListener.onFinished(pref, true); 277 } 278 279 // Unsuccessful query for call barring. 280 if (ar.exception != null) { 281 if (DBG) { 282 Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.exception=" + ar.exception); 283 } 284 pref.mTcpListener.onException(pref, (CommandException) ar.exception); 285 } else { 286 if (ar.userObj instanceof Throwable) { 287 pref.mTcpListener.onError(pref, RESPONSE_ERROR); 288 } 289 int[] ints = (int[]) ar.result; 290 if (ints.length == 0) { 291 if (DBG) { 292 Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.result.length==0"); 293 } 294 pref.setEnabled(false); 295 pref.mTcpListener.onError(pref, RESPONSE_ERROR); 296 } else { 297 pref.handleCallBarringResult(ints[0] != 0); 298 if (DBG) { 299 Log.d(LOG_TAG, 300 "handleGetCallBarringResponse: CB state successfully queried: " 301 + ints[0]); 302 } 303 } 304 } 305 // Update call barring status. 306 pref.updateSummaryText(); 307 } 308 309 // Handle the response message for CB settings. handleSetCallBarringResponse(Message msg)310 private void handleSetCallBarringResponse(Message msg) { 311 final CallBarringEditPreference pref = mCallBarringEditPreference.get(); 312 if (pref == null) { 313 return; 314 } 315 316 AsyncResult ar = (AsyncResult) msg.obj; 317 318 if (ar.exception != null || ar.userObj instanceof Throwable) { 319 if (DBG) { 320 Log.d(LOG_TAG, "handleSetCallBarringResponse: ar.exception=" + ar.exception); 321 } 322 } 323 if (DBG) { 324 Log.d(LOG_TAG, "handleSetCallBarringResponse: re-get call barring option"); 325 } 326 pref.mPhone.getCallBarring( 327 pref.mFacility, 328 "", 329 obtainMessage(MESSAGE_GET_CALL_BARRING, 0, MESSAGE_SET_CALL_BARRING, 330 ar.exception), 331 CommandsInterface.SERVICE_CLASS_VOICE); 332 } 333 } 334 } 335