/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.statusbar.phone; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.drawable.Drawable; import android.hardware.display.WifiDisplayStatus; import android.os.Handler; import android.provider.Settings; import android.text.TextUtils; import android.view.View; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.view.RotationPolicy; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; import java.util.List; class QuickSettingsModel implements BluetoothStateChangeCallback, NetworkSignalChangedCallback, BatteryStateChangeCallback, LocationGpsStateChangeCallback { /** Represents the state of a given attribute. */ static class State { int iconId; String label; boolean enabled = false; } static class BatteryState extends State { int batteryLevel; boolean pluggedIn; } static class RSSIState extends State { int signalIconId; int dataTypeIconId; } static class UserState extends State { Drawable avatar; } /** The callback to update a given tile. */ interface RefreshCallback { public void refreshView(QuickSettingsTileView view, State state); } /** Broadcast receive to determine if there is an alarm set. */ private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_ALARM_CHANGED)) { onAlarmChanged(intent); onNextAlarmChanged(); } } }; /** ContentObserver to determine the next alarm */ private class NextAlarmObserver extends ContentObserver { public NextAlarmObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { onNextAlarmChanged(); } public void startObserving() { final ContentResolver cr = mContext.getContentResolver(); cr.registerContentObserver( Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this); } } private Context mContext; private Handler mHandler; private NextAlarmObserver mNextAlarmObserver; private QuickSettingsTileView mUserTile; private RefreshCallback mUserCallback; private UserState mUserState = new UserState(); private QuickSettingsTileView mTimeTile; private RefreshCallback mTimeAlarmCallback; private State mTimeAlarmState = new State(); private QuickSettingsTileView mAirplaneModeTile; private RefreshCallback mAirplaneModeCallback; private State mAirplaneModeState = new State(); private QuickSettingsTileView mWifiTile; private RefreshCallback mWifiCallback; private State mWifiState = new State(); private QuickSettingsTileView mWifiDisplayTile; private RefreshCallback mWifiDisplayCallback; private State mWifiDisplayState = new State(); private QuickSettingsTileView mRSSITile; private RefreshCallback mRSSICallback; private RSSIState mRSSIState = new RSSIState(); private QuickSettingsTileView mBluetoothTile; private RefreshCallback mBluetoothCallback; private State mBluetoothState = new State(); private QuickSettingsTileView mBatteryTile; private RefreshCallback mBatteryCallback; private BatteryState mBatteryState = new BatteryState(); private QuickSettingsTileView mLocationTile; private RefreshCallback mLocationCallback; private State mLocationState = new State(); private QuickSettingsTileView mImeTile; private RefreshCallback mImeCallback; private State mImeState = new State(); private QuickSettingsTileView mRotationLockTile; private RefreshCallback mRotationLockCallback; private State mRotationLockState = new State(); public QuickSettingsModel(Context context) { mContext = context; mHandler = new Handler(); mNextAlarmObserver = new NextAlarmObserver(mHandler); mNextAlarmObserver.startObserving(); IntentFilter alarmIntentFilter = new IntentFilter(); alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED); context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter); } // User void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { mUserTile = view; mUserCallback = cb; mUserCallback.refreshView(mUserTile, mUserState); } void setUserTileInfo(String name, Drawable avatar) { mUserState.label = name; mUserState.avatar = avatar; mUserCallback.refreshView(mUserTile, mUserState); } // Time void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) { mTimeTile = view; mTimeAlarmCallback = cb; mTimeAlarmCallback.refreshView(view, mTimeAlarmState); } void onAlarmChanged(Intent intent) { mTimeAlarmState.enabled = intent.getBooleanExtra("alarmSet", false); mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); } void onNextAlarmChanged() { mTimeAlarmState.label = Settings.System.getString(mContext.getContentResolver(), Settings.System.NEXT_ALARM_FORMATTED); mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); } // Airplane Mode void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) { mAirplaneModeTile = view; mAirplaneModeTile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mAirplaneModeState.enabled) { setAirplaneModeState(false); } else { setAirplaneModeState(true); } } }); mAirplaneModeCallback = cb; mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); } private void setAirplaneModeState(boolean enabled) { // TODO: Sets the view to be "awaiting" if not already awaiting // Change the system setting Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, enabled ? 1 : 0); // Post the intent Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", enabled); mContext.sendBroadcast(intent); } // NetworkSignalChanged callback @Override public void onAirplaneModeChanged(boolean enabled) { // TODO: If view is in awaiting state, disable Resources r = mContext.getResources(); mAirplaneModeState.enabled = enabled; mAirplaneModeState.iconId = (enabled ? R.drawable.ic_qs_airplane_on : R.drawable.ic_qs_airplane_off); mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); } // Wifi void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) { mWifiTile = view; mWifiCallback = cb; mWifiCallback.refreshView(mWifiTile, mWifiState); } // NetworkSignalChanged callback @Override public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String enabledDesc) { // TODO: If view is in awaiting state, disable Resources r = mContext.getResources(); mWifiState.iconId = enabled && (wifiSignalIconId > 0) ? wifiSignalIconId : R.drawable.ic_qs_wifi_no_network; mWifiState.label = enabled ? enabledDesc : r.getString(R.string.quick_settings_wifi_no_network); mWifiCallback.refreshView(mWifiTile, mWifiState); } // RSSI void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) { mRSSITile = view; mRSSICallback = cb; mRSSICallback.refreshView(mRSSITile, mRSSIState); } boolean deviceSupportsTelephony() { PackageManager pm = mContext.getPackageManager(); return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); } // NetworkSignalChanged callback @Override public void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, int dataTypeIconId, String enabledDesc) { if (deviceSupportsTelephony()) { // TODO: If view is in awaiting state, disable Resources r = mContext.getResources(); mRSSIState.signalIconId = enabled && (mobileSignalIconId > 0) ? mobileSignalIconId : R.drawable.ic_qs_signal_no_signal; mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) ? dataTypeIconId : 0; mRSSIState.label = enabled ? enabledDesc : r.getString(R.string.quick_settings_rssi_emergency_only); mRSSICallback.refreshView(mRSSITile, mRSSIState); } } // Bluetooth void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { mBluetoothTile = view; mBluetoothCallback = cb; final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); onBluetoothStateChange(adapter.isEnabled()); } boolean deviceSupportsBluetooth() { return (BluetoothAdapter.getDefaultAdapter() != null); } // BluetoothController callback @Override public void onBluetoothStateChange(boolean on) { // TODO: If view is in awaiting state, disable Resources r = mContext.getResources(); mBluetoothState.enabled = on; if (on) { mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on; } else { mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off; } mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); } // Battery void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) { mBatteryTile = view; mBatteryCallback = cb; mBatteryCallback.refreshView(mBatteryTile, mBatteryState); } // BatteryController callback @Override public void onBatteryLevelChanged(int level, boolean pluggedIn) { mBatteryState.batteryLevel = level; mBatteryState.pluggedIn = pluggedIn; mBatteryCallback.refreshView(mBatteryTile, mBatteryState); } // Location void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) { mLocationTile = view; mLocationCallback = cb; mLocationCallback.refreshView(mLocationTile, mLocationState); } // LocationController callback @Override public void onLocationGpsStateChanged(boolean inUse, String description) { mLocationState.enabled = inUse; mLocationState.label = description; mLocationCallback.refreshView(mLocationTile, mLocationState); } // Wifi Display void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { mWifiDisplayTile = view; mWifiDisplayCallback = cb; } public void onWifiDisplayStateChanged(WifiDisplayStatus status) { mWifiDisplayState.enabled = status.isEnabled(); if (status.getActiveDisplay() != null) { mWifiDisplayState.label = status.getActiveDisplay().getDeviceName(); } else { mWifiDisplayState.label = mContext.getString( R.string.quick_settings_wifi_display_no_connection_label); } mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); } // IME void addImeTile(QuickSettingsTileView view, RefreshCallback cb) { mImeTile = view; mImeCallback = cb; mImeCallback.refreshView(mImeTile, mImeState); } void onImeWindowStatusChanged(boolean visible) { InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); List imis = imm.getInputMethodList(); mImeState.enabled = visible; mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(), imm, imis, mContext.getPackageManager()); mImeCallback.refreshView(mImeTile, mImeState); } private static String getCurrentInputMethodName(Context context, ContentResolver resolver, InputMethodManager imm, List imis, PackageManager pm) { if (resolver == null || imis == null) return null; final String currentInputMethodId = Settings.Secure.getString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD); if (TextUtils.isEmpty(currentInputMethodId)) return null; for (InputMethodInfo imi : imis) { if (currentInputMethodId.equals(imi.getId())) { final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype(); final CharSequence summary = subtype != null ? subtype.getDisplayName(context, imi.getPackageName(), imi.getServiceInfo().applicationInfo) : context.getString(R.string.quick_settings_ime_label); return summary.toString(); } } return null; } // Rotation lock void addRotationLockTile(QuickSettingsTileView view, RefreshCallback cb) { mRotationLockTile = view; mRotationLockCallback = cb; onRotationLockChanged(); } void onRotationLockChanged() { boolean locked = RotationPolicy.isRotationLocked(mContext); mRotationLockState.enabled = locked; mRotationLockState.iconId = locked ? R.drawable.ic_qs_rotation_locked : R.drawable.ic_qs_auto_rotate; mRotationLockState.label = locked ? mContext.getString(R.string.quick_settings_rotation_locked_label) : mContext.getString(R.string.quick_settings_rotation_unlocked_label); mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState); } }