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.components; 18 19 import android.app.Service; 20 import android.app.role.RoleManager; 21 import android.bluetooth.BluetoothAdapter; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.media.IAudioService; 25 import android.media.ToneGenerator; 26 import android.os.IBinder; 27 import android.os.Looper; 28 import android.os.PowerManager; 29 import android.os.ServiceManager; 30 import android.os.SystemClock; 31 import android.telecom.Log; 32 33 import com.android.internal.telephony.CallerInfoAsyncQuery; 34 import com.android.server.telecom.AsyncRingtonePlayer; 35 import com.android.server.telecom.BluetoothAdapterProxy; 36 import com.android.server.telecom.BluetoothPhoneServiceImpl; 37 import com.android.server.telecom.CallAudioRouteStateMachine; 38 import com.android.server.telecom.CallerInfoAsyncQueryFactory; 39 import com.android.server.telecom.CallsManager; 40 import com.android.server.telecom.ClockProxy; 41 import com.android.server.telecom.ConnectionServiceFocusManager; 42 import com.android.server.telecom.DefaultDialerCache; 43 import com.android.server.telecom.HeadsetMediaButton; 44 import com.android.server.telecom.HeadsetMediaButtonFactory; 45 import com.android.server.telecom.InCallTonePlayer; 46 import com.android.server.telecom.InCallWakeLockControllerFactory; 47 import com.android.server.telecom.CallAudioManager; 48 import com.android.server.telecom.PhoneAccountRegistrar; 49 import com.android.server.telecom.PhoneNumberUtilsAdapterImpl; 50 import com.android.server.telecom.ProximitySensorManagerFactory; 51 import com.android.server.telecom.InCallWakeLockController; 52 import com.android.server.telecom.ProximitySensorManager; 53 import com.android.server.telecom.R; 54 import com.android.server.telecom.RoleManagerAdapter; 55 import com.android.server.telecom.RoleManagerAdapterImpl; 56 import com.android.server.telecom.TelecomSystem; 57 import com.android.server.telecom.TelecomWakeLock; 58 import com.android.server.telecom.Timeouts; 59 import com.android.server.telecom.ui.IncomingCallNotifier; 60 import com.android.server.telecom.ui.MissedCallNotifierImpl; 61 import com.android.server.telecom.ui.NotificationChannelManager; 62 63 /** 64 * Implementation of the ITelecom interface. 65 */ 66 public class TelecomService extends Service implements TelecomSystem.Component { 67 68 @Override onBind(Intent intent)69 public IBinder onBind(Intent intent) { 70 Log.d(this, "onBind"); 71 initializeTelecomSystem(this); 72 synchronized (getTelecomSystem().getLock()) { 73 return getTelecomSystem().getTelecomServiceImpl().getBinder(); 74 } 75 } 76 77 /** 78 * This method is to be called by components (Activitys, Services, ...) to initialize the 79 * Telecom singleton. It should only be called on the main thread. As such, it is atomic 80 * and needs no synchronization -- it will either perform its initialization, after which 81 * the {@link TelecomSystem#getInstance()} will be initialized, or some other invocation of 82 * this method on the main thread will have happened strictly prior to it, and this method 83 * will be a benign no-op. 84 * 85 * @param context 86 */ initializeTelecomSystem(Context context)87 static void initializeTelecomSystem(Context context) { 88 if (TelecomSystem.getInstance() == null) { 89 NotificationChannelManager notificationChannelManager = 90 new NotificationChannelManager(); 91 notificationChannelManager.createChannels(context); 92 93 boolean shouldPauseBetweenRingtoneRepeat = context.getResources().getBoolean( 94 R.bool.should_pause_between_ringtone_repeats); 95 TelecomSystem.setInstance( 96 new TelecomSystem( 97 context, 98 new MissedCallNotifierImpl.MissedCallNotifierImplFactory() { 99 @Override 100 public MissedCallNotifierImpl makeMissedCallNotifierImpl( 101 Context context, 102 PhoneAccountRegistrar phoneAccountRegistrar, 103 DefaultDialerCache defaultDialerCache) { 104 return new MissedCallNotifierImpl(context, 105 phoneAccountRegistrar, defaultDialerCache); 106 } 107 }, 108 new CallerInfoAsyncQueryFactory() { 109 @Override 110 public CallerInfoAsyncQuery startQuery( 111 int token, 112 Context context, 113 String number, 114 CallerInfoAsyncQuery.OnQueryCompleteListener listener, 115 Object cookie) { 116 Log.i(TelecomSystem.getInstance(), 117 "CallerInfoAsyncQuery.startQuery number=%s cookie=%s", 118 Log.pii(number), cookie); 119 return CallerInfoAsyncQuery.startQuery( 120 token, context, number, listener, cookie); 121 } 122 }, 123 new HeadsetMediaButtonFactory() { 124 @Override 125 public HeadsetMediaButton create( 126 Context context, 127 CallsManager callsManager, 128 TelecomSystem.SyncRoot lock) { 129 return new HeadsetMediaButton(context, callsManager, lock); 130 } 131 }, 132 new ProximitySensorManagerFactory() { 133 @Override 134 public ProximitySensorManager create( 135 Context context, 136 CallsManager callsManager) { 137 return new ProximitySensorManager( 138 new TelecomWakeLock( 139 context, 140 PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, 141 ProximitySensorManager.class.getSimpleName()), 142 callsManager); 143 } 144 }, 145 new InCallWakeLockControllerFactory() { 146 @Override 147 public InCallWakeLockController create(Context context, 148 CallsManager callsManager) { 149 return new InCallWakeLockController( 150 new TelecomWakeLock(context, 151 PowerManager.FULL_WAKE_LOCK, 152 InCallWakeLockController.class.getSimpleName()), 153 callsManager); 154 } 155 }, 156 new CallAudioManager.AudioServiceFactory() { 157 @Override 158 public IAudioService getAudioService() { 159 return IAudioService.Stub.asInterface( 160 ServiceManager.getService(Context.AUDIO_SERVICE)); 161 } 162 }, 163 new BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory() { 164 @Override 165 public BluetoothPhoneServiceImpl makeBluetoothPhoneServiceImpl( 166 Context context, TelecomSystem.SyncRoot lock, 167 CallsManager callsManager, 168 PhoneAccountRegistrar phoneAccountRegistrar) { 169 return new BluetoothPhoneServiceImpl(context, lock, 170 callsManager, new BluetoothAdapterProxy(), 171 phoneAccountRegistrar); 172 } 173 }, 174 ConnectionServiceFocusManager::new, 175 new Timeouts.Adapter(), 176 new AsyncRingtonePlayer(shouldPauseBetweenRingtoneRepeat), 177 new PhoneNumberUtilsAdapterImpl(), 178 new IncomingCallNotifier(context), 179 ToneGenerator::new, 180 new CallAudioRouteStateMachine.Factory(), 181 new ClockProxy() { 182 @Override 183 public long currentTimeMillis() { 184 return System.currentTimeMillis(); 185 } 186 187 @Override 188 public long elapsedRealtime() { 189 return SystemClock.elapsedRealtime(); 190 } 191 }, 192 new RoleManagerAdapterImpl(context, 193 (RoleManager) context.getSystemService(Context.ROLE_SERVICE)))); 194 } 195 if (BluetoothAdapter.getDefaultAdapter() != null) { 196 context.startService(new Intent(context, BluetoothPhoneService.class)); 197 } 198 } 199 200 @Override getTelecomSystem()201 public TelecomSystem getTelecomSystem() { 202 return TelecomSystem.getInstance(); 203 } 204 } 205