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 NewReturnToCallController newReturnToCallController; 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 InCallPresenter.getInstance().onServiceBind(); 112 InCallPresenter.getInstance().maybeStartRevealAnimation(intent); 113 TelecomAdapter.getInstance().setInCallService(this); 114 if (NewReturnToCallController.isEnabled(this)) { 115 newReturnToCallController = 116 new NewReturnToCallController(this, ContactInfoCache.getInstance(context)); 117 } 118 feedbackListener = FeedbackComponent.get(context).getCallFeedbackListener(); 119 CallList.getInstance().addListener(feedbackListener); 120 121 IBinder iBinder = super.onBind(intent); 122 Trace.endSection(); 123 return iBinder; 124 } 125 126 @Override onUnbind(Intent intent)127 public boolean onUnbind(Intent intent) { 128 Trace.beginSection("InCallServiceImpl.onUnbind"); 129 super.onUnbind(intent); 130 131 InCallPresenter.getInstance().onServiceUnbind(); 132 tearDown(); 133 134 Trace.endSection(); 135 return false; 136 } 137 tearDown()138 private void tearDown() { 139 Trace.beginSection("InCallServiceImpl.tearDown"); 140 Log.v(this, "tearDown"); 141 // Tear down the InCall system 142 InCallPresenter.getInstance().tearDown(); 143 TelecomAdapter.getInstance().clearInCallService(); 144 if (newReturnToCallController != null) { 145 newReturnToCallController.tearDown(); 146 newReturnToCallController = null; 147 } 148 if (feedbackListener != null) { 149 CallList.getInstance().removeListener(feedbackListener); 150 feedbackListener = null; 151 } 152 Trace.endSection(); 153 } 154 } 155