• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.telephony.ServiceState;
30 import android.text.method.DigitsKeyListener;
31 import android.text.method.PasswordTransformationMethod;
32 import android.util.AttributeSet;
33 import android.util.Log;
34 import android.view.View;
35 import android.widget.EditText;
36 import android.widget.TextView;
37 import android.widget.Toast;
38 
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.internal.telephony.imsphone.ImsPhone;
43 import com.android.phone.settings.fdn.EditPinPreference;
44 
45 import 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  */
51 public 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      */
CallBarringEditPreference(Context context, AttributeSet attrs)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      */
CallBarringEditPreference(Context context)106     public CallBarringEditPreference(Context context) {
107         this(context, null);
108     }
109 
init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone)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(
120                     MyHandler.MESSAGE_GET_CALL_BARRING), 0);
121             if (mTcpListener != null) {
122                 mTcpListener.onStarted(this, true);
123             }
124         }
125     }
126 
127     @Override
onClick(DialogInterface dialog, int which)128     public void onClick(DialogInterface dialog, int which) {
129         super.onClick(dialog, which);
130         mButtonClicked = which;
131     }
132 
133     @Override
needInputMethod()134     protected boolean needInputMethod() {
135         // Input method should only be displayed if the password-field is shown.
136         return mShowPassword;
137     }
138 
setInputMethodNeeded(boolean needed)139     void setInputMethodNeeded(boolean needed) {
140         mShowPassword = needed;
141     }
142 
143     @Override
showDialog(Bundle state)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
onBindView(View view)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
onPrepareDialogBuilder(AlertDialog.Builder builder)191     protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
192         builder.setPositiveButton(null, null);
193         builder.setNeutralButton(mIsActivated ? mDisableText : mEnableText, this);
194     }
195 
196     @Override
onBindDialogView(View view)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
onDialogClosed(boolean positiveResult)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,
239                     mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_BARRING), 0);
240             if (mTcpListener != null) {
241                 mTcpListener.onStarted(this, false);
242             }
243         }
244     }
245 
handleCallBarringResult(boolean status)246     void handleCallBarringResult(boolean status) {
247         mIsActivated = status;
248         if (DBG) {
249             Log.d(LOG_TAG, "handleCallBarringResult: mIsActivated=" + mIsActivated);
250         }
251     }
252 
updateSummaryText()253     void updateSummaryText() {
254         notifyChanged();
255         notifyDependencyChange(shouldDisableDependents());
256     }
257 
setShowPassword()258     private void setShowPassword() {
259         ImsPhone imsPhone = mPhone != null ? (ImsPhone) mPhone.getImsPhone() : null;
260         mShowPassword = !(imsPhone != null
261                 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
262                         || imsPhone.isUtEnabled()));
263     }
264 
265     @Override
shouldDisableDependents()266     public boolean shouldDisableDependents() {
267         return mIsActivated;
268     }
269 
270     // Message protocol:
271     // what: get vs. set
272     // arg1: action -- register vs. disable
273     // arg2: get vs. set for the preceding request
274     private static class MyHandler extends Handler {
275         private static final int MESSAGE_GET_CALL_BARRING = 0;
276         private static final int MESSAGE_SET_CALL_BARRING = 1;
277 
278         private final WeakReference<CallBarringEditPreference> mCallBarringEditPreference;
279 
MyHandler(CallBarringEditPreference callBarringEditPreference)280         private MyHandler(CallBarringEditPreference callBarringEditPreference) {
281             mCallBarringEditPreference =
282                     new WeakReference<CallBarringEditPreference>(callBarringEditPreference);
283         }
284 
285         @Override
handleMessage(Message msg)286         public void handleMessage(Message msg) {
287             switch (msg.what) {
288                 case MESSAGE_GET_CALL_BARRING:
289                     handleGetCallBarringResponse(msg);
290                     break;
291                 case MESSAGE_SET_CALL_BARRING:
292                     handleSetCallBarringResponse(msg);
293                     break;
294                 default:
295                     break;
296             }
297         }
298 
299         // Handle the response message for query CB status.
handleGetCallBarringResponse(Message msg)300         private void handleGetCallBarringResponse(Message msg) {
301             final CallBarringEditPreference pref = mCallBarringEditPreference.get();
302             if (pref == null) {
303                 return;
304             }
305 
306             if (DBG) {
307                 Log.d(LOG_TAG, "handleGetCallBarringResponse: done");
308             }
309 
310             AsyncResult ar = (AsyncResult) msg.obj;
311 
312             if (msg.arg2 == MESSAGE_SET_CALL_BARRING) {
313                 pref.mTcpListener.onFinished(pref, false);
314             } else {
315                 pref.mTcpListener.onFinished(pref, true);
316                 ImsPhone imsPhone = pref.mPhone != null
317                         ? (ImsPhone) pref.mPhone.getImsPhone() : null;
318                 if (!pref.mShowPassword && (imsPhone == null || !imsPhone.isUtEnabled())) {
319                     // Re-enable password when rejected from NW and modem would perform CSFB
320                     pref.mShowPassword = true;
321                     if (DBG) {
322                         Log.d(LOG_TAG,
323                                 "handleGetCallBarringResponse: mShowPassword changed for CSFB");
324                     }
325                 }
326             }
327 
328             // Unsuccessful query for call barring.
329             if (ar.exception != null) {
330                 if (DBG) {
331                     Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.exception=" + ar.exception);
332                 }
333                 pref.mTcpListener.onException(pref, (CommandException) ar.exception);
334             } else {
335                 if (ar.userObj instanceof Throwable) {
336                     pref.mTcpListener.onError(pref, RESPONSE_ERROR);
337                 }
338                 int[] ints = (int[]) ar.result;
339                 if (ints.length == 0) {
340                     if (DBG) {
341                         Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.result.length==0");
342                     }
343                     pref.setEnabled(false);
344                     pref.mTcpListener.onError(pref, RESPONSE_ERROR);
345                 } else {
346                     pref.handleCallBarringResult(ints[0] != 0);
347                     if (DBG) {
348                         Log.d(LOG_TAG,
349                                 "handleGetCallBarringResponse: CB state successfully queried: "
350                                         + ints[0]);
351                     }
352                 }
353             }
354             // Update call barring status.
355             pref.updateSummaryText();
356         }
357 
358         // Handle the response message for CB settings.
handleSetCallBarringResponse(Message msg)359         private void handleSetCallBarringResponse(Message msg) {
360             final CallBarringEditPreference pref = mCallBarringEditPreference.get();
361             if (pref == null) {
362                 return;
363             }
364 
365             AsyncResult ar = (AsyncResult) msg.obj;
366 
367             if (ar.exception != null || ar.userObj instanceof Throwable) {
368                 if (DBG) {
369                     Log.d(LOG_TAG, "handleSetCallBarringResponse: ar.exception=" + ar.exception);
370                 }
371             }
372             if (DBG) {
373                 Log.d(LOG_TAG, "handleSetCallBarringResponse: re-get call barring option");
374             }
375             pref.mPhone.getCallBarring(
376                     pref.mFacility,
377                     "",
378                     obtainMessage(MESSAGE_GET_CALL_BARRING, 0, MESSAGE_SET_CALL_BARRING,
379                             ar.exception),
380                     0);
381         }
382     }
383 }
384