Home | History | Annotate | Download | only in telecom
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.telecom;
     18 
     19 import android.os.RemoteException;
     20 import android.os.ServiceManager;
     21 import android.telecom.Log;
     22 import android.telephony.TelephonyManager;
     23 
     24 import com.android.internal.telephony.ITelephonyRegistry;
     25 
     26 /**
     27  * Send a {@link TelephonyManager#ACTION_PHONE_STATE_CHANGED} broadcast when the call state
     28  * changes.
     29  */
     30 final class PhoneStateBroadcaster extends CallsManagerListenerBase {
     31 
     32     private final CallsManager mCallsManager;
     33     private final ITelephonyRegistry mRegistry;
     34     private int mCurrentState = TelephonyManager.CALL_STATE_IDLE;
     35 
     36     public PhoneStateBroadcaster(CallsManager callsManager) {
     37         mCallsManager = callsManager;
     38         mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
     39                 "telephony.registry"));
     40         if (mRegistry == null) {
     41             Log.w(this, "TelephonyRegistry is null");
     42         }
     43     }
     44 
     45     @Override
     46     public void onCallStateChanged(Call call, int oldState, int newState) {
     47         if (call.isExternalCall()) {
     48             return;
     49         }
     50         updateStates(call);
     51     }
     52 
     53     @Override
     54     public void onCallAdded(Call call) {
     55         if (call.isExternalCall()) {
     56             return;
     57         }
     58         updateStates(call);
     59     }
     60 
     61     @Override
     62     public void onCallRemoved(Call call) {
     63         if (call.isExternalCall()) {
     64             return;
     65         }
     66         updateStates(call);
     67     }
     68 
     69     /**
     70      * Handles changes to a call's external property.  If the call becomes external, we end up
     71      * updating the call state to idle.  If the call becomes non-external, then the call state can
     72      * update to off hook.
     73      *
     74      * @param call The call.
     75      * @param isExternalCall {@code True} if the call is external, {@code false} otherwise.
     76      */
     77     @Override
     78     public void onExternalCallChanged(Call call, boolean isExternalCall) {
     79         updateStates(call);
     80     }
     81 
     82     private void updateStates(Call call) {
     83         // Recalculate the current phone state based on the consolidated state of the remaining
     84         // calls in the call list.
     85         // Note: CallsManager#hasRingingCall() and CallsManager#getFirstCallWithState(..) do not
     86         // consider external calls, so an external call is going to cause the state to be idle.
     87         int callState = TelephonyManager.CALL_STATE_IDLE;
     88         if (mCallsManager.hasRingingCall()) {
     89             callState = TelephonyManager.CALL_STATE_RINGING;
     90         } else if (mCallsManager.getFirstCallWithState(CallState.DIALING, CallState.PULLING,
     91                 CallState.ACTIVE, CallState.ON_HOLD) != null) {
     92             callState = TelephonyManager.CALL_STATE_OFFHOOK;
     93         }
     94         sendPhoneStateChangedBroadcast(call, callState);
     95     }
     96 
     97     int getCallState() {
     98         return mCurrentState;
     99     }
    100 
    101     private void sendPhoneStateChangedBroadcast(Call call, int phoneState) {
    102         if (phoneState == mCurrentState) {
    103             return;
    104         }
    105 
    106         mCurrentState = phoneState;
    107 
    108         String callHandle = null;
    109         // Only report phone numbers in phone state broadcast for regular mobile calls; do not
    110         // include numbers from 3rd party apps.
    111         if (!call.isSelfManaged() && call.getHandle() != null) {
    112             callHandle = call.getHandle().getSchemeSpecificPart();
    113         }
    114 
    115         try {
    116             if (mRegistry != null) {
    117                 mRegistry.notifyCallState(phoneState, callHandle);
    118                 Log.i(this, "Broadcasted state change: %s", mCurrentState);
    119             }
    120         } catch (RemoteException e) {
    121             Log.w(this, "RemoteException when notifying TelephonyRegistry of call state change.");
    122         }
    123     }
    124 }
    125