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
17package com.android.server.telecom;
18
19import com.android.internal.annotations.VisibleForTesting;
20import com.android.server.telecom.components.UserCallIntentProcessor;
21import com.android.server.telecom.components.UserCallIntentProcessorFactory;
22import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
23import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
24import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
25import com.android.server.telecom.TelecomServiceImpl.DefaultDialerManagerAdapter;
26
27import android.Manifest;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.net.Uri;
33import android.os.UserHandle;
34
35import java.io.FileNotFoundException;
36import java.io.InputStream;
37
38/**
39 * Top-level Application class for Telecom.
40 */
41public final class TelecomSystem {
42
43    /**
44     * This interface is implemented by system-instantiated components (e.g., Services and
45     * Activity-s) that wish to use the TelecomSystem but would like to be testable. Such a
46     * component should implement the getTelecomSystem() method to return the global singleton,
47     * and use its own method. Tests can subclass the component to return a non-singleton.
48     *
49     * A refactoring goal for Telecom is to limit use of the TelecomSystem singleton to those
50     * system-instantiated components, and have all other parts of the system just take all their
51     * dependencies as explicit arguments to their constructor or other methods.
52     */
53    public interface Component {
54        TelecomSystem getTelecomSystem();
55    }
56
57
58    /**
59     * Tagging interface for the object used for synchronizing multi-threaded operations in
60     * the Telecom system.
61     */
62    public interface SyncRoot {
63    }
64
65    private static final IntentFilter USER_SWITCHED_FILTER =
66            new IntentFilter(Intent.ACTION_USER_SWITCHED);
67
68    private static final IntentFilter USER_STARTING_FILTER =
69            new IntentFilter(Intent.ACTION_USER_STARTING);
70
71    /** Intent filter for dialer secret codes. */
72    private static final IntentFilter DIALER_SECRET_CODE_FILTER;
73
74    /**
75     * Initializes the dialer secret code intent filter.  Setup to handle the various secret codes
76     * which can be dialed (e.g. in format *#*#code#*#*) to trigger various behavior in Telecom.
77     */
78    static {
79        DIALER_SECRET_CODE_FILTER = new IntentFilter(
80                "android.provider.Telephony.SECRET_CODE");
81        DIALER_SECRET_CODE_FILTER.addDataScheme("android_secret_code");
82        DIALER_SECRET_CODE_FILTER
83                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_ON, null);
84        DIALER_SECRET_CODE_FILTER
85                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null);
86        DIALER_SECRET_CODE_FILTER
87                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
88    }
89
90    private static TelecomSystem INSTANCE = null;
91
92    private final SyncRoot mLock = new SyncRoot() { };
93    private final MissedCallNotifier mMissedCallNotifier;
94    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
95    private final CallsManager mCallsManager;
96    private final RespondViaSmsManager mRespondViaSmsManager;
97    private final Context mContext;
98    private final BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
99    private final CallIntentProcessor mCallIntentProcessor;
100    private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
101    private final TelecomServiceImpl mTelecomServiceImpl;
102    private final ContactsAsyncHelper mContactsAsyncHelper;
103    private final DialerCodeReceiver mDialerCodeReceiver;
104
105    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
106        @Override
107        public void onReceive(Context context, Intent intent) {
108            Log.startSession("TSSwR.oR");
109            try {
110                int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
111                UserHandle currentUserHandle = new UserHandle(userHandleId);
112                mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
113                mCallsManager.onUserSwitch(currentUserHandle);
114            } finally {
115                Log.endSession();
116            }
117        }
118    };
119
120    private final BroadcastReceiver mUserStartingReceiver = new BroadcastReceiver() {
121        @Override
122        public void onReceive(Context context, Intent intent) {
123            Log.startSession("TSStR.oR");
124            try {
125                int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
126                UserHandle addingUserHandle = new UserHandle(userHandleId);
127                mCallsManager.onUserStarting(addingUserHandle);
128            } finally {
129                Log.endSession();
130            }
131        }
132    };
133
134    public static TelecomSystem getInstance() {
135        return INSTANCE;
136    }
137
138    public static void setInstance(TelecomSystem instance) {
139        if (INSTANCE != null) {
140            throw new RuntimeException("Attempt to set TelecomSystem.INSTANCE twice");
141        }
142        Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
143        INSTANCE = instance;
144    }
145
146    public TelecomSystem(
147            Context context,
148            MissedCallNotifierImplFactory missedCallNotifierImplFactory,
149            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
150            HeadsetMediaButtonFactory headsetMediaButtonFactory,
151            ProximitySensorManagerFactory proximitySensorManagerFactory,
152            InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
153            AudioServiceFactory audioServiceFactory,
154            BluetoothPhoneServiceImplFactory
155                    bluetoothPhoneServiceImplFactory,
156            Timeouts.Adapter timeoutsAdapter,
157            AsyncRingtonePlayer asyncRingtonePlayer) {
158        mContext = context.getApplicationContext();
159        Log.setContext(mContext);
160        Log.initMd5Sum();
161
162        Log.startSession("TS.init");
163        mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
164        mContactsAsyncHelper = new ContactsAsyncHelper(
165                new ContactsAsyncHelper.ContentResolverAdapter() {
166                    @Override
167                    public InputStream openInputStream(Context context, Uri uri)
168                            throws FileNotFoundException {
169                        return context.getContentResolver().openInputStream(uri);
170                    }
171                });
172        BluetoothManager bluetoothManager = new BluetoothManager(mContext,
173                new BluetoothAdapterProxy());
174        WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext);
175        SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
176
177        mMissedCallNotifier = missedCallNotifierImplFactory
178                .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar);
179
180        DefaultDialerManagerAdapter defaultDialerAdapter =
181                new TelecomServiceImpl.DefaultDialerManagerAdapterImpl();
182
183        mCallsManager = new CallsManager(
184                mContext,
185                mLock,
186                mContactsAsyncHelper,
187                callerInfoAsyncQueryFactory,
188                mMissedCallNotifier,
189                mPhoneAccountRegistrar,
190                headsetMediaButtonFactory,
191                proximitySensorManagerFactory,
192                inCallWakeLockControllerFactory,
193                audioServiceFactory,
194                bluetoothManager,
195                wiredHeadsetManager,
196                systemStateProvider,
197                defaultDialerAdapter,
198                timeoutsAdapter,
199                asyncRingtonePlayer);
200
201        mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
202        mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
203
204        mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
205        mContext.registerReceiver(mUserStartingReceiver, USER_STARTING_FILTER);
206
207        mBluetoothPhoneServiceImpl = bluetoothPhoneServiceImplFactory.makeBluetoothPhoneServiceImpl(
208                mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
209        mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager);
210        mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
211                mContext, mCallsManager);
212
213        // Register the receiver for the dialer secret codes, used to enable extended logging.
214        mDialerCodeReceiver = new DialerCodeReceiver(mCallsManager);
215        mContext.registerReceiver(mDialerCodeReceiver, DIALER_SECRET_CODE_FILTER,
216                Manifest.permission.CONTROL_INCALL_EXPERIENCE, null);
217
218        mTelecomServiceImpl = new TelecomServiceImpl(
219                mContext, mCallsManager, mPhoneAccountRegistrar,
220                new CallIntentProcessor.AdapterImpl(),
221                new UserCallIntentProcessorFactory() {
222                    @Override
223                    public UserCallIntentProcessor create(Context context, UserHandle userHandle) {
224                        return new UserCallIntentProcessor(context, userHandle);
225                    }
226                },
227                defaultDialerAdapter,
228                new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
229                mLock);
230        Log.endSession();
231    }
232
233    @VisibleForTesting
234    public PhoneAccountRegistrar getPhoneAccountRegistrar() {
235        return mPhoneAccountRegistrar;
236    }
237
238    @VisibleForTesting
239    public CallsManager getCallsManager() {
240        return mCallsManager;
241    }
242
243    public BluetoothPhoneServiceImpl getBluetoothPhoneServiceImpl() {
244        return mBluetoothPhoneServiceImpl;
245    }
246
247    public CallIntentProcessor getCallIntentProcessor() {
248        return mCallIntentProcessor;
249    }
250
251    public TelecomBroadcastIntentProcessor getTelecomBroadcastIntentProcessor() {
252        return mTelecomBroadcastIntentProcessor;
253    }
254
255    public TelecomServiceImpl getTelecomServiceImpl() {
256        return mTelecomServiceImpl;
257    }
258
259    public Object getLock() {
260        return mLock;
261    }
262}
263