blob: d5745896a4b84fdbe5e5892ef7da7c0ec7e727ad [file] [log] [blame]
/*
* Copyright (C) 2014 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.server.telecom;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telecom.Log;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.ITelephonyRegistry;
/**
* Send a {@link TelephonyManager#ACTION_PHONE_STATE_CHANGED} broadcast when the call state
* changes.
*/
final class PhoneStateBroadcaster extends CallsManagerListenerBase {
private final CallsManager mCallsManager;
private final ITelephonyRegistry mRegistry;
private int mCurrentState = TelephonyManager.CALL_STATE_IDLE;
public PhoneStateBroadcaster(CallsManager callsManager) {
mCallsManager = callsManager;
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry"));
if (mRegistry == null) {
Log.w(this, "TelephonyRegistry is null");
}
}
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
if (call.isExternalCall()) {
return;
}
updateStates(call);
}
@Override
public void onCallAdded(Call call) {
if (call.isExternalCall()) {
return;
}
updateStates(call);
}
@Override
public void onCallRemoved(Call call) {
if (call.isExternalCall()) {
return;
}
updateStates(call);
}
/**
* Handles changes to a call's external property. If the call becomes external, we end up
* updating the call state to idle. If the call becomes non-external, then the call state can
* update to off hook.
*
* @param call The call.
* @param isExternalCall {@code True} if the call is external, {@code false} otherwise.
*/
@Override
public void onExternalCallChanged(Call call, boolean isExternalCall) {
updateStates(call);
}
private void updateStates(Call call) {
// Recalculate the current phone state based on the consolidated state of the remaining
// calls in the call list.
// Note: CallsManager#hasRingingCall() and CallsManager#getFirstCallWithState(..) do not
// consider external calls, so an external call is going to cause the state to be idle.
int callState = TelephonyManager.CALL_STATE_IDLE;
if (mCallsManager.hasRingingCall()) {
callState = TelephonyManager.CALL_STATE_RINGING;
} else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
CallState.ACTIVE, CallState.ON_HOLD) != null) {
callState = TelephonyManager.CALL_STATE_OFFHOOK;
}
sendPhoneStateChangedBroadcast(call, callState);
}
int getCallState() {
return mCurrentState;
}
private void sendPhoneStateChangedBroadcast(Call call, int phoneState) {
if (phoneState == mCurrentState) {
return;
}
mCurrentState = phoneState;
String callHandle = null;
// Only report phone numbers in phone state broadcast for regular mobile calls; do not
// include numbers from 3rd party apps.
if (!call.isSelfManaged() && call.getHandle() != null) {
callHandle = call.getHandle().getSchemeSpecificPart();
}
try {
if (mRegistry != null) {
mRegistry.notifyCallState(phoneState, callHandle);
Log.i(this, "Broadcasted state change: %s", mCurrentState);
}
} catch (RemoteException e) {
Log.w(this, "RemoteException when notifying TelephonyRegistry of call state change.");
}
}
}