189647a60693ebdd94a0fc60da557d17d19847942Santos Cordon/* 289647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * Copyright (C) 2013 The Android Open Source Project 389647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * 489647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * Licensed under the Apache License, Version 2.0 (the "License"); 589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * you may not use this file except in compliance with the License. 689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * You may obtain a copy of the License at 789647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * 889647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * http://www.apache.org/licenses/LICENSE-2.0 989647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * 1089647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * Unless required by applicable law or agreed to in writing, software 1189647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * distributed under the License is distributed on an "AS IS" BASIS, 1289647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1389647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * See the License for the specific language governing permissions and 1489647a60693ebdd94a0fc60da557d17d19847942Santos Cordon * limitations under the License. 1589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon */ 1689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 1789647a60693ebdd94a0fc60da557d17d19847942Santos Cordonpackage com.android.phone; 1889647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 197984000187238151f2a5c46c7289db87df923050Yorke Leeimport android.Manifest; 2089647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.content.ComponentName; 2189647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.content.Context; 2289647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.content.Intent; 2389647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.content.ServiceConnection; 2411a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Chengimport android.content.pm.PackageManager; 2511a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Chengimport android.content.pm.ResolveInfo; 267984000187238151f2a5c46c7289db87df923050Yorke Leeimport android.content.pm.ServiceInfo; 2789647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.os.Handler; 2889647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.os.IBinder; 2989647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.os.Message; 3026c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Chengimport android.os.PowerManager; 3189647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.os.RemoteException; 3226c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Chengimport android.os.SystemClock; 3389647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.os.SystemProperties; 34de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Leeimport android.text.TextUtils; 3589647a60693ebdd94a0fc60da557d17d19847942Santos Cordonimport android.util.Log; 3689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 37de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Leeimport com.android.internal.telephony.Connection; 38de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Leeimport com.android.internal.telephony.Connection.PostDialState; 399b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordonimport com.android.phone.AudioRouter.AudioModeListener; 40362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Leeimport com.android.phone.NotificationMgr.StatusBarHelper; 419b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordonimport com.android.services.telephony.common.AudioMode; 42f404688cbde8e73c68c3b285cdd144c0b8580f8fSantos Cordonimport com.android.services.telephony.common.Call; 43345350ee0b6fa5c510e64b4b8cfb5ed1e5d70851Santos Cordonimport com.android.services.telephony.common.ICallHandlerService; 446c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Chengimport com.google.common.collect.Lists; 4589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 46a3d0514c3480db25a813d8841c39e965f2925180Santos Cordonimport java.util.List; 47a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon 4889647a60693ebdd94a0fc60da557d17d19847942Santos Cordon/** 49345350ee0b6fa5c510e64b4b8cfb5ed1e5d70851Santos Cordon * This class is responsible for passing through call state changes to the CallHandlerService. 5089647a60693ebdd94a0fc60da557d17d19847942Santos Cordon */ 516c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Chengpublic class CallHandlerServiceProxy extends Handler 526c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng implements CallModeler.Listener, AudioModeListener { 5389647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 54345350ee0b6fa5c510e64b4b8cfb5ed1e5d70851Santos Cordon private static final String TAG = CallHandlerServiceProxy.class.getSimpleName(); 5571d5c6e4d0036e30eaa6a23faf0c246934ef8e6bSantos Cordon private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt( 566c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng "ro.debuggable", 0) == 1); 57e41661cbc5db3cbb8e60e0137fbac3f3a1f506a5Chiao Cheng 586c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng public static final int RETRY_DELAY_MILLIS = 2000; 5970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon public static final int RETRY_DELAY_LONG_MILLIS = 30 * 1000; // 30 seconds 606c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private static final int BIND_RETRY_MSG = 1; 6170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon private static final int MAX_SHORT_DELAY_RETRY_COUNT = 5; 6289647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 63593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon private AudioRouter mAudioRouter; 64593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon private CallCommandService mCallCommandService; 6563a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon private CallModeler mCallModeler; 66593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon private Context mContext; 67f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon private boolean mFullUpdateOnConnect; 68d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng 696c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private ICallHandlerService mCallHandlerServiceGuarded; // Guarded by mServiceAndQueueLock 70d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng // Single queue to guarantee ordering 71d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private List<QueueParams> mQueue; // Guarded by mServiceAndQueueLock 72d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng 736c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private final Object mServiceAndQueueLock = new Object(); 746c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private int mBindRetryCount = 0; 756c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng 766c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng @Override 776c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng public void handleMessage(Message msg) { 786c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng super.handleMessage(msg); 796c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng 806c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng switch (msg.what) { 816c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng case BIND_RETRY_MSG: 8270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon handleConnectRetry(); 836c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng break; 846c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 856c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 8689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 8763a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon public CallHandlerServiceProxy(Context context, CallModeler callModeler, 88593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon CallCommandService callCommandService, AudioRouter audioRouter) { 896c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 906c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "init CallHandlerServiceProxy"); 916c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 9289647a60693ebdd94a0fc60da557d17d19847942Santos Cordon mContext = context; 93cba1b444f3c4f94b7be1e07b39ba4873a11f379fSantos Cordon mCallCommandService = callCommandService; 9463a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon mCallModeler = callModeler; 95593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon mAudioRouter = audioRouter; 9689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 97593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon mAudioRouter.addAudioModeListener(this); 98daf7bf63f4f104977b01623e4f36a50db190d47cChristine Chen mCallModeler.addListener(this); 9963a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon } 10063a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon 10163a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon @Override 102995c816b6a596ccd48628c1da4199ea9e8a830b2Santos Cordon public void onDisconnect(Call call) { 10326c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng // Wake up in case the screen was off. 10426c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng wakeUpScreen(); 1053e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 1063e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded == null) { 1073e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (DBG) { 1083e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "CallHandlerService not connected. Enqueue disconnect"); 1096c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 1103e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng enqueueDisconnect(call); 1113e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng setupServiceConnection(); 1123e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng return; 11363a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon } 1143e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1153e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processDisconnect(call); 1163e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1173e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 11826c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng private void wakeUpScreen() { 11926c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng Log.d(TAG, "wakeUpScreen()"); 12026c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 12126c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng pm.wakeUp(SystemClock.uptimeMillis()); 12226c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng } 12326c6e92b6bb096e7f4a863f8dba2c64bdb5c34b0Chiao Cheng 1243e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private void processDisconnect(Call call) { 1253e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng try { 1266c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 1276c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "onDisconnect: " + call); 12863a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon } 1293e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 1303e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded != null) { 1313e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mCallHandlerServiceGuarded.onDisconnect(call); 1323e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1333e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1343e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (!mCallModeler.hasLiveCall()) { 1353e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng unbind(); 1363e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1376c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } catch (Exception e) { 1386c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.e(TAG, "Remote exception handling onDisconnect ", e); 13989647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 14089647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 14189647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 142a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon @Override 1436c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng public void onIncoming(Call call) { 14470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // for new incoming calls, reset the retry count. 14570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon resetConnectRetryCount(); 14670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 1473e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 1483e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded == null) { 1493e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (DBG) { 1503e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "CallHandlerService not connected. Enqueue incoming."); 1516c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 1523e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng enqueueIncoming(call); 1533e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng setupServiceConnection(); 1543e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng return; 1556c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 1563e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1573e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processIncoming(call); 1583e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1593e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 1603e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private void processIncoming(Call call) { 1613e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (DBG) { 1623e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "onIncoming: " + call); 1633e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1643e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng try { 1653e0f0414daa2266dc51b77198fe433797f7d610aChristine Chen // TODO: check RespondViaSmsManager.allowRespondViaSmsForCall() 1666c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // must refactor call method to accept proper call object. 1673e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 1683e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded != null) { 1693e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mCallHandlerServiceGuarded.onIncoming(call, 1703e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng RejectWithTextMessageManager.loadCannedResponses()); 1713e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1723e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1736c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } catch (Exception e) { 1746c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.e(TAG, "Remote exception handling onUpdate", e); 175ee09a49b24b2228f7ea7fb3d3be7a551120abb1aChristine Chen } 176ee09a49b24b2228f7ea7fb3d3be7a551120abb1aChristine Chen } 177ee09a49b24b2228f7ea7fb3d3be7a551120abb1aChristine Chen 178ee09a49b24b2228f7ea7fb3d3be7a551120abb1aChristine Chen @Override 1796c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng public void onUpdate(List<Call> calls) { 1803e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 1813e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded == null) { 1823e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (DBG) { 1833e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "CallHandlerService not connected. Enqueue update."); 1843e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1853e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng enqueueUpdate(calls); 1863e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng setupServiceConnection(); 1873e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng return; 1883e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1893e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1903e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processUpdate(calls); 1913e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1923e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 1933e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private void processUpdate(List<Call> calls) { 1943e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (DBG) { 1953e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "onUpdate: " + calls.toString()); 1963e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 1976c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng try { 1986c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 1993e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded != null) { 2003e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mCallHandlerServiceGuarded.onUpdate(calls); 2016c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 202a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon } 2033e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (!mCallModeler.hasLiveCall()) { 2043e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // TODO: unbinding happens in both onUpdate and onDisconnect because the ordering 2053e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // is not deterministic. Unbinding in both ensures that the service is unbound. 2063e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // But it also makes this in-efficient because we are unbinding twice, which leads 2073e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // to the CallHandlerService performing onCreate() and onDestroy() twice for each 2083e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // disconnect. 2093e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng unbind(); 210a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon } 2116c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } catch (Exception e) { 2126c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.e(TAG, "Remote exception handling onUpdate", e); 213a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon } 214a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon } 215a3d0514c3480db25a813d8841c39e965f2925180Santos Cordon 2163f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng 2173f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng @Override 218de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Lee public void onPostDialAction(Connection.PostDialState state, int callId, String remainingChars, 219de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Lee char currentChar) { 220de41f67985e48d9cc17d48a9299648966b9bc7e5Yorke Lee if (state != PostDialState.WAIT) return; 2213f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng try { 2223f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng synchronized (mServiceAndQueueLock) { 2233f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng if (mCallHandlerServiceGuarded == null) { 2243f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng if (DBG) { 2253f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng Log.d(TAG, "CallHandlerService not conneccted. Skipping " 2263f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng + "onPostDialWait()."); 2273f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } 2283f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng return; 2293f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } 2303f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } 2313f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng 2323f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng mCallHandlerServiceGuarded.onPostDialWait(callId, remainingChars); 2333f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } catch (Exception e) { 2343f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng Log.e(TAG, "Remote exception handling onUpdate", e); 2353f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } 2363f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng } 2373f015c9e837c4e7a2b710d32f16e81eb684dda74Chiao Cheng 2389b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordon @Override 239cd95f62ea9f94c06d01debfcd1f01fd2cd6e2708Santos Cordon public void onAudioModeChange(int newMode, boolean muted) { 2406c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng try { 2416c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 2426c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (mCallHandlerServiceGuarded == null) { 2436c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 2446c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "CallHandlerService not conneccted. Skipping " 2456c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng + "onAudioModeChange()."); 2466c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 2476c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng return; 2486c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 2496c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 2509b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordon 2516c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // Just do a simple log for now. 2526c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.i(TAG, "Updating with new audio mode: " + AudioMode.toString(newMode) + 253cd95f62ea9f94c06d01debfcd1f01fd2cd6e2708Santos Cordon " with mute " + muted); 254593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon 255cd95f62ea9f94c06d01debfcd1f01fd2cd6e2708Santos Cordon mCallHandlerServiceGuarded.onAudioModeChange(newMode, muted); 2566c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } catch (Exception e) { 2576c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.e(TAG, "Remote exception handling onAudioModeChange", e); 2589b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordon } 2599b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordon } 2609b7bac7705b3afcae7b010edc2032c7c0f37f770Santos Cordon 261593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon @Override 262593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon public void onSupportedAudioModeChange(int modeMask) { 2636c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng try { 2646c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 2656c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (mCallHandlerServiceGuarded == null) { 2666c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 2676c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "CallHandlerService not conneccted. Skipping" 2686c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng + "onSupportedAudioModeChange()."); 2696c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 2706c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng return; 2716c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 272593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon } 273593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon 2746c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 2756c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "onSupportAudioModeChange: " + AudioMode.toString(modeMask)); 276593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon } 27789647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 2786c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng mCallHandlerServiceGuarded.onSupportedAudioModeChange(modeMask); 2796c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } catch (Exception e) { 2806c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.e(TAG, "Remote exception handling onAudioModeChange", e); 281593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon } 282af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 283593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon } 284406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon 2853e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private ServiceConnection mConnection = null; 2863e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 2873e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private class InCallServiceConnection implements ServiceConnection { 2886c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng @Override public void onServiceConnected (ComponentName className, IBinder service){ 2896c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng if (DBG) { 2906c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.d(TAG, "Service Connected"); 29189647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 2926c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng onCallHandlerServiceConnected(ICallHandlerService.Stub.asInterface(service)); 29370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon resetConnectRetryCount(); 29489647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 29589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 2966c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng @Override public void onServiceDisconnected (ComponentName className){ 2976c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng Log.i(TAG, "Disconnected from UI service."); 2986c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 2996c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // Technically, unbindService is un-necessary since the framework will schedule and 3006c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // restart the crashed service. But there is a exponential backoff for the restart. 3016c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // Unbind explicitly and setup again to avoid the backoff since it's important to 3026c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng // always have an in call ui. 3033e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng unbind(); 3043e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 305f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon reconnectOnRemainingCalls(); 306af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 307af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 3083e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 3096c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng 310bcf2099b92870b863f53e79288d4c8e73a4dc42dMakoto Onuki public void bringToForeground(boolean showDialpad) { 311406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon // only support this call if the service is already connected. 31219d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon synchronized (mServiceAndQueueLock) { 31319d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon if (mCallHandlerServiceGuarded != null && mCallModeler.hasLiveCall()) { 31419d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon try { 315bcf2099b92870b863f53e79288d4c8e73a4dc42dMakoto Onuki if (DBG) Log.d(TAG, "bringToForeground: " + showDialpad); 316bcf2099b92870b863f53e79288d4c8e73a4dc42dMakoto Onuki mCallHandlerServiceGuarded.bringToForeground(showDialpad); 31719d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon } catch (RemoteException e) { 31819d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon Log.e(TAG, "Exception handling bringToForeground", e); 31919d814b12a6ba77ba93ee5d8f3b46ca979d8e5caSantos Cordon } 320406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon } 321406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon } 322406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon } 323593ab38970a84a60ac39edba4306647c8b66436dSantos Cordon 3243e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private static Intent getInCallServiceIntent(Context context) { 3253e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng final Intent serviceIntent = new Intent(ICallHandlerService.class.getName()); 3263e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng final ComponentName component = new ComponentName(context.getResources().getString( 327d3105fe2f9f544fccd2cddbb1ab977dfe157b56eYorke Lee R.string.ui_default_package), context.getResources().getString( 328d3105fe2f9f544fccd2cddbb1ab977dfe157b56eYorke Lee R.string.incall_default_class)); 3293e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng serviceIntent.setComponent(component); 3303e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng return serviceIntent; 3313e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 3323e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 33389647a60693ebdd94a0fc60da557d17d19847942Santos Cordon /** 334345350ee0b6fa5c510e64b4b8cfb5ed1e5d70851Santos Cordon * Sets up the connection with ICallHandlerService 33589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon */ 33689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon private void setupServiceConnection() { 3373e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (!PhoneGlobals.sVoiceCapable) { 3383e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng return; 3393e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 34011a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Cheng 3413e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng final Intent serviceIntent = getInCallServiceIntent(mContext); 34211a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Cheng if (DBG) { 34311a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Cheng Log.d(TAG, "binding to service " + serviceIntent); 34411a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Cheng } 34511a4b650d5b5203045d82f37a10b2eb7623cf639Chiao Cheng 3466c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 3473e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mConnection == null) { 3483e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mConnection = new InCallServiceConnection(); 3493e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 35070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon boolean failedConnection = false; 3513e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng final PackageManager packageManger = mContext.getPackageManager(); 3523e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng final List<ResolveInfo> services = packageManger.queryIntentServices(serviceIntent, 3533e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 0); 3547984000187238151f2a5c46c7289db87df923050Yorke Lee 3557984000187238151f2a5c46c7289db87df923050Yorke Lee ServiceInfo serviceInfo = null; 3567984000187238151f2a5c46c7289db87df923050Yorke Lee 3577984000187238151f2a5c46c7289db87df923050Yorke Lee for (int i = 0; i < services.size(); i++) { 3587984000187238151f2a5c46c7289db87df923050Yorke Lee final ResolveInfo info = services.get(i); 3597984000187238151f2a5c46c7289db87df923050Yorke Lee if (info.serviceInfo != null) { 3607984000187238151f2a5c46c7289db87df923050Yorke Lee if (Manifest.permission.BIND_CALL_SERVICE.equals( 3617984000187238151f2a5c46c7289db87df923050Yorke Lee info.serviceInfo.permission)) { 3627984000187238151f2a5c46c7289db87df923050Yorke Lee serviceInfo = info.serviceInfo; 3637984000187238151f2a5c46c7289db87df923050Yorke Lee break; 3647984000187238151f2a5c46c7289db87df923050Yorke Lee } 3657984000187238151f2a5c46c7289db87df923050Yorke Lee } 3667984000187238151f2a5c46c7289db87df923050Yorke Lee } 3677984000187238151f2a5c46c7289db87df923050Yorke Lee 3687984000187238151f2a5c46c7289db87df923050Yorke Lee if (serviceInfo == null) { 3693e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // Service not found, retry again after some delay 3703e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // This can happen if the service is being installed by the package manager. 3713e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // Between deletes and installs, bindService could get a silent service not 3723e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng // found error. 37370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.w(TAG, "Default call handler service not found."); 37470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon failedConnection = true; 37570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } else { 3763e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 37770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon serviceIntent.setComponent(new ComponentName(serviceInfo.packageName, 37870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon serviceInfo.name)); 37970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (DBG) { 38070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.d(TAG, "binding to service " + serviceIntent); 38170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 38270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (!mContext.bindService(serviceIntent, mConnection, 38370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Context.BIND_AUTO_CREATE)) { 38470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // This happens when the in-call package is in the middle of being installed 38570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.w(TAG, "Could not bind to default call handler service: " + 38670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon serviceIntent.getComponent()); 38770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon failedConnection = true; 3886c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 38989647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 3903e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 39170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (failedConnection) { 39270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon mConnection = null; 39370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon enqueueConnectRetry(); 39470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 3953e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } else { 3963e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "Service connection to in call service already started."); 3973e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 3983e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 3993e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 4003e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng 40170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon private void resetConnectRetryCount() { 40270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon mBindRetryCount = 0; 40370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 40470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 40570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon private void incrementRetryCount() { 40670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // Reset to the short delay retry count to avoid overflow 40770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (Integer.MAX_VALUE == mBindRetryCount) { 40870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon mBindRetryCount = MAX_SHORT_DELAY_RETRY_COUNT; 40970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 41070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 41170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon mBindRetryCount++; 41270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 41370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 41470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon private void handleConnectRetry() { 41570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // Remove any pending messages since we're already performing the action. 41670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // If the call to setupServiceConnection() fails, it will queue up another retry. 41770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon removeMessages(BIND_RETRY_MSG); 41870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 41970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // Something else triggered the connection, cancel. 42070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (mConnection != null) { 42170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.i(TAG, "Retry: already connected."); 42270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon return; 42370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 42470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 42570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (mCallModeler.hasLiveCall()) { 42670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // Update the count when we are actually trying the retry instead of when the 42770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // retry is queued up. 42870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon incrementRetryCount(); 42970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 43070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.i(TAG, "Retrying connection: " + mBindRetryCount); 43170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon setupServiceConnection(); 43270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } else { 43370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.i(TAG, "Canceling connection retry since there are no calls."); 43470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // We are not currently connected and there is no call so lets not bother 43570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // with the retry. Also, empty the queue of pending messages to send 43670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // to the UI. 43770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon synchronized (mServiceAndQueueLock) { 43870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon if (mQueue != null) { 43970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon mQueue.clear(); 44070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 44170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 44270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 44370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon // Since we have no calls, reset retry count. 44470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon resetConnectRetryCount(); 44570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 44670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 44770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 44870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon /** 44970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon * Called after the connection failed and a retry is needed. 45070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon * Queues up a retry to happen with a delay. 45170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon */ 45270d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon private void enqueueConnectRetry() { 45370d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon final boolean isLongDelay = (mBindRetryCount > MAX_SHORT_DELAY_RETRY_COUNT); 45470d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon final int delay = isLongDelay ? RETRY_DELAY_LONG_MILLIS : RETRY_DELAY_MILLIS; 45570d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 45670d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon Log.w(TAG, "InCallUI Connection failed. Enqueuing delayed retry for " + delay + " ms." + 45770d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon " retries(" + mBindRetryCount + ")"); 45870d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 45970d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon sendEmptyMessageDelayed(BIND_RETRY_MSG, delay); 46070d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon } 46170d3866b170effeb64cacbdb59e3a5161447c944Santos Cordon 4623e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng private void unbind() { 4633e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 464362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee // On unbind, reenable the notification shade and navigation bar just in case the 465362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee // in-call UI crashed on an incoming call. 466362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee final StatusBarHelper statusBarHelper = PhoneGlobals.getInstance().notificationMgr. 467362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee statusBarHelper; 468362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee statusBarHelper.enableSystemBarNavigation(true); 469362cec21b259ce1a8bfe69a873a7e90293f8b33dYorke Lee statusBarHelper.enableExpandedView(true); 4703e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mCallHandlerServiceGuarded != null) { 4713e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng Log.d(TAG, "Unbinding service."); 4723e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mCallHandlerServiceGuarded = null; 4733e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mContext.unbindService(mConnection); 47489647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 4753e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mConnection = null; 476af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 477af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 478af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 479af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon /** 480cba1b444f3c4f94b7be1e07b39ba4873a11f379fSantos Cordon * Called when the in-call UI service is connected. Send command interface to in-call. 481cba1b444f3c4f94b7be1e07b39ba4873a11f379fSantos Cordon */ 48263a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon private void onCallHandlerServiceConnected(ICallHandlerService callHandlerService) { 483d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng 4846c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng synchronized (mServiceAndQueueLock) { 4856c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng mCallHandlerServiceGuarded = callHandlerService; 48689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 487ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon // Before we send any updates, we need to set up the initial service calls. 488ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon makeInitialServiceCalls(); 489ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon 490d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng processQueue(); 491f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon 492f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon if (mFullUpdateOnConnect) { 493f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon mFullUpdateOnConnect = false; 494f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon onUpdate(mCallModeler.getFullList()); 495f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon } 496f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon } 497f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon } 498f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon 499f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon /** 500f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon * Checks to see if there are any live calls left, and if so, try reconnecting the UI. 501f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon */ 502f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon private void reconnectOnRemainingCalls() { 503f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon if (mCallModeler.hasLiveCall()) { 504f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon mFullUpdateOnConnect = true; 505f9ad0640b8f71c0f3ee0d5a46e6f709b0827f544Santos Cordon setupServiceConnection(); 5066c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 507ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon } 508af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 509ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon /** 510ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon * Makes initial service calls to set up callcommandservice and audio modes. 511ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon */ 512ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon private void makeInitialServiceCalls() { 5136c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng try { 51412a03aa7bf49224d531f7469cdcd019e1b0f155eSantos Cordon mCallHandlerServiceGuarded.startCallService(mCallCommandService); 515ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon 516ad07819ef0a3968cf562ccc87c2be9417db08328Santos Cordon onSupportedAudioModeChange(mAudioRouter.getSupportedAudioModes()); 5178fd0ec73400aed9ad5e46d46befb20b2b1008338Santos Cordon onAudioModeChange(mAudioRouter.getAudioMode(), mAudioRouter.getMute()); 518cba1b444f3c4f94b7be1e07b39ba4873a11f379fSantos Cordon } catch (RemoteException e) { 51963a8424848966c0e94a78c4200bb091366dca3b8Santos Cordon Log.e(TAG, "Remote exception calling CallHandlerService::setCallCommandService", e); 52089647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 52189647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 522af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 523d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private List<QueueParams> getQueue() { 524d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng if (mQueue == null) { 525d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng mQueue = Lists.newArrayList(); 526d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng } 527d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng return mQueue; 528d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng } 52989647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 5306c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private void enqueueDisconnect(Call call) { 531d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng getQueue().add(new QueueParams(QueueParams.METHOD_DISCONNECT, new Call(call))); 53289647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 53389647a60693ebdd94a0fc60da557d17d19847942Santos Cordon 5346c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private void enqueueIncoming(Call call) { 535d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng getQueue().add(new QueueParams(QueueParams.METHOD_INCOMING, new Call(call))); 536af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 537af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 5386c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng private void enqueueUpdate(List<Call> calls) { 5396c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng final List<Call> copy = Lists.newArrayList(); 5406c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng for (Call call : calls) { 5416c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng copy.add(new Call(call)); 5426c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 543c340ba99a03178987c15789cbca0994190c15fd6Chiao Cheng getQueue().add(new QueueParams(QueueParams.METHOD_UPDATE, copy)); 544af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon } 545af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 546d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private void processQueue() { 5473e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng synchronized (mServiceAndQueueLock) { 5483e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng if (mQueue != null) { 5493e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng for (QueueParams params : mQueue) { 5503e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng switch (params.mMethod) { 5513e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng case QueueParams.METHOD_INCOMING: 5523e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processIncoming((Call) params.mArg); 5533e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng break; 5543e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng case QueueParams.METHOD_UPDATE: 5553e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processUpdate((List<Call>) params.mArg); 5563e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng break; 5573e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng case QueueParams.METHOD_DISCONNECT: 5583e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng processDisconnect((Call) params.mArg); 5593e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng break; 5603e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng default: 5613e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng throw new IllegalArgumentException("Method type " + params.mMethod + 5623e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng " not recognized."); 5633e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 5643e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng } 5653e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mQueue.clear(); 5663e6486e012ce6c15675cd0d2f20155e5a49ed0aeChiao Cheng mQueue = null; 5676c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 5686c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 5696c6b27265806a053193b8ccbc57f66b1feb8e5abChiao Cheng } 570cba1b444f3c4f94b7be1e07b39ba4873a11f379fSantos Cordon 571d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng /** 572d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng * Holds method parameters. 573d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng */ 574d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private static class QueueParams { 575d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private static final int METHOD_INCOMING = 1; 576d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private static final int METHOD_UPDATE = 2; 577d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private static final int METHOD_DISCONNECT = 3; 578af763a15f376f8248684b02695d38a5a08e61ac3Santos Cordon 579d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private final int mMethod; 580d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private final Object mArg; 581d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng 582d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng private QueueParams(int method, Object arg) { 583d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng mMethod = method; 584d38eebcd68a92b7ba1ebb1b79530b98b594e04c2Chiao Cheng this.mArg = arg; 58589647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 58689647a60693ebdd94a0fc60da557d17d19847942Santos Cordon } 58789647a60693ebdd94a0fc60da557d17d19847942Santos Cordon} 588