PhoneStatusBarPolicy.java revision bcc1087af40a0e1bb35dbe8a39c830ecdea8280b
1/*
2 * Copyright (C) 2008 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.systemui.statusbar.phone;
18
19import android.app.AlarmManager;
20import android.app.StatusBarManager;
21import android.bluetooth.BluetoothAdapter;
22import android.content.BroadcastReceiver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
26import android.media.AudioManager;
27import android.os.Handler;
28import android.os.UserHandle;
29import android.provider.Settings.Global;
30import android.telecom.TelecomManager;
31import android.util.Log;
32
33import com.android.internal.telephony.IccCardConstants;
34import com.android.internal.telephony.TelephonyIntents;
35import com.android.systemui.R;
36import com.android.systemui.statusbar.policy.CastController;
37import com.android.systemui.statusbar.policy.CastController.CastDevice;
38import com.android.systemui.statusbar.policy.HotspotController;
39
40/**
41 * This class contains all of the policy about which icons are installed in the status
42 * bar at boot time.  It goes through the normal API for icons, even though it probably
43 * strictly doesn't need to.
44 */
45public class PhoneStatusBarPolicy {
46    private static final String TAG = "PhoneStatusBarPolicy";
47    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
48
49    private static final boolean SHOW_SYNC_ICON = false;
50
51    private static final String SLOT_SYNC_ACTIVE = "sync_active";
52    private static final String SLOT_CAST = "cast";
53    private static final String SLOT_HOTSPOT = "hotspot";
54    private static final String SLOT_BLUETOOTH = "bluetooth";
55    private static final String SLOT_TTY = "tty";
56    private static final String SLOT_ZEN = "zen";
57    private static final String SLOT_VOLUME = "volume";
58    private static final String SLOT_CDMA_ERI = "cdma_eri";
59    private static final String SLOT_ALARM_CLOCK = "alarm_clock";
60
61    private final Context mContext;
62    private final StatusBarManager mService;
63    private final Handler mHandler = new Handler();
64    private final CastController mCast;
65    private final HotspotController mHotspot;
66
67    // Assume it's all good unless we hear otherwise.  We don't always seem
68    // to get broadcasts that it *is* there.
69    IccCardConstants.State mSimState = IccCardConstants.State.READY;
70
71    private boolean mZenVisible;
72    private boolean mVolumeVisible;
73
74    private int mZen;
75
76    private boolean mBluetoothEnabled = false;
77
78
79    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
80        @Override
81        public void onReceive(Context context, Intent intent) {
82            String action = intent.getAction();
83            if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
84                updateAlarm();
85            }
86            else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
87                updateSyncState(intent);
88            }
89            else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
90                    action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
91                updateBluetooth();
92            }
93            else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
94                    action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
95                updateVolumeZen();
96            }
97            else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
98                updateSimState(intent);
99            }
100            else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) {
101                updateTTY(intent);
102            }
103            else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
104                updateAlarm();
105            }
106        }
107    };
108
109    public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) {
110        mContext = context;
111        mCast = cast;
112        mHotspot = hotspot;
113        mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
114
115        // listen for broadcasts
116        IntentFilter filter = new IntentFilter();
117        filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
118        filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
119        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
120        filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
121        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
122        filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
123        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
124        filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
125        filter.addAction(Intent.ACTION_USER_SWITCHED);
126        mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
127
128        // TTY status
129        mService.setIcon(SLOT_TTY,  R.drawable.stat_sys_tty_mode, 0, null);
130        mService.setIconVisibility(SLOT_TTY, false);
131
132        // Cdma Roaming Indicator, ERI
133        mService.setIcon(SLOT_CDMA_ERI, R.drawable.stat_sys_roaming_cdma_0, 0, null);
134        mService.setIconVisibility(SLOT_CDMA_ERI, false);
135
136        // bluetooth status
137        updateBluetooth();
138
139        // Alarm clock
140        mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null);
141        mService.setIconVisibility(SLOT_ALARM_CLOCK, false);
142
143        // Sync state
144        mService.setIcon(SLOT_SYNC_ACTIVE, R.drawable.stat_sys_sync, 0, null);
145        mService.setIconVisibility(SLOT_SYNC_ACTIVE, false);
146        // "sync_failing" is obsolete: b/1297963
147
148        // zen
149        mService.setIcon(SLOT_ZEN, R.drawable.stat_sys_zen_important, 0, null);
150        mService.setIconVisibility(SLOT_ZEN, false);
151
152        // volume
153        mService.setIcon(SLOT_VOLUME, R.drawable.stat_sys_ringer_vibrate, 0, null);
154        mService.setIconVisibility(SLOT_VOLUME, false);
155        updateVolumeZen();
156
157        // cast
158        mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null);
159        mService.setIconVisibility(SLOT_CAST, false);
160        mCast.addCallback(mCastCallback);
161
162        // hotspot
163        mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null);
164        mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
165        mHotspot.addCallback(mHotspotCallback);
166    }
167
168    public void setZenMode(int zen) {
169        mZen = zen;
170        updateVolumeZen();
171    }
172
173    private void updateAlarm() {
174        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
175	boolean alarmSet = alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT) != null;
176        mService.setIconVisibility(SLOT_ALARM_CLOCK, alarmSet);
177    }
178
179    private final void updateSyncState(Intent intent) {
180        if (!SHOW_SYNC_ICON) return;
181        boolean isActive = intent.getBooleanExtra("active", false);
182        mService.setIconVisibility(SLOT_SYNC_ACTIVE, isActive);
183    }
184
185    private final void updateSimState(Intent intent) {
186        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
187        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
188            mSimState = IccCardConstants.State.ABSENT;
189        }
190        else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
191            mSimState = IccCardConstants.State.CARD_IO_ERROR;
192        }
193        else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
194            mSimState = IccCardConstants.State.READY;
195        }
196        else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
197            final String lockedReason =
198                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
199            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
200                mSimState = IccCardConstants.State.PIN_REQUIRED;
201            }
202            else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
203                mSimState = IccCardConstants.State.PUK_REQUIRED;
204            }
205            else {
206                mSimState = IccCardConstants.State.NETWORK_LOCKED;
207            }
208        } else {
209            mSimState = IccCardConstants.State.UNKNOWN;
210        }
211    }
212
213    private final void updateVolumeZen() {
214        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
215
216        boolean zenVisible = false;
217        int zenIconId = 0;
218        String zenDescription = null;
219
220        boolean volumeVisible = false;
221        int volumeIconId = 0;
222        String volumeDescription = null;
223
224        if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
225            zenVisible = true;
226            zenIconId = R.drawable.stat_sys_zen_none;
227            zenDescription = mContext.getString(R.string.zen_no_interruptions);
228        } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
229            zenVisible = true;
230            zenIconId = R.drawable.stat_sys_zen_important;
231            zenDescription = mContext.getString(R.string.zen_important_interruptions);
232        }
233
234        if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS &&
235                audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
236            volumeVisible = true;
237            volumeIconId = R.drawable.stat_sys_ringer_vibrate;
238            volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
239        }
240
241        if (zenVisible) {
242            mService.setIcon(SLOT_ZEN, zenIconId, 0, zenDescription);
243        }
244        if (zenVisible != mZenVisible) {
245            mService.setIconVisibility(SLOT_ZEN, zenVisible);
246            mZenVisible = zenVisible;
247        }
248
249        if (volumeVisible) {
250            mService.setIcon(SLOT_VOLUME, volumeIconId, 0, volumeDescription);
251        }
252        if (volumeVisible != mVolumeVisible) {
253            mService.setIconVisibility(SLOT_VOLUME, volumeVisible);
254            mVolumeVisible = volumeVisible;
255        }
256    }
257
258    private final void updateBluetooth() {
259        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
260        int iconId = R.drawable.stat_sys_data_bluetooth;
261        String contentDescription =
262                mContext.getString(R.string.accessibility_bluetooth_disconnected);
263        if (adapter != null) {
264            mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
265            if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
266                iconId = R.drawable.stat_sys_data_bluetooth_connected;
267                contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
268            }
269        } else {
270            mBluetoothEnabled = false;
271        }
272
273        mService.setIcon(SLOT_BLUETOOTH, iconId, 0, contentDescription);
274        mService.setIconVisibility(SLOT_BLUETOOTH, mBluetoothEnabled);
275    }
276
277    private final void updateTTY(Intent intent) {
278        int currentTtyMode = intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
279                TelecomManager.TTY_MODE_OFF);
280        boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
281
282        if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
283
284        if (enabled) {
285            // TTY is on
286            if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
287            mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0,
288                    mContext.getString(R.string.accessibility_tty_enabled));
289            mService.setIconVisibility(SLOT_TTY, true);
290        } else {
291            // TTY is off
292            if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
293            mService.setIconVisibility(SLOT_TTY, false);
294        }
295    }
296
297    private void updateCast() {
298        boolean isCasting = false;
299        for (CastDevice device : mCast.getCastDevices()) {
300            if (device.state == CastDevice.STATE_CONNECTING
301                    || device.state == CastDevice.STATE_CONNECTED) {
302                isCasting = true;
303                break;
304            }
305        }
306        if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
307        if (isCasting) {
308            mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0,
309                    mContext.getString(R.string.accessibility_casting));
310        }
311        mService.setIconVisibility(SLOT_CAST, isCasting);
312    }
313
314    private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
315        @Override
316        public void onHotspotChanged(boolean enabled) {
317            mService.setIconVisibility(SLOT_HOTSPOT, enabled);
318        }
319    };
320
321    private final CastController.Callback mCastCallback = new CastController.Callback() {
322        @Override
323        public void onCastDevicesChanged() {
324            updateCast();
325        }
326    };
327}
328