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