| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.phone; |
| |
| import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR; |
| |
| import android.app.AlertDialog; |
| import android.content.Context; |
| import android.content.DialogInterface; |
| import android.content.res.TypedArray; |
| import android.os.AsyncResult; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.Message; |
| import android.os.PersistableBundle; |
| import android.telephony.CarrierConfigManager; |
| import android.text.method.DigitsKeyListener; |
| import android.text.method.PasswordTransformationMethod; |
| import android.util.AttributeSet; |
| import android.util.Log; |
| import android.view.View; |
| import android.widget.EditText; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| |
| import com.android.internal.telephony.CommandException; |
| import com.android.internal.telephony.Phone; |
| import com.android.internal.telephony.PhoneFactory; |
| import com.android.phone.settings.fdn.EditPinPreference; |
| |
| import java.lang.ref.WeakReference; |
| |
| /** |
| * This preference represents the status of call barring options, enabling/disabling |
| * the call barring option will prompt the user for the current password. |
| */ |
| public class CallBarringEditPreference extends EditPinPreference { |
| private static final String LOG_TAG = "CallBarringEditPreference"; |
| private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); |
| |
| private String mFacility; |
| boolean mIsActivated = false; |
| private CharSequence mEnableText; |
| private CharSequence mDisableText; |
| private CharSequence mSummaryOn; |
| private CharSequence mSummaryOff; |
| private int mButtonClicked; |
| private final MyHandler mHandler = new MyHandler(this); |
| private Phone mPhone; |
| private TimeConsumingPreferenceListener mTcpListener; |
| |
| private static final int PW_LENGTH = 4; |
| |
| /** |
| * CallBarringEditPreference constructor. |
| * |
| * @param context The context of view. |
| * @param attrs The attributes of the XML tag that is inflating EditTextPreference. |
| */ |
| public CallBarringEditPreference(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| // Get the summary settings, use CheckBoxPreference as the standard. |
| TypedArray typedArray = context.obtainStyledAttributes(attrs, |
| android.R.styleable.CheckBoxPreference, 0, 0); |
| mSummaryOn = typedArray.getString(android.R.styleable.CheckBoxPreference_summaryOn); |
| mSummaryOff = typedArray.getString(android.R.styleable.CheckBoxPreference_summaryOff); |
| mDisableText = context.getText(R.string.disable); |
| mEnableText = context.getText(R.string.enable); |
| typedArray.recycle(); |
| |
| // Get default phone |
| mPhone = PhoneFactory.getDefaultPhone(); |
| |
| typedArray = context.obtainStyledAttributes(attrs, |
| R.styleable.CallBarringEditPreference, 0, R.style.EditPhoneNumberPreference); |
| mFacility = typedArray.getString(R.styleable.CallBarringEditPreference_facility); |
| typedArray.recycle(); |
| } |
| |
| /** |
| * CallBarringEditPreference constructor. |
| * |
| * @param context The context of view. |
| */ |
| public CallBarringEditPreference(Context context) { |
| this(context, null); |
| } |
| |
| void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) { |
| if (DBG) { |
| Log.d(LOG_TAG, "init: phone id = " + phone.getPhoneId()); |
| } |
| mPhone = phone; |
| |
| mTcpListener = listener; |
| if (!skipReading) { |
| // Query call barring status |
| mPhone.getCallBarring(mFacility, "", mHandler.obtainMessage( |
| MyHandler.MESSAGE_GET_CALL_BARRING), getServiceClassForCallBarring(mPhone)); |
| if (mTcpListener != null) { |
| mTcpListener.onStarted(this, true); |
| } |
| } |
| } |
| |
| @Override |
| public void onClick(DialogInterface dialog, int which) { |
| super.onClick(dialog, which); |
| mButtonClicked = which; |
| } |
| |
| @Override |
| protected void showDialog(Bundle state) { |
| setDialogMessage(getContext().getString(R.string.messageCallBarring)); |
| super.showDialog(state); |
| } |
| |
| @Override |
| protected void onBindView(View view) { |
| super.onBindView(view); |
| |
| // Sync the summary view |
| TextView summaryView = (TextView) view.findViewById(android.R.id.summary); |
| if (summaryView != null) { |
| CharSequence sum; |
| int vis; |
| |
| // Set summary depending upon mode |
| if (mIsActivated) { |
| sum = (mSummaryOn == null) ? getSummary() : mSummaryOn; |
| } else { |
| sum = (mSummaryOff == null) ? getSummary() : mSummaryOff; |
| } |
| |
| if (sum != null) { |
| summaryView.setText(sum); |
| vis = View.VISIBLE; |
| } else { |
| vis = View.GONE; |
| } |
| |
| if (vis != summaryView.getVisibility()) { |
| summaryView.setVisibility(vis); |
| } |
| } |
| } |
| |
| @Override |
| protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { |
| builder.setPositiveButton(null, null); |
| builder.setNeutralButton(mIsActivated ? mDisableText : mEnableText, this); |
| } |
| |
| @Override |
| protected void onBindDialogView(View view) { |
| super.onBindDialogView(view); |
| // Default the button clicked to be the cancel button. |
| mButtonClicked = DialogInterface.BUTTON_NEGATIVE; |
| |
| final EditText editText = (EditText) view.findViewById(android.R.id.edit); |
| if (editText != null) { |
| editText.setSingleLine(true); |
| editText.setTransformationMethod(PasswordTransformationMethod.getInstance()); |
| editText.setKeyListener(DigitsKeyListener.getInstance()); |
| |
| editText.setVisibility(View.VISIBLE); |
| } |
| } |
| |
| @Override |
| protected void onDialogClosed(boolean positiveResult) { |
| super.onDialogClosed(positiveResult); |
| if (DBG) { |
| Log.d(LOG_TAG, "onDialogClosed: mButtonClicked=" + mButtonClicked + ", positiveResult=" |
| + positiveResult); |
| } |
| if (mButtonClicked != DialogInterface.BUTTON_NEGATIVE) { |
| String password = getEditText().getText().toString(); |
| |
| // Check if the password is valid. |
| if (password == null || password.length() != PW_LENGTH) { |
| Toast.makeText(getContext(), |
| getContext().getString(R.string.call_barring_right_pwd_number), |
| Toast.LENGTH_SHORT).show(); |
| return; |
| } |
| |
| if (DBG) { |
| Log.d(LOG_TAG, "onDialogClosed: password=" + password); |
| } |
| // Send set call barring message to RIL layer. |
| mPhone.setCallBarring(mFacility, !mIsActivated, password, |
| mHandler.obtainMessage(MyHandler.MESSAGE_SET_CALL_BARRING), |
| getServiceClassForCallBarring(mPhone)); |
| if (mTcpListener != null) { |
| mTcpListener.onStarted(this, false); |
| } |
| } |
| } |
| |
| void handleCallBarringResult(boolean status) { |
| mIsActivated = status; |
| if (DBG) { |
| Log.d(LOG_TAG, "handleCallBarringResult: mIsActivated=" + mIsActivated); |
| } |
| } |
| |
| private static int getServiceClassForCallBarring(Phone phone) { |
| int serviceClass = CarrierConfigManager.SERVICE_CLASS_VOICE; |
| PersistableBundle carrierConfig = PhoneGlobals.getInstance() |
| .getCarrierConfigForSubId(phone.getSubId()); |
| if (carrierConfig != null) { |
| serviceClass = carrierConfig.getInt( |
| CarrierConfigManager.KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT, |
| CarrierConfigManager.SERVICE_CLASS_VOICE); |
| } |
| return serviceClass; |
| } |
| |
| void updateSummaryText() { |
| notifyChanged(); |
| notifyDependencyChange(shouldDisableDependents()); |
| } |
| |
| @Override |
| public boolean shouldDisableDependents() { |
| return mIsActivated; |
| } |
| |
| // Message protocol: |
| // what: get vs. set |
| // arg1: action -- register vs. disable |
| // arg2: get vs. set for the preceding request |
| private static class MyHandler extends Handler { |
| private static final int MESSAGE_GET_CALL_BARRING = 0; |
| private static final int MESSAGE_SET_CALL_BARRING = 1; |
| |
| private final WeakReference<CallBarringEditPreference> mCallBarringEditPreference; |
| |
| private MyHandler(CallBarringEditPreference callBarringEditPreference) { |
| mCallBarringEditPreference = |
| new WeakReference<CallBarringEditPreference>(callBarringEditPreference); |
| } |
| |
| @Override |
| public void handleMessage(Message msg) { |
| switch (msg.what) { |
| case MESSAGE_GET_CALL_BARRING: |
| handleGetCallBarringResponse(msg); |
| break; |
| case MESSAGE_SET_CALL_BARRING: |
| handleSetCallBarringResponse(msg); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| // Handle the response message for query CB status. |
| private void handleGetCallBarringResponse(Message msg) { |
| final CallBarringEditPreference pref = mCallBarringEditPreference.get(); |
| if (pref == null) { |
| return; |
| } |
| |
| if (DBG) { |
| Log.d(LOG_TAG, "handleGetCallBarringResponse: done"); |
| } |
| |
| AsyncResult ar = (AsyncResult) msg.obj; |
| |
| if (msg.arg2 == MESSAGE_SET_CALL_BARRING) { |
| pref.mTcpListener.onFinished(pref, false); |
| } else { |
| pref.mTcpListener.onFinished(pref, true); |
| } |
| |
| // Unsuccessful query for call barring. |
| if (ar.exception != null) { |
| if (DBG) { |
| Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.exception=" + ar.exception); |
| } |
| pref.mTcpListener.onException(pref, (CommandException) ar.exception); |
| } else { |
| if (ar.userObj instanceof Throwable) { |
| pref.mTcpListener.onError(pref, RESPONSE_ERROR); |
| } |
| int[] ints = (int[]) ar.result; |
| if (ints.length == 0) { |
| if (DBG) { |
| Log.d(LOG_TAG, "handleGetCallBarringResponse: ar.result.length==0"); |
| } |
| pref.setEnabled(false); |
| pref.mTcpListener.onError(pref, RESPONSE_ERROR); |
| } else { |
| pref.handleCallBarringResult(ints[0] != 0); |
| if (DBG) { |
| Log.d(LOG_TAG, |
| "handleGetCallBarringResponse: CB state successfully queried: " |
| + ints[0]); |
| } |
| } |
| } |
| // Update call barring status. |
| pref.updateSummaryText(); |
| } |
| |
| // Handle the response message for CB settings. |
| private void handleSetCallBarringResponse(Message msg) { |
| final CallBarringEditPreference pref = mCallBarringEditPreference.get(); |
| if (pref == null) { |
| return; |
| } |
| |
| AsyncResult ar = (AsyncResult) msg.obj; |
| |
| if (ar.exception != null || ar.userObj instanceof Throwable) { |
| if (DBG) { |
| Log.d(LOG_TAG, "handleSetCallBarringResponse: ar.exception=" + ar.exception); |
| } |
| } |
| if (DBG) { |
| Log.d(LOG_TAG, "handleSetCallBarringResponse: re-get call barring option"); |
| } |
| pref.mPhone.getCallBarring( |
| pref.mFacility, |
| "", |
| obtainMessage(MESSAGE_GET_CALL_BARRING, 0, MESSAGE_SET_CALL_BARRING, |
| ar.exception), getServiceClassForCallBarring(pref.mPhone)); |
| } |
| } |
| } |