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