Home | History | Annotate | Download | only in tiles
      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 
     17 package com.android.systemui.qs.tiles;
     18 
     19 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_MODE;
     20 
     21 import android.annotation.Nullable;
     22 import android.app.ActivityManager;
     23 import android.content.Intent;
     24 import android.metrics.LogMaker;
     25 import android.provider.Settings;
     26 import android.service.quicksettings.Tile;
     27 import android.support.annotation.StringRes;
     28 import android.util.Log;
     29 import android.widget.Switch;
     30 
     31 import com.android.internal.app.ColorDisplayController;
     32 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     33 import com.android.systemui.R;
     34 import com.android.systemui.qs.QSHost;
     35 import com.android.systemui.plugins.qs.QSTile.BooleanState;
     36 import com.android.systemui.qs.tileimpl.QSTileImpl;
     37 
     38 import java.time.LocalTime;
     39 import java.time.format.DateTimeFormatter;
     40 
     41 public class NightDisplayTile extends QSTileImpl<BooleanState>
     42         implements ColorDisplayController.Callback {
     43 
     44     /**
     45      * Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the
     46      * nearest hour and add on the AM/PM indicator.
     47      */
     48     private static final String PATTERN_HOUR = "h a";
     49     private static final String PATTERN_HOUR_MINUTE = "h:mm a";
     50 
     51 
     52     private ColorDisplayController mController;
     53     private boolean mIsListening;
     54 
     55     public NightDisplayTile(QSHost host) {
     56         super(host);
     57         mController = new ColorDisplayController(mContext, ActivityManager.getCurrentUser());
     58     }
     59 
     60     @Override
     61     public boolean isAvailable() {
     62         return ColorDisplayController.isAvailable(mContext);
     63     }
     64 
     65     @Override
     66     public BooleanState newTileState() {
     67         return new BooleanState();
     68     }
     69 
     70     @Override
     71     protected void handleClick() {
     72         // Enroll in forced auto mode if eligible.
     73         if ("1".equals(Settings.Global.getString(mContext.getContentResolver(),
     74                 Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE))
     75                 && mController.getAutoModeRaw() == -1) {
     76             mController.setAutoMode(ColorDisplayController.AUTO_MODE_CUSTOM);
     77             Log.i("NightDisplayTile", "Enrolled in forced night display auto mode");
     78         }
     79 
     80         // Change current activation state.
     81         final boolean activated = !mState.value;
     82         mController.setActivated(activated);
     83     }
     84 
     85     @Override
     86     protected void handleUserSwitch(int newUserId) {
     87         // Stop listening to the old controller.
     88         if (mIsListening) {
     89             mController.setListener(null);
     90         }
     91 
     92         // Make a new controller for the new user.
     93         mController = new ColorDisplayController(mContext, newUserId);
     94         if (mIsListening) {
     95             mController.setListener(this);
     96         }
     97 
     98         super.handleUserSwitch(newUserId);
     99     }
    100 
    101     @Override
    102     protected void handleUpdateState(BooleanState state, Object arg) {
    103         state.value = mController.isActivated();
    104         state.label = state.contentDescription =
    105                 mContext.getString(R.string.quick_settings_night_display_label);
    106         state.icon = ResourceIcon.get(R.drawable.ic_qs_night_display_on);
    107         state.expandedAccessibilityClassName = Switch.class.getName();
    108         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
    109         state.secondaryLabel = getSecondaryLabel(state.value);
    110     }
    111 
    112     /**
    113      * Returns a {@link String} for the secondary label that reflects when the light will be turned
    114      * on or off based on the current auto mode and night light activated status.
    115      */
    116     @Nullable
    117     private String getSecondaryLabel(boolean isNightLightActivated) {
    118         switch(mController.getAutoMode()) {
    119             case ColorDisplayController.AUTO_MODE_TWILIGHT:
    120                 // Auto mode related to sunrise & sunset. If the light is on, it's guaranteed to be
    121                 // turned off at sunrise. If it's off, it's guaranteed to be turned on at sunset.
    122                 return isNightLightActivated
    123                         ? mContext.getString(
    124                                 R.string.quick_settings_night_secondary_label_until_sunrise)
    125                         : mContext.getString(
    126                                 R.string.quick_settings_night_secondary_label_on_at_sunset);
    127 
    128             case ColorDisplayController.AUTO_MODE_CUSTOM:
    129                 // User-specified time, approximated to the nearest hour.
    130                 final @StringRes int toggleTimeStringRes;
    131                 final LocalTime toggleTime;
    132                 final DateTimeFormatter toggleTimeFormat;
    133 
    134                 if (isNightLightActivated) {
    135                     toggleTime = mController.getCustomEndTime();
    136                     toggleTimeStringRes = R.string.quick_settings_secondary_label_until;
    137                 } else {
    138                     toggleTime = mController.getCustomStartTime();
    139                     toggleTimeStringRes = R.string.quick_settings_night_secondary_label_on_at;
    140                 }
    141 
    142                 // Choose between just showing the hour or also showing the minutes (based on the
    143                 // user-selected toggle time). This helps reduce how much space the label takes.
    144                 toggleTimeFormat = DateTimeFormatter.ofPattern(
    145                         toggleTime.getMinute() == 0 ? PATTERN_HOUR : PATTERN_HOUR_MINUTE);
    146 
    147                 return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
    148 
    149             default:
    150                 // No secondary label when auto mode is disabled.
    151                 return null;
    152         }
    153     }
    154 
    155     @Override
    156     public int getMetricsCategory() {
    157         return MetricsEvent.QS_NIGHT_DISPLAY;
    158     }
    159 
    160     @Override
    161     public LogMaker populate(LogMaker logMaker) {
    162         return super.populate(logMaker).addTaggedData(FIELD_QS_MODE, mController.getAutoModeRaw());
    163     }
    164 
    165     @Override
    166     public Intent getLongClickIntent() {
    167         return new Intent(Settings.ACTION_NIGHT_DISPLAY_SETTINGS);
    168     }
    169 
    170     @Override
    171     protected void handleSetListening(boolean listening) {
    172         mIsListening = listening;
    173         if (listening) {
    174             mController.setListener(this);
    175             refreshState();
    176         } else {
    177             mController.setListener(null);
    178         }
    179     }
    180 
    181     @Override
    182     public CharSequence getTileLabel() {
    183         return mContext.getString(R.string.quick_settings_night_display_label);
    184     }
    185 
    186     @Override
    187     public void onActivated(boolean activated) {
    188         refreshState();
    189     }
    190 }
    191