1 /* 2 * Copyright (C) 2020 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.keyguard; 18 19 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 20 21 import android.annotation.SuppressLint; 22 import android.content.Context; 23 import android.content.res.ColorStateList; 24 import android.graphics.Color; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.graphics.RectF; 28 import android.util.AttributeSet; 29 import android.view.Gravity; 30 import android.view.View; 31 import android.widget.FrameLayout; 32 import android.widget.ImageView; 33 34 import androidx.annotation.IntDef; 35 import androidx.annotation.NonNull; 36 37 import com.android.internal.graphics.ColorUtils; 38 import com.android.settingslib.Utils; 39 import com.android.systemui.Dumpable; 40 import com.android.systemui.res.R; 41 42 import java.io.PrintWriter; 43 44 /** 45 * A view positioned under the notification shade. 46 */ 47 public class LockIconView extends FrameLayout implements Dumpable { 48 @IntDef({ICON_NONE, ICON_LOCK, ICON_FINGERPRINT, ICON_UNLOCK}) 49 public @interface IconType {} 50 51 public static final int ICON_NONE = -1; 52 public static final int ICON_LOCK = 0; 53 public static final int ICON_FINGERPRINT = 1; 54 public static final int ICON_UNLOCK = 2; 55 56 private @IconType int mIconType; 57 private boolean mAod; 58 59 @NonNull private final RectF mSensorRect; 60 @NonNull private Point mLockIconCenter = new Point(0, 0); 61 private float mRadius; 62 private int mLockIconPadding; 63 64 private ImageView mLockIcon; 65 private ImageView mBgView; 66 67 private int mLockIconColor; 68 private boolean mUseBackground = false; 69 private float mDozeAmount = 0f; 70 71 @SuppressLint("ClickableViewAccessibility") LockIconView(Context context, AttributeSet attrs)72 public LockIconView(Context context, AttributeSet attrs) { 73 super(context, attrs); 74 mSensorRect = new RectF(); 75 76 addBgImageView(context, attrs); 77 addLockIconImageView(context, attrs); 78 } 79 setDozeAmount(float dozeAmount)80 void setDozeAmount(float dozeAmount) { 81 mDozeAmount = dozeAmount; 82 updateColorAndBackgroundVisibility(); 83 } 84 updateColorAndBackgroundVisibility()85 void updateColorAndBackgroundVisibility() { 86 if (mUseBackground && mLockIcon.getDrawable() != null) { 87 mLockIconColor = ColorUtils.blendARGB( 88 Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary), 89 Color.WHITE, 90 mDozeAmount); 91 int backgroundColor = Utils.getColorAttrDefaultColor(getContext(), 92 com.android.internal.R.attr.colorSurface); 93 mBgView.setImageTintList(ColorStateList.valueOf(backgroundColor)); 94 mBgView.setAlpha(1f - mDozeAmount); 95 mBgView.setVisibility(View.VISIBLE); 96 } else { 97 mLockIconColor = ColorUtils.blendARGB( 98 Utils.getColorAttrDefaultColor(getContext(), R.attr.wallpaperTextColorAccent), 99 Color.WHITE, 100 mDozeAmount); 101 mBgView.setVisibility(View.GONE); 102 } 103 104 mLockIcon.setImageTintList(ColorStateList.valueOf(mLockIconColor)); 105 } 106 107 /** 108 * Whether or not to render the lock icon background. Mainly used for UDPFS. 109 */ setUseBackground(boolean useBackground)110 public void setUseBackground(boolean useBackground) { 111 mUseBackground = useBackground; 112 updateColorAndBackgroundVisibility(); 113 } 114 115 /** 116 * Set the location of the lock icon. 117 */ setCenterLocation(@onNull Point center, float radius, int drawablePadding)118 public void setCenterLocation(@NonNull Point center, float radius, int drawablePadding) { 119 mLockIconCenter = center; 120 mRadius = radius; 121 mLockIconPadding = drawablePadding; 122 123 mLockIcon.setPadding(mLockIconPadding, mLockIconPadding, mLockIconPadding, 124 mLockIconPadding); 125 126 mSensorRect.set(mLockIconCenter.x - mRadius, 127 mLockIconCenter.y - mRadius, 128 mLockIconCenter.x + mRadius, 129 mLockIconCenter.y + mRadius); 130 131 final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); 132 if (lp != null) { 133 lp.width = (int) (mSensorRect.right - mSensorRect.left); 134 lp.height = (int) (mSensorRect.bottom - mSensorRect.top); 135 lp.topMargin = (int) mSensorRect.top; 136 lp.setMarginStart((int) mSensorRect.left); 137 setLayoutParams(lp); 138 } 139 } 140 141 @Override hasOverlappingRendering()142 public boolean hasOverlappingRendering() { 143 return false; 144 } 145 getLocationTop()146 float getLocationTop() { 147 Rect r = new Rect(); 148 mLockIcon.getGlobalVisibleRect(r); 149 return r.top; 150 } 151 getLocationBottom()152 float getLocationBottom() { 153 Rect r = new Rect(); 154 mLockIcon.getGlobalVisibleRect(r); 155 return r.bottom; 156 157 } 158 159 /** 160 * Updates the icon its default state where no visual is shown. 161 */ clearIcon()162 public void clearIcon() { 163 updateIcon(ICON_NONE, false); 164 } 165 166 /** 167 * Transition the current icon to a new state 168 * @param icon type (ie: lock icon, unlock icon, fingerprint icon) 169 * @param aod whether to use the aod icon variant (some icons don't have aod variants and will 170 * therefore show no icon) 171 */ updateIcon(@conType int icon, boolean aod)172 public void updateIcon(@IconType int icon, boolean aod) { 173 mIconType = icon; 174 mAod = aod; 175 176 mLockIcon.setImageState(getLockIconState(mIconType, mAod), true); 177 } 178 getLockIcon()179 public ImageView getLockIcon() { 180 return mLockIcon; 181 } 182 addLockIconImageView(Context context, AttributeSet attrs)183 private void addLockIconImageView(Context context, AttributeSet attrs) { 184 mLockIcon = new ImageView(context, attrs); 185 mLockIcon.setId(R.id.lock_icon); 186 mLockIcon.setScaleType(ImageView.ScaleType.CENTER_CROP); 187 mLockIcon.setImageDrawable(context.getDrawable(R.drawable.super_lock_icon)); 188 addView(mLockIcon); 189 LayoutParams lp = (LayoutParams) mLockIcon.getLayoutParams(); 190 lp.height = MATCH_PARENT; 191 lp.width = MATCH_PARENT; 192 lp.gravity = Gravity.CENTER; 193 mLockIcon.setLayoutParams(lp); 194 } 195 addBgImageView(Context context, AttributeSet attrs)196 private void addBgImageView(Context context, AttributeSet attrs) { 197 mBgView = new ImageView(context, attrs); 198 mBgView.setId(R.id.lock_icon_bg); 199 mBgView.setImageDrawable(context.getDrawable(R.drawable.fingerprint_bg)); 200 mBgView.setVisibility(View.INVISIBLE); 201 addView(mBgView); 202 LayoutParams lp = (LayoutParams) mBgView.getLayoutParams(); 203 lp.height = MATCH_PARENT; 204 lp.width = MATCH_PARENT; 205 mBgView.setLayoutParams(lp); 206 } 207 getLockIconState(@conType int icon, boolean aod)208 private static int[] getLockIconState(@IconType int icon, boolean aod) { 209 if (icon == ICON_NONE) { 210 return new int[0]; 211 } 212 213 int[] lockIconState = new int[2]; 214 switch (icon) { 215 case ICON_LOCK: 216 lockIconState[0] = android.R.attr.state_first; 217 break; 218 case ICON_FINGERPRINT: 219 lockIconState[0] = android.R.attr.state_middle; 220 break; 221 case ICON_UNLOCK: 222 lockIconState[0] = android.R.attr.state_last; 223 break; 224 } 225 226 if (aod) { 227 lockIconState[1] = android.R.attr.state_single; 228 } else { 229 lockIconState[1] = -android.R.attr.state_single; 230 } 231 232 return lockIconState; 233 } 234 typeToString(@conType int type)235 private String typeToString(@IconType int type) { 236 switch (type) { 237 case ICON_NONE: 238 return "none"; 239 case ICON_LOCK: 240 return "lock"; 241 case ICON_FINGERPRINT: 242 return "fingerprint"; 243 case ICON_UNLOCK: 244 return "unlock"; 245 } 246 247 return "invalid"; 248 } 249 250 @Override dump(@onNull PrintWriter pw, @NonNull String[] args)251 public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { 252 pw.println("Lock Icon View Parameters:"); 253 pw.println(" Center in px (x, y)= (" 254 + mLockIconCenter.x + ", " + mLockIconCenter.y + ")"); 255 pw.println(" Radius in pixels: " + mRadius); 256 pw.println(" Drawable padding: " + mLockIconPadding); 257 pw.println(" mIconType=" + typeToString(mIconType)); 258 pw.println(" mAod=" + mAod); 259 pw.println("Lock Icon View actual measurements:"); 260 pw.println(" topLeft= (" + getX() + ", " + getY() + ")"); 261 pw.println(" width=" + getWidth() + " height=" + getHeight()); 262 } 263 } 264