178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad/*
278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * Copyright (C) 2014 The Android Open Source Project
378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad *
478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * Licensed under the Apache License, Version 2.0 (the "License");
578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * you may not use this file except in compliance with the License.
678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * You may obtain a copy of the License at
778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad *
878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad *      http://www.apache.org/licenses/LICENSE-2.0
978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad *
1078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * Unless required by applicable law or agreed to in writing, software
1178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * distributed under the License is distributed on an "AS IS" BASIS,
1278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * See the License for the specific language governing permissions and
1478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * limitations under the License.
1578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad */
1678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
1778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadpackage com.android.server.telecom;
1878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
198d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awadimport com.android.internal.annotations.VisibleForTesting;
208d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
2178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadimport android.content.BroadcastReceiver;
2278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadimport android.content.Context;
2378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadimport android.content.Intent;
2478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadimport android.content.IntentFilter;
2578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadimport android.os.UserHandle;
2678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
2778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad/**
2878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad * Top-level Application class for Telecom.
2978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad */
3078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadpublic final class TelecomSystem {
3178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
3278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    /**
3378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * This interface is implemented by system-instantiated components (e.g., Services and
3478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * Activity-s) that wish to use the TelecomSystem but would like to be testable. Such a
3578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * component should implement the getTelecomSystem() method to return the global singleton,
3678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * and use its own method. Tests can subclass the component to return a non-singleton.
3778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     *
3878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * A refactoring goal for Telecom is to limit use of the TelecomSystem singleton to those
3978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * system-instantiated components, and have all other parts of the system just take all their
4078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     * dependencies as explicit arguments to their constructor or other methods.
4178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad     */
4278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public interface Component {
4378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        TelecomSystem getTelecomSystem();
4478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
4578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
468d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
478d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    /**
488d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad     * Tagging interface for the object used for synchronizing multi-threaded operations in
498d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad     * the Telecom system.
508d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad     */
518d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    public interface SyncRoot {
528d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    }
538d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
5478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private static final IntentFilter USER_SWITCHED_FILTER =
5578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad            new IntentFilter(Intent.ACTION_USER_SWITCHED);
5678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
5778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private static TelecomSystem INSTANCE = null;
5878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
598d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    private final SyncRoot mLock = new SyncRoot() { };
6078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final MissedCallNotifier mMissedCallNotifier;
6178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
6278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final CallsManager mCallsManager;
6378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final RespondViaSmsManager mRespondViaSmsManager;
6478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final Context mContext;
6578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
6678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final CallIntentProcessor mCallIntentProcessor;
6778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
6878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final TelecomServiceImpl mTelecomServiceImpl;
698d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    private final ContactsAsyncHelper mContactsAsyncHelper;
7078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
7178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
7278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        @Override
7378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        public void onReceive(Context context, Intent intent) {
7478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad            int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
7578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad            UserHandle currentUserHandle = new UserHandle(userHandleId);
7678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad            mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
7778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        }
7878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    };
7978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
8078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public static TelecomSystem getInstance() {
8178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return INSTANCE;
8278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
8378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
8478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public static void setInstance(TelecomSystem instance) {
8578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        if (INSTANCE != null) {
8678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad            throw new RuntimeException("Attempt to set TelecomSystem.INSTANCE twice");
8778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        }
8878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
8978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        INSTANCE = instance;
9078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
9178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
928de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    public TelecomSystem(
938de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            Context context,
948de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            MissedCallNotifier missedCallNotifier,
95abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
968de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            HeadsetMediaButtonFactory headsetMediaButtonFactory,
978de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            ProximitySensorManagerFactory proximitySensorManagerFactory,
988de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            InCallWakeLockControllerFactory inCallWakeLockControllerFactory) {
9978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        mContext = context.getApplicationContext();
10078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
1018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mMissedCallNotifier = missedCallNotifier;
10278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
1038d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        mContactsAsyncHelper = new ContactsAsyncHelper(mLock);
10478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
10578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        mCallsManager = new CallsManager(
1068de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                mContext,
1078d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                mLock,
1088d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                mContactsAsyncHelper,
109abcbce4441720c52a443d292d5adc2d95f446494Ihab Awad                callerInfoAsyncQueryFactory,
1108de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                mMissedCallNotifier,
1118de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                mPhoneAccountRegistrar,
1128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                headsetMediaButtonFactory,
1138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                proximitySensorManagerFactory,
1148de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                inCallWakeLockControllerFactory);
1158de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad
1168d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
1178de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
1188de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad
11978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
1208d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        mBluetoothPhoneServiceImpl = new BluetoothPhoneServiceImpl(
1218d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
1228de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager);
1238de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
1248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad                mContext, mCallsManager);
1258d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        mTelecomServiceImpl = new TelecomServiceImpl(
1268d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                mContext, mCallsManager, mPhoneAccountRegistrar, mLock);
12778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
12878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
1298d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    @VisibleForTesting
13078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public PhoneAccountRegistrar getPhoneAccountRegistrar() {
13178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return mPhoneAccountRegistrar;
13278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
13378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
13478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public BluetoothPhoneServiceImpl getBluetoothPhoneServiceImpl() {
13578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return mBluetoothPhoneServiceImpl;
13678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
13778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
13878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public CallIntentProcessor getCallIntentProcessor() {
13978a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return mCallIntentProcessor;
14078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
14178a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
14278a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public TelecomBroadcastIntentProcessor getTelecomBroadcastIntentProcessor() {
14378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return mTelecomBroadcastIntentProcessor;
14478a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
14578a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad
14678a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    public TelecomServiceImpl getTelecomServiceImpl() {
14778a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad        return mTelecomServiceImpl;
14878a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad    }
1498d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
1508d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    public Object getLock() {
1518d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        return mLock;
1528d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad    }
15378a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awad}
154