1/*
2 * Copyright (C) 2016 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 android.car.cluster.demorenderer;
18
19import android.annotation.Nullable;
20import android.car.cluster.demorenderer.PhoneBook.Contact;
21import android.car.cluster.demorenderer.PhoneBook.ContactLoadedListener;
22import android.car.cluster.demorenderer.PhoneBook.ContactPhotoLoadedListener;
23import android.content.Context;
24import android.graphics.Bitmap;
25import android.telephony.TelephonyManager;
26import android.util.Log;
27
28import java.lang.ref.WeakReference;
29
30/**
31 * Monitors call state.
32 */
33public class CallStateMonitor implements ContactLoadedListener, ContactPhotoLoadedListener {
34    private final static String TAG = CallStateMonitor.class.getSimpleName();
35
36    private final PhoneBook mPhoneBook;
37    private final TelephonyManager mTelephonyManager;
38    private final PhoneStateListener mListener;
39    private final CallStateListener mCallStateListener;
40
41    CallStateMonitor(Context context, PhoneStateListener listener) {
42        Log.d(TAG, "ctor, context: " + context + ", phoneRenderer: " + listener +
43                ", contentResolver: " + context.getContentResolver() +
44                ", applicationContext: " + context.getApplicationContext());
45
46        mListener = listener;
47        mTelephonyManager = context.getSystemService(TelephonyManager.class);
48        mPhoneBook = new PhoneBook(context, mTelephonyManager);
49        mCallStateListener = new CallStateListener(this);
50        mTelephonyManager.listen(mCallStateListener,
51                android.telephony.PhoneStateListener.LISTEN_CALL_STATE);
52
53        updateRendererPhoneStatusIfAvailable();
54    }
55
56    public void release() {
57        mTelephonyManager.listen(mCallStateListener,
58                android.telephony.PhoneStateListener.LISTEN_NONE);
59    }
60
61    private void updateRendererPhoneStatusIfAvailable() {
62        onCallStateChanged(mTelephonyManager.getCallState(), null);
63    }
64
65    private void onCallStateChanged(int state, final String number) {
66        Log.d(TAG, "onCallStateChanged, state:" + state + ", phoneNumber: " + number);
67
68        // Update call state immediately on instrument cluster.
69        mListener.onCallStateChanged(state, PhoneBook.getFormattedNumber(number));
70
71        // Now fetching details asynchronously.
72        mPhoneBook.getContactDetailsAsync(number, this);
73    }
74
75    @Override
76    public void onContactLoaded(String number, @Nullable Contact contact) {
77        if (contact != null) {
78            mListener.onContactDetailsUpdated(contact.getName(), contact.getType(),
79                    mPhoneBook.isVoicemail(number));
80
81            mPhoneBook.getContactPictureAsync(contact.getId(), this);
82        }
83    }
84
85    @Override
86    public void onPhotoLoaded(int contactId, @Nullable Bitmap photo) {
87        mListener.onContactPhotoUpdated(photo);
88    }
89
90    public interface PhoneStateListener {
91        void onCallStateChanged(int state, @Nullable String number);
92        void onContactDetailsUpdated(
93                @Nullable  CharSequence name,
94                @Nullable CharSequence typeLabel,
95                boolean isVoiceMail);
96        void onContactPhotoUpdated(Bitmap picture);
97    }
98
99    private static class CallStateListener extends android.telephony.PhoneStateListener {
100        private final WeakReference<CallStateMonitor> mServiceRef;
101
102        CallStateListener(CallStateMonitor service) {
103            mServiceRef = new WeakReference<>(service);
104        }
105
106        @Override
107        public void onCallStateChanged(int state, String incomingNumber) {
108            CallStateMonitor service = mServiceRef.get();
109            if (service != null) {
110                service.onCallStateChanged(state, incomingNumber);
111            }
112        }
113    }
114}
115