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; 18 19 import android.content.Context; 20 import android.content.res.Configuration; 21 import android.util.AttributeSet; 22 import android.view.View; 23 import android.widget.LinearLayout; 24 25 import com.android.internal.logging.UiEventLogger; 26 import com.android.systemui.R; 27 import com.android.systemui.plugins.qs.QSTile; 28 import com.android.systemui.plugins.qs.QSTile.SignalState; 29 import com.android.systemui.plugins.qs.QSTile.State; 30 31 /** 32 * Version of QSPanel that only shows N Quick Tiles in the QS Header. 33 */ 34 public class QuickQSPanel extends QSPanel { 35 36 public static final String NUM_QUICK_TILES = "sysui_qqs_count"; 37 private static final String TAG = "QuickQSPanel"; 38 // A default value so that we never return 0. 39 public static final int DEFAULT_MAX_TILES = 6; 40 41 private boolean mDisabledByPolicy; 42 private int mMaxTiles; 43 QuickQSPanel(Context context, AttributeSet attrs)44 public QuickQSPanel(Context context, AttributeSet attrs) { 45 super(context, attrs); 46 mMaxTiles = Math.min(DEFAULT_MAX_TILES, 47 getResources().getInteger(R.integer.quick_qs_panel_max_columns)); 48 } 49 50 @Override setBrightnessView(View view)51 public void setBrightnessView(View view) { 52 // Don't add brightness view 53 } 54 55 @Override initialize()56 void initialize() { 57 super.initialize(); 58 if (mHorizontalContentContainer != null) { 59 mHorizontalContentContainer.setClipChildren(false); 60 } 61 } 62 63 @Override getOrCreateTileLayout()64 public TileLayout getOrCreateTileLayout() { 65 return new QQSSideLabelTileLayout(mContext); 66 } 67 68 69 @Override displayMediaMarginsOnMedia()70 protected boolean displayMediaMarginsOnMedia() { 71 // Margins should be on the container to visually center the view 72 return false; 73 } 74 75 @Override mediaNeedsTopMargin()76 protected boolean mediaNeedsTopMargin() { 77 return true; 78 } 79 80 @Override updatePadding()81 protected void updatePadding() { 82 // QS Panel is setting a top padding by default, which we don't need. 83 } 84 85 @Override getDumpableTag()86 protected String getDumpableTag() { 87 return TAG; 88 } 89 90 @Override shouldShowDetail()91 protected boolean shouldShowDetail() { 92 return !mExpanded; 93 } 94 95 @Override drawTile(QSPanelControllerBase.TileRecord r, State state)96 protected void drawTile(QSPanelControllerBase.TileRecord r, State state) { 97 if (state instanceof SignalState) { 98 SignalState copy = new SignalState(); 99 state.copyTo(copy); 100 // No activity shown in the quick panel. 101 copy.activityIn = false; 102 copy.activityOut = false; 103 state = copy; 104 } 105 super.drawTile(r, state); 106 } 107 setMaxTiles(int maxTiles)108 public void setMaxTiles(int maxTiles) { 109 mMaxTiles = Math.min(maxTiles, DEFAULT_MAX_TILES); 110 } 111 112 @Override onTuningChanged(String key, String newValue)113 public void onTuningChanged(String key, String newValue) { 114 if (QS_SHOW_BRIGHTNESS.equals(key)) { 115 // No Brightness or Tooltip for you! 116 super.onTuningChanged(key, "0"); 117 } 118 } 119 getNumQuickTiles()120 public int getNumQuickTiles() { 121 return mMaxTiles; 122 } 123 124 /** 125 * Parses the String setting into the number of tiles. Defaults to {@code mDefaultMaxTiles} 126 * 127 * @param numTilesValue value of the setting to parse 128 * @return parsed value of numTilesValue OR {@code mDefaultMaxTiles} on error 129 */ parseNumTiles(String numTilesValue)130 public static int parseNumTiles(String numTilesValue) { 131 try { 132 return Integer.parseInt(numTilesValue); 133 } catch (NumberFormatException e) { 134 // Couldn't read an int from the new setting value. Use default. 135 return DEFAULT_MAX_TILES; 136 } 137 } 138 setDisabledByPolicy(boolean disabled)139 void setDisabledByPolicy(boolean disabled) { 140 if (disabled != mDisabledByPolicy) { 141 mDisabledByPolicy = disabled; 142 setVisibility(disabled ? View.GONE : View.VISIBLE); 143 } 144 } 145 146 /** 147 * Sets the visibility of this {@link QuickQSPanel}. This method has no effect when this panel 148 * is disabled by policy through {@link #setDisabledByPolicy(boolean)}, and in this case the 149 * visibility will always be {@link View#GONE}. This method is called externally by 150 * {@link QSAnimator} only. 151 */ 152 @Override setVisibility(int visibility)153 public void setVisibility(int visibility) { 154 if (mDisabledByPolicy) { 155 if (getVisibility() == View.GONE) { 156 return; 157 } 158 visibility = View.GONE; 159 } 160 super.setVisibility(visibility); 161 } 162 163 @Override openPanelEvent()164 protected QSEvent openPanelEvent() { 165 return QSEvent.QQS_PANEL_EXPANDED; 166 } 167 168 @Override closePanelEvent()169 protected QSEvent closePanelEvent() { 170 return QSEvent.QQS_PANEL_COLLAPSED; 171 } 172 173 @Override tileVisibleEvent()174 protected QSEvent tileVisibleEvent() { 175 return QSEvent.QQS_TILE_VISIBLE; 176 } 177 178 static class QQSSideLabelTileLayout extends SideLabelTileLayout { 179 180 private boolean mLastSelected; 181 QQSSideLabelTileLayout(Context context)182 QQSSideLabelTileLayout(Context context) { 183 super(context, null); 184 setClipChildren(false); 185 setClipToPadding(false); 186 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 187 LayoutParams.WRAP_CONTENT); 188 setLayoutParams(lp); 189 setMaxColumns(4); 190 } 191 192 @Override updateResources()193 public boolean updateResources() { 194 mCellHeightResId = R.dimen.qs_quick_tile_size; 195 boolean b = super.updateResources(); 196 mMaxAllowedRows = 2; 197 return b; 198 } 199 200 @Override onConfigurationChanged(Configuration newConfig)201 protected void onConfigurationChanged(Configuration newConfig) { 202 super.onConfigurationChanged(newConfig); 203 updateResources(); 204 } 205 206 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)207 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 208 // Make sure to always use the correct number of rows. As it's determined by the 209 // columns, just use as many as needed. 210 updateMaxRows(10000, mRecords.size()); 211 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 212 } 213 214 @Override setListening(boolean listening, UiEventLogger uiEventLogger)215 public void setListening(boolean listening, UiEventLogger uiEventLogger) { 216 boolean startedListening = !mListening && listening; 217 super.setListening(listening, uiEventLogger); 218 if (startedListening) { 219 // getNumVisibleTiles() <= mRecords.size() 220 for (int i = 0; i < getNumVisibleTiles(); i++) { 221 QSTile tile = mRecords.get(i).tile; 222 uiEventLogger.logWithInstanceId(QSEvent.QQS_TILE_VISIBLE, 0, 223 tile.getMetricsSpec(), tile.getInstanceId()); 224 } 225 } 226 } 227 228 @Override setExpansion(float expansion, float proposedTranslation)229 public void setExpansion(float expansion, float proposedTranslation) { 230 if (expansion > 0f && expansion < 1f) { 231 return; 232 } 233 // The cases we must set select for marquee when QQS/QS collapsed, and QS full expanded. 234 // Expansion == 0f is when QQS is fully showing (as opposed to 1f, which is QS). At this 235 // point we want them to be selected so the tiles will marquee (but not at other points 236 // of expansion. 237 boolean selected = (expansion == 1f || proposedTranslation < 0f); 238 if (mLastSelected == selected) { 239 return; 240 } 241 // We set it as not important while we change this, so setting each tile as selected 242 // will not cause them to announce themselves until the user has actually selected the 243 // item. 244 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); 245 for (int i = 0; i < getChildCount(); i++) { 246 getChildAt(i).setSelected(selected); 247 } 248 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); 249 mLastSelected = selected; 250 } 251 } 252 } 253