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.incallui; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.IBinder; 22 import android.os.Trace; 23 import android.telecom.Call; 24 import android.telecom.CallAudioState; 25 import android.telecom.InCallService; 26 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; 27 import com.android.dialer.feedback.FeedbackComponent; 28 import com.android.incallui.audiomode.AudioModeProvider; 29 import com.android.incallui.call.CallList; 30 import com.android.incallui.call.ExternalCallList; 31 import com.android.incallui.call.TelecomAdapter; 32 import com.android.incallui.speakeasy.SpeakEasyCallManager; 33 import com.android.incallui.speakeasy.SpeakEasyComponent; 34 35 /** 36 * Used to receive updates about calls from the Telecom component. This service is bound to Telecom 37 * while there exist calls which potentially require UI. This includes ringing (incoming), dialing 38 * (outgoing), and active calls. When the last call is disconnected, Telecom will unbind to the 39 * service triggering InCallActivity (via CallList) to finish soon after. 40 */ 41 public class InCallServiceImpl extends InCallService { 42 43 private ReturnToCallController returnToCallController; 44 private CallList.Listener feedbackListener; 45 // We only expect there to be one speakEasyCallManager to be instantiated at a time. 46 // We did not use a singleton SpeakEasyCallManager to avoid holding on to state beyond the 47 // lifecycle of this service, because the singleton is associated with the state of the 48 // Application, not this service. 49 private SpeakEasyCallManager speakEasyCallManager; 50 51 @Override onCallAudioStateChanged(CallAudioState audioState)52 public void onCallAudioStateChanged(CallAudioState audioState) { 53 Trace.beginSection("InCallServiceImpl.onCallAudioStateChanged"); 54 AudioModeProvider.getInstance().onAudioStateChanged(audioState); 55 Trace.endSection(); 56 } 57 58 @Override onBringToForeground(boolean showDialpad)59 public void onBringToForeground(boolean showDialpad) { 60 Trace.beginSection("InCallServiceImpl.onBringToForeground"); 61 InCallPresenter.getInstance().onBringToForeground(showDialpad); 62 Trace.endSection(); 63 } 64 65 @Override onCallAdded(Call call)66 public void onCallAdded(Call call) { 67 Trace.beginSection("InCallServiceImpl.onCallAdded"); 68 InCallPresenter.getInstance().onCallAdded(call); 69 Trace.endSection(); 70 } 71 72 @Override onCallRemoved(Call call)73 public void onCallRemoved(Call call) { 74 Trace.beginSection("InCallServiceImpl.onCallRemoved"); 75 speakEasyCallManager.onCallRemoved(CallList.getInstance().getDialerCallFromTelecomCall(call)); 76 77 InCallPresenter.getInstance().onCallRemoved(call); 78 Trace.endSection(); 79 } 80 81 @Override onCanAddCallChanged(boolean canAddCall)82 public void onCanAddCallChanged(boolean canAddCall) { 83 Trace.beginSection("InCallServiceImpl.onCanAddCallChanged"); 84 InCallPresenter.getInstance().onCanAddCallChanged(canAddCall); 85 Trace.endSection(); 86 } 87 88 @Override onCreate()89 public void onCreate() { 90 super.onCreate(); 91 this.speakEasyCallManager = SpeakEasyComponent.get(this).speakEasyCallManager(); 92 } 93 94 @Override onBind(Intent intent)95 public IBinder onBind(Intent intent) { 96 Trace.beginSection("InCallServiceImpl.onBind"); 97 final Context context = getApplicationContext(); 98 final ContactInfoCache contactInfoCache = ContactInfoCache.getInstance(context); 99 AudioModeProvider.getInstance().initializeAudioState(this); 100 InCallPresenter.getInstance() 101 .setUp( 102 context, 103 CallList.getInstance(), 104 new ExternalCallList(), 105 new StatusBarNotifier(context, contactInfoCache), 106 new ExternalCallNotifier(context, contactInfoCache), 107 contactInfoCache, 108 new ProximitySensor( 109 context, AudioModeProvider.getInstance(), new AccelerometerListener(context)), 110 new FilteredNumberAsyncQueryHandler(context), 111 speakEasyCallManager); 112 InCallPresenter.getInstance().onServiceBind(); 113 InCallPresenter.getInstance().maybeStartRevealAnimation(intent); 114 TelecomAdapter.getInstance().setInCallService(this); 115 returnToCallController = 116 new ReturnToCallController(this, ContactInfoCache.getInstance(context)); 117 feedbackListener = FeedbackComponent.get(context).getCallFeedbackListener(); 118 CallList.getInstance().addListener(feedbackListener); 119 120 IBinder iBinder = super.onBind(intent); 121 Trace.endSection(); 122 return iBinder; 123 } 124 125 @Override onUnbind(Intent intent)126 public boolean onUnbind(Intent intent) { 127 Trace.beginSection("InCallServiceImpl.onUnbind"); 128 super.onUnbind(intent); 129 130 InCallPresenter.getInstance().onServiceUnbind(); 131 tearDown(); 132 133 Trace.endSection(); 134 return false; 135 } 136 tearDown()137 private void tearDown() { 138 Trace.beginSection("InCallServiceImpl.tearDown"); 139 Log.v(this, "tearDown"); 140 // Tear down the InCall system 141 InCallPresenter.getInstance().tearDown(); 142 TelecomAdapter.getInstance().clearInCallService(); 143 if (returnToCallController != null) { 144 returnToCallController.tearDown(); 145 returnToCallController = null; 146 } 147 if (feedbackListener != null) { 148 CallList.getInstance().removeListener(feedbackListener); 149 feedbackListener = null; 150 } 151 Trace.endSection(); 152 } 153 } 154