Home | History | Annotate | Download | only in tiles
      1 /*
      2  * Copyright (C) 2015 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 
     17 package com.android.systemui.qs.tiles;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.content.SharedPreferences;
     24 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
     25 import android.provider.Settings;
     26 import android.provider.Settings.Global;
     27 import android.view.LayoutInflater;
     28 import android.view.View;
     29 import android.view.View.OnAttachStateChangeListener;
     30 import android.view.ViewGroup;
     31 import android.widget.Toast;
     32 
     33 import com.android.internal.logging.MetricsLogger;
     34 import com.android.systemui.Prefs;
     35 import com.android.systemui.R;
     36 import com.android.systemui.SysUIToast;
     37 import com.android.systemui.qs.QSTile;
     38 import com.android.systemui.statusbar.policy.ZenModeController;
     39 import com.android.systemui.volume.ZenModePanel;
     40 
     41 /** Quick settings tile: Do not disturb **/
     42 public class DndTile extends QSTile<QSTile.BooleanState> {
     43 
     44     private static final Intent ZEN_SETTINGS =
     45             new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
     46 
     47     private static final Intent ZEN_PRIORITY_SETTINGS =
     48             new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
     49 
     50     private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
     51     private static final String EXTRA_VISIBLE = "visible";
     52 
     53     private static final QSTile.Icon TOTAL_SILENCE =
     54             ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
     55 
     56     private final AnimationIcon mDisable =
     57             new AnimationIcon(R.drawable.ic_dnd_disable_animation);
     58     private final AnimationIcon mDisableTotalSilence =
     59             new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation);
     60 
     61     private final ZenModeController mController;
     62     private final DndDetailAdapter mDetailAdapter;
     63 
     64     private boolean mListening;
     65     private boolean mShowingDetail;
     66 
     67     public DndTile(Host host) {
     68         super(host);
     69         mController = host.getZenModeController();
     70         mDetailAdapter = new DndDetailAdapter();
     71         mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
     72     }
     73 
     74     public static void setVisible(Context context, boolean visible) {
     75         Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
     76     }
     77 
     78     public static boolean isVisible(Context context) {
     79         return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */);
     80     }
     81 
     82     public static void setCombinedIcon(Context context, boolean combined) {
     83         Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined);
     84     }
     85 
     86     public static boolean isCombinedIcon(Context context) {
     87         return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON,
     88                 false /* defaultValue */);
     89     }
     90 
     91     @Override
     92     public DetailAdapter getDetailAdapter() {
     93         return mDetailAdapter;
     94     }
     95 
     96     @Override
     97     protected BooleanState newTileState() {
     98         return new BooleanState();
     99     }
    100 
    101     @Override
    102     public void handleClick() {
    103         if (mController.isVolumeRestricted()) {
    104             // Collapse the panels, so the user can see the toast.
    105             mHost.collapsePanels();
    106             SysUIToast.makeText(mContext, mContext.getString(
    107                     com.android.internal.R.string.error_message_change_not_allowed),
    108                     Toast.LENGTH_LONG).show();
    109             return;
    110         }
    111         mDisable.setAllowAnimation(true);
    112         mDisableTotalSilence.setAllowAnimation(true);
    113         MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
    114         if (mState.value) {
    115             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
    116         } else {
    117             int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
    118             mController.setZen(zen, null, TAG);
    119             showDetail(true);
    120         }
    121     }
    122 
    123     @Override
    124     protected void handleUpdateState(BooleanState state, Object arg) {
    125         final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
    126         final boolean newValue = zen != Global.ZEN_MODE_OFF;
    127         final boolean valueChanged = state.value != newValue;
    128         state.value = newValue;
    129         state.visible = isVisible(mContext);
    130         switch (zen) {
    131             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
    132                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
    133                 state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
    134                 state.contentDescription = mContext.getString(
    135                         R.string.accessibility_quick_settings_dnd_priority_on);
    136                 break;
    137             case Global.ZEN_MODE_NO_INTERRUPTIONS:
    138                 state.icon = TOTAL_SILENCE;
    139                 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
    140                 state.contentDescription = mContext.getString(
    141                         R.string.accessibility_quick_settings_dnd_none_on);
    142                 break;
    143             case Global.ZEN_MODE_ALARMS:
    144                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
    145                 state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
    146                 state.contentDescription = mContext.getString(
    147                         R.string.accessibility_quick_settings_dnd_alarms_on);
    148                 break;
    149             default:
    150                 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
    151                 state.label = mContext.getString(R.string.quick_settings_dnd_label);
    152                 state.contentDescription =  mContext.getString(
    153                         R.string.accessibility_quick_settings_dnd_off);
    154                 break;
    155         }
    156         if (mShowingDetail && !state.value) {
    157             showDetail(false);
    158         }
    159         if (valueChanged) {
    160             fireToggleStateChanged(state.value);
    161         }
    162     }
    163 
    164     @Override
    165     public int getMetricsCategory() {
    166         return MetricsLogger.QS_DND;
    167     }
    168 
    169     @Override
    170     protected String composeChangeAnnouncement() {
    171         if (mState.value) {
    172             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
    173         } else {
    174             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
    175         }
    176     }
    177 
    178     @Override
    179     public void setListening(boolean listening) {
    180         if (mListening == listening) return;
    181         mListening = listening;
    182         if (mListening) {
    183             mController.addCallback(mZenCallback);
    184             Prefs.registerListener(mContext, mPrefListener);
    185         } else {
    186             mController.removeCallback(mZenCallback);
    187             Prefs.unregisterListener(mContext, mPrefListener);
    188         }
    189     }
    190 
    191     private final OnSharedPreferenceChangeListener mPrefListener
    192             = new OnSharedPreferenceChangeListener() {
    193         @Override
    194         public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
    195                 @Prefs.Key String key) {
    196             if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
    197                     Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
    198                 refreshState();
    199             }
    200         }
    201     };
    202 
    203     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
    204         public void onZenChanged(int zen) {
    205             refreshState(zen);
    206         }
    207     };
    208 
    209     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    210         @Override
    211         public void onReceive(Context context, Intent intent) {
    212             final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
    213             setVisible(mContext, visible);
    214             refreshState();
    215         }
    216     };
    217 
    218     private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
    219 
    220         @Override
    221         public int getTitle() {
    222             return R.string.quick_settings_dnd_label;
    223         }
    224 
    225         @Override
    226         public Boolean getToggleState() {
    227             return mState.value;
    228         }
    229 
    230         @Override
    231         public Intent getSettingsIntent() {
    232             return ZEN_SETTINGS;
    233         }
    234 
    235         @Override
    236         public void setToggleState(boolean state) {
    237             MetricsLogger.action(mContext, MetricsLogger.QS_DND_TOGGLE, state);
    238             if (!state) {
    239                 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
    240                 showDetail(false);
    241             }
    242         }
    243 
    244         @Override
    245         public int getMetricsCategory() {
    246             return MetricsLogger.QS_DND_DETAILS;
    247         }
    248 
    249         @Override
    250         public View createDetailView(Context context, View convertView, ViewGroup parent) {
    251             final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
    252                     : (ZenModePanel) LayoutInflater.from(context).inflate(
    253                             R.layout.zen_mode_panel, parent, false);
    254             if (convertView == null) {
    255                 zmp.init(mController);
    256                 zmp.addOnAttachStateChangeListener(this);
    257                 zmp.setCallback(mZenModePanelCallback);
    258             }
    259             return zmp;
    260         }
    261 
    262         @Override
    263         public void onViewAttachedToWindow(View v) {
    264             mShowingDetail = true;
    265         }
    266 
    267         @Override
    268         public void onViewDetachedFromWindow(View v) {
    269             mShowingDetail = false;
    270         }
    271     }
    272 
    273     private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
    274         @Override
    275         public void onPrioritySettings() {
    276             mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
    277         }
    278 
    279         @Override
    280         public void onInteraction() {
    281             // noop
    282         }
    283 
    284         @Override
    285         public void onExpanded(boolean expanded) {
    286             // noop
    287         }
    288     };
    289 
    290 }
    291