blob: a5bc92ec8ca28ab2d5648e5cc4154c7adab89778 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001package com.android.phone;
2
SongFerngWang0e767992021-03-31 22:08:45 +08003import static com.android.phone.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
SongFerngWangebda2c52022-01-11 15:28:38 +08004import static com.android.phone.TimeConsumingPreferenceActivity.FDN_CHECK_FAILURE;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07005import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
6
7import android.content.Context;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07008import android.os.Handler;
9import android.os.Message;
SongFerngWangcf10dc92022-01-13 19:00:22 +080010import android.os.PersistableBundle;
fionaxue46e69f2017-04-27 14:32:46 -070011import android.preference.SwitchPreference;
SongFerngWangcf10dc92022-01-13 19:00:22 +080012import android.telephony.CarrierConfigManager;
SongFerngWang0e767992021-03-31 22:08:45 +080013import android.telephony.TelephonyManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070014import android.util.AttributeSet;
15import android.util.Log;
16
Aravind Sreekumarc94dea82018-04-10 15:34:32 -070017import com.android.internal.telephony.Phone;
18
SongFerngWang0e767992021-03-31 22:08:45 +080019import java.util.concurrent.Executors;
SongFerngWangcf10dc92022-01-13 19:00:22 +080020import java.util.concurrent.ScheduledExecutorService;
21import java.util.concurrent.TimeUnit;
22import java.util.function.Consumer;
SongFerngWang0e767992021-03-31 22:08:45 +080023
fionaxue46e69f2017-04-27 14:32:46 -070024public class CallWaitingSwitchPreference extends SwitchPreference {
25 private static final String LOG_TAG = "CallWaitingSwitchPreference";
SongFerngWangcf10dc92022-01-13 19:00:22 +080026 private static final int DELAY_MILLIS_FOR_USSD = 1000;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070027 private final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
28
29 private final MyHandler mHandler = new MyHandler();
Andrew Lee2b36ba22014-11-05 17:08:49 -080030 private Phone mPhone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070031 private TimeConsumingPreferenceListener mTcpListener;
SongFerngWangcf10dc92022-01-13 19:00:22 +080032 private ScheduledExecutorService mExecutor;
SongFerngWang0e767992021-03-31 22:08:45 +080033 private TelephonyManager mTelephonyManager;
34 private boolean mIsDuringUpdateProcess = false;
35 private int mUpdateStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
36 private int mQueryStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
SongFerngWangcf10dc92022-01-13 19:00:22 +080037 private boolean mUssdMode = false;
Pranav Madapurmath0af52d72024-03-29 15:11:10 -070038 private boolean mCwEnabled = false;
39 private boolean mCwClicked = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070040
fionaxue46e69f2017-04-27 14:32:46 -070041 public CallWaitingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042 super(context, attrs, defStyle);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070043 }
44
fionaxue46e69f2017-04-27 14:32:46 -070045 public CallWaitingSwitchPreference(Context context, AttributeSet attrs) {
46 this(context, attrs, com.android.internal.R.attr.switchPreferenceStyle);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070047 }
48
fionaxue46e69f2017-04-27 14:32:46 -070049 public CallWaitingSwitchPreference(Context context) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070050 this(context, null);
51 }
52
Andrew Lee2b36ba22014-11-05 17:08:49 -080053 /* package */ void init(
54 TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) {
55 mPhone = phone;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070056 mTcpListener = listener;
SongFerngWangcf10dc92022-01-13 19:00:22 +080057 mExecutor = Executors.newSingleThreadScheduledExecutor();
SongFerngWang0e767992021-03-31 22:08:45 +080058 mTelephonyManager = getContext().getSystemService(
59 TelephonyManager.class).createForSubscriptionId(phone.getSubId());
SongFerngWangcf10dc92022-01-13 19:00:22 +080060 CarrierConfigManager configManager = getContext().getSystemService(
61 CarrierConfigManager.class);
62 PersistableBundle bundle = configManager.getConfigForSubId(phone.getSubId());
63 mUssdMode = (bundle != null) ? bundle.getBoolean(
64 CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false) : false;
Pranav Madapurmath0af52d72024-03-29 15:11:10 -070065 mCwEnabled = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070066
67 if (!skipReading) {
SongFerngWang0e767992021-03-31 22:08:45 +080068 Log.d(LOG_TAG, "init getCallWaitingStatus");
69 mTelephonyManager.getCallWaitingStatus(mExecutor, this::queryStatusCallBack);
Santos Cordon7d4ddf62013-07-10 11:58:08 -070070 if (mTcpListener != null) {
71 mTcpListener.onStarted(this, true);
72 }
73 }
74 }
75
SongFerngWang0e767992021-03-31 22:08:45 +080076 private void queryStatusCallBack(int result) {
77 Log.d(LOG_TAG, "queryStatusCallBack: CW state " + result);
78 mQueryStatus = result;
79 mHandler.sendMessage(mHandler.obtainMessage(MyHandler.MESSAGE_UPDATE_CALL_WAITING));
80 }
81
82 private void updateStatusCallBack(int result) {
83 Log.d(LOG_TAG, "updateStatusCallBack: CW state " + result + ", and re get");
84 mUpdateStatus = result;
SongFerngWangcf10dc92022-01-13 19:00:22 +080085 if (mUssdMode) {
86 Log.d(LOG_TAG, "updateStatusCallBack: USSD mode needs to wait 1s since Framework"
87 + " has the limitation");
88 Consumer<Integer> resultListener = this::queryStatusCallBack;
89 try {
90 mExecutor.schedule(new Runnable() {
91 @Override
92 public void run() {
93 mTelephonyManager.getCallWaitingStatus(mExecutor, resultListener);
94 }
95 }, DELAY_MILLIS_FOR_USSD, TimeUnit.MILLISECONDS);
96 } catch (Exception e) {
97 Log.d(LOG_TAG, "Exception while waiting: " + e);
98 }
99 } else {
100 mTelephonyManager.getCallWaitingStatus(mExecutor, this::queryStatusCallBack);
101 }
SongFerngWang0e767992021-03-31 22:08:45 +0800102 }
103
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700104 @Override
105 protected void onClick() {
106 super.onClick();
Pranav Madapurmath0af52d72024-03-29 15:11:10 -0700107 mCwEnabled = isChecked();
108 mCwClicked = true;
109 mTelephonyManager.setCallWaitingEnabled(mCwEnabled, mExecutor, this::updateStatusCallBack);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700110 if (mTcpListener != null) {
SongFerngWang0e767992021-03-31 22:08:45 +0800111 mIsDuringUpdateProcess = true;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700112 mTcpListener.onStarted(this, false);
113 }
114 }
115
116 private class MyHandler extends Handler {
SongFerngWang0e767992021-03-31 22:08:45 +0800117 static final int MESSAGE_UPDATE_CALL_WAITING = 0;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700118
119 @Override
120 public void handleMessage(Message msg) {
121 switch (msg.what) {
SongFerngWang0e767992021-03-31 22:08:45 +0800122 case MESSAGE_UPDATE_CALL_WAITING:
123 updateUi();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700124 break;
125 }
126 }
127
SongFerngWang0e767992021-03-31 22:08:45 +0800128 private void updateUi() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129 if (mTcpListener != null) {
SongFerngWang0e767992021-03-31 22:08:45 +0800130 if (mIsDuringUpdateProcess) {
fionaxue46e69f2017-04-27 14:32:46 -0700131 mTcpListener.onFinished(CallWaitingSwitchPreference.this, false);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700132 } else {
fionaxue46e69f2017-04-27 14:32:46 -0700133 mTcpListener.onFinished(CallWaitingSwitchPreference.this, true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700134 }
135 }
136
SongFerngWangebda2c52022-01-11 15:28:38 +0800137 if (mQueryStatus != TelephonyManager.CALL_WAITING_STATUS_ENABLED
138 && mQueryStatus != TelephonyManager.CALL_WAITING_STATUS_DISABLED
139 && mQueryStatus != TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR) {
140 Log.d(LOG_TAG, "handleGetCallWaitingResponse: Exception:" + mQueryStatus);
141 int error = EXCEPTION_ERROR;
142 switch (mQueryStatus) {
143 case TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE:
144 error = FDN_CHECK_FAILURE;
145 break;
146 default:
147 error = EXCEPTION_ERROR;
148 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700149 }
SongFerngWangebda2c52022-01-11 15:28:38 +0800150 if (mTcpListener != null) {
151 mTcpListener.onError(CallWaitingSwitchPreference.this, error);
152 }
Pranav Madapurmath0af52d72024-03-29 15:11:10 -0700153 handleCwFallbackOnError();
154 setChecked(mCwEnabled);
SongFerngWangebda2c52022-01-11 15:28:38 +0800155 } else if (mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR
156 || (mIsDuringUpdateProcess && (
157 mUpdateStatus != TelephonyManager.CALL_WAITING_STATUS_ENABLED
158 && mUpdateStatus != TelephonyManager.CALL_WAITING_STATUS_DISABLED))) {
159 Log.d(LOG_TAG, "handleSetCallWaitingResponse: Exception");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700160 if (mTcpListener != null) {
fionaxue46e69f2017-04-27 14:32:46 -0700161 mTcpListener.onError(CallWaitingSwitchPreference.this, RESPONSE_ERROR);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700162 }
Pranav Madapurmath0af52d72024-03-29 15:11:10 -0700163 handleCwFallbackOnError();
164 setChecked(mCwEnabled);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700165 } else {
Pranav Madapurmath0af52d72024-03-29 15:11:10 -0700166 mCwEnabled = mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_ENABLED;
167 setChecked(mCwEnabled);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700168 }
SongFerngWang0e767992021-03-31 22:08:45 +0800169 mIsDuringUpdateProcess = false;
Pranav Madapurmath0af52d72024-03-29 15:11:10 -0700170 mCwClicked = false;
171 }
172 }
173
174 private void handleCwFallbackOnError() {
175 // Recover initial state before onClick.
176 if (mCwClicked) {
177 mCwEnabled = !mCwEnabled;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700178 }
179 }
180}