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