1810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal/*
2810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * Copyright (C) 2014 The Android Open Source Project
3810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal *
4810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * Licensed under the Apache License, Version 2.0 (the "License");
5810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * you may not use this file except in compliance with the License.
6810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * You may obtain a copy of the License at
7810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal *
8810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal *      http://www.apache.org/licenses/LICENSE-2.0
9810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal *
10810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * Unless required by applicable law or agreed to in writing, software
11810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * distributed under the License is distributed on an "AS IS" BASIS,
12810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * See the License for the specific language governing permissions and
14810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * limitations under the License.
15810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal */
16810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
18810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
19e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Leeimport android.os.RemoteException;
20e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Leeimport android.os.ServiceManager;
21810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepalimport android.telephony.TelephonyManager;
22810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
23e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Leeimport com.android.internal.telephony.ITelephonyRegistry;
24e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee
25810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal/**
26810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * Send a {@link TelephonyManager#ACTION_PHONE_STATE_CHANGED} broadcast when the call state
27810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * changes.
28810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal */
29810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepalfinal class PhoneStateBroadcaster extends CallsManagerListenerBase {
30e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee
318de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    private final CallsManager mCallsManager;
32e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    private final ITelephonyRegistry mRegistry;
33e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    private int mCurrentState = TelephonyManager.CALL_STATE_IDLE;
34e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee
358de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    public PhoneStateBroadcaster(CallsManager callsManager) {
368de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mCallsManager = callsManager;
37e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
38e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee                "telephony.registry"));
39e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        if (mRegistry == null) {
40e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee            Log.w(this, "TelephonyRegistry is null");
41e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        }
42e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    }
43e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee
44810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    @Override
456fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public void onCallStateChanged(Call call, int oldState, int newState) {
46f15dc33f87f88e21ef745952a68af65c86e1bf1eTyler Gunn        if (call.isExternalCall()) {
47f15dc33f87f88e21ef745952a68af65c86e1bf1eTyler Gunn            return;
48f15dc33f87f88e21ef745952a68af65c86e1bf1eTyler Gunn        }
49880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon        updateStates(call);
50810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    }
51810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
52e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    @Override
53e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    public void onCallAdded(Call call) {
541a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        if (call.isExternalCall()) {
551a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn            return;
561a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        }
57880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon        updateStates(call);
58880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon    }
59810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
60e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    @Override
61e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    public void onCallRemoved(Call call) {
621a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        if (call.isExternalCall()) {
631a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn            return;
641a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        }
651a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        updateStates(call);
661a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn    }
671a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn
681a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn    /**
691a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     * Handles changes to a call's external property.  If the call becomes external, we end up
701a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     * updating the call state to idle.  If the call becomes non-external, then the call state can
711a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     * update to off hook.
721a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     *
731a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     * @param call The call.
741a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     * @param isExternalCall {@code True} if the call is external, {@code false} otherwise.
751a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn     */
761a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn    @Override
771a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn    public void onExternalCallChanged(Call call, boolean isExternalCall) {
78880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon        updateStates(call);
79880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon    }
80880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon
81880b98372368b1d2be2ed34edaeb1e2f338d121aSantos Cordon    private void updateStates(Call call) {
82677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee        // Recalculate the current phone state based on the consolidated state of the remaining
83677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee        // calls in the call list.
841a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        // Note: CallsManager#hasRingingCall() and CallsManager#getFirstCallWithState(..) do not
851a40c4f4daf2cdfba3f67383c726f93b85a98b00Tyler Gunn        // consider external calls, so an external call is going to cause the state to be idle.
86677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee        int callState = TelephonyManager.CALL_STATE_IDLE;
878de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        if (mCallsManager.hasRingingCall()) {
88677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee            callState = TelephonyManager.CALL_STATE_RINGING;
891e37be5dd86a51b90e461f09dc8a89effe4aee21Tyler Gunn        } else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
901e37be5dd86a51b90e461f09dc8a89effe4aee21Tyler Gunn                CallState.ACTIVE, CallState.ON_HOLD) != null) {
91677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee            callState = TelephonyManager.CALL_STATE_OFFHOOK;
92e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        }
93677e811379dba9b0cce2230b770697d474ed8e56Yorke Lee        sendPhoneStateChangedBroadcast(call, callState);
94e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    }
95810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
96f86db2e63ec71781ac8214ed6d2603d02266143dYorke Lee    int getCallState() {
97f86db2e63ec71781ac8214ed6d2603d02266143dYorke Lee        return mCurrentState;
98f86db2e63ec71781ac8214ed6d2603d02266143dYorke Lee    }
99f86db2e63ec71781ac8214ed6d2603d02266143dYorke Lee
100e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee    private void sendPhoneStateChangedBroadcast(Call call, int phoneState) {
101e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        if (phoneState == mCurrentState) {
102e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee            return;
10312de5495028142b15c5e25508c77ff4506e29b57Ihab Awad        }
104810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
105e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        mCurrentState = phoneState;
106e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee
107e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        String callHandle = null;
108e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        if (call.getHandle() != null) {
109e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee            callHandle = call.getHandle().getSchemeSpecificPart();
110810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
11153fb8c103ab542608e0225eae1edfdf43bfa2273Sailesh Nepal
112e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        try {
113e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee            if (mRegistry != null) {
114e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee                mRegistry.notifyCallState(phoneState, callHandle);
115e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee                Log.i(this, "Broadcasted state change: %s", mCurrentState);
11653fb8c103ab542608e0225eae1edfdf43bfa2273Sailesh Nepal            }
117e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee        } catch (RemoteException e) {
118e19d33e309b1024261c085ddc1ee1e438442bb14Yorke Lee            Log.w(this, "RemoteException when notifying TelephonyRegistry of call state change.");
11953fb8c103ab542608e0225eae1edfdf43bfa2273Sailesh Nepal        }
120810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    }
121810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal}
122