summaryrefslogtreecommitdiffstats
path: root/src/com/android/dialer/discovery/WifiCallStatusNudgeListener.java
blob: 3990d27f4cf1d605c0046df6ccc3386605c70686 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package com.android.dialer.discovery;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Message;
import android.telephony.PhoneStateListener;
import android.telephony.PreciseCallState;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.dialer.DialtactsActivity;
import com.android.phone.common.incall.utils.CallMethodUtils;
import com.cyanogen.ambient.discovery.util.NudgeKey;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Listener to monitor and count calls that have wifi connected the entire time.
 */
public class WifiCallStatusNudgeListener {

    private final static String TAG = WifiCallStatusNudgeListener.class.getSimpleName();
    private final static boolean DEBUG = false;

    private final static AtomicBoolean mReceiverRegistered = new AtomicBoolean(false);
    private final static int WIFI_STATE_DISABLED = 0;
    private final static int PRECISE_CALL_STATE_IDLE = 1;
    private final static int PRECISE_CALL_STATE_DIALING = 2;

    private static Context mContext;
    private static TelephonyManager mTelephonyManager;

    private static BroadcastReceiver mWifiListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                    WifiManager.WIFI_STATE_UNKNOWN);
            if (DEBUG) Log.v(TAG, "Got wifi state: " + state);
            if (state == WifiManager.WIFI_STATE_DISABLED) {
                Message phoneStateMessage
                        = mPhoneWifiStateHandler.obtainMessage(WIFI_STATE_DISABLED);
                phoneStateMessage.sendToTarget();
            }
        }
    };

    private static Handler mPhoneWifiStateHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case PRECISE_CALL_STATE_DIALING:

                    ConnectivityManager connManager = (ConnectivityManager) mContext
                            .getSystemService(Context.CONNECTIVITY_SERVICE);
                    NetworkInfo mWifi
                            = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

                    // If wifi is connected when we first get the OFFHOOK state, start a receiver to
                    // watch for wifi connection slips during the call.
                    if (mWifi.isConnected()) {
                        startReceiver();
                    } else {
                        callOnWifiFailure();
                    }
                    break;
                case PRECISE_CALL_STATE_IDLE:
                    synchronized (mReceiverRegistered) {
                        if (mReceiverRegistered.get()) {
                            // We lasted the whole call
                            stopReceiver();
                            callOnWifiSuccess();
                        } else {
                            callOnWifiFailure();
                        }
                    }
                    break;
                case WIFI_STATE_DISABLED:
                    stopReceiver();
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private static PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
        @Override
        public void onPreciseCallStateChanged(PreciseCallState callState) {
            int ringingState = callState.getForegroundCallState();
            if (DEBUG) Log.v(TAG, "ringing state: " + ringingState);
            Message phoneStateMessage = null;
            switch (ringingState) {
                case PreciseCallState.PRECISE_CALL_STATE_DIALING:
                    phoneStateMessage
                            = mPhoneWifiStateHandler.obtainMessage(PRECISE_CALL_STATE_DIALING);
                    break;
                case PreciseCallState.PRECISE_CALL_STATE_IDLE:
                case PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED:
                    phoneStateMessage
                            = mPhoneWifiStateHandler.obtainMessage(PRECISE_CALL_STATE_IDLE);
                    break;
            }
            if (phoneStateMessage != null) {
                phoneStateMessage.sendToTarget();
            }
        }
    };

    public static void init(Context c) {
        mContext = c;
        mReceiverRegistered.set(false);

        mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_PRECISE_CALL_STATE);
    }

    private static void startReceiver() {
        synchronized (mReceiverRegistered) {
            if (DEBUG) Log.v(TAG, "Receiver starting...");
            IntentFilter intFilter = new IntentFilter();
            intFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
            mContext.registerReceiver(mWifiListener, intFilter);
            mReceiverRegistered.set(true);
        }
    }

    private static void stopReceiver() {
        synchronized (mReceiverRegistered) {
            if (DEBUG) Log.v(TAG, "Receiver stopping...");
            mContext.unregisterReceiver(mWifiListener);
            mReceiverRegistered.set(false);
        }
    }

    private static void callOnWifiSuccess() {
        if (DEBUG) Log.v(TAG, "call was made with wifi connected the whole time");

        SharedPreferences preferences = mContext
                .getSharedPreferences(DialtactsActivity.SHARED_PREFS_NAME, Context.MODE_PRIVATE);

        int currentCount;
        // If the network is roaming and we are on wifi,
        // then we want to show a potential roaming nudge instead of a wifi nudge.
        if (mTelephonyManager.isNetworkRoaming()) {
            currentCount = preferences.getInt(CallMethodUtils.PREF_ROAMING_CALLS, 0);
            preferences.edit().putInt(CallMethodUtils.PREF_ROAMING_CALLS, ++currentCount).apply();
            DiscoverySignalReceiver.startServiceForConnectivityChanged(mContext);
        } else {
            currentCount = preferences.getInt(CallMethodUtils.PREF_WIFI_CALL, 0);
            preferences.edit().putInt(CallMethodUtils.PREF_WIFI_CALL, ++currentCount).apply();

            new DiscoveryEventHandler(mContext).getNudgeProvidersWithKey(
                    NudgeKey.NOTIFICATION_WIFI_CALL);
        }
    }

    private static void callOnWifiFailure() {
        if (DEBUG) Log.v(TAG, "call was made with wifi not connected at some point");
    }
}