blob: 25965fc863706caa49326cab8e1b38206a742b9d [file] [log] [blame]
/*
* Copyright (C) 2021 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.people;
import android.annotation.ColorInt;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.IconDrawableFactory;
import android.util.Log;
import android.view.ContextThemeWrapper;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import com.android.settingslib.Utils;
class PeopleStoryIconFactory implements AutoCloseable {
private static final int PADDING = 2;
private static final int RING_WIDTH = 2;
private static final int MAX_BADGE_SIZE = 40;
final PackageManager mPackageManager;
final IconDrawableFactory mIconDrawableFactory;
private int mImportantConversationColor;
private int mAccentColor;
private float mDensity;
private float mIconSize;
private Context mContext;
private final int mIconBitmapSize;
PeopleStoryIconFactory(Context context, PackageManager pm,
IconDrawableFactory iconDrawableFactory, int iconSizeDp) {
mContext = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_DayNight);
mIconBitmapSize = (int) (iconSizeDp * mContext.getResources().getDisplayMetrics().density);
mDensity = mContext.getResources().getDisplayMetrics().density;
mIconSize = mDensity * iconSizeDp;
mPackageManager = pm;
mIconDrawableFactory = iconDrawableFactory;
mImportantConversationColor = mContext.getColor(
com.android.launcher3.icons.R.color.important_conversation);
mAccentColor = Utils.getColorAttr(mContext,
com.android.internal.R.attr.colorAccentPrimaryVariant).getDefaultColor();
}
/**
* Gets the {@link Drawable} that represents the app icon, badged with the work profile icon
* if appropriate.
*/
private Drawable getAppBadge(String packageName, int userId) {
Drawable badge = null;
try {
final ApplicationInfo appInfo = mPackageManager.getApplicationInfoAsUser(
packageName, PackageManager.GET_META_DATA, userId);
badge = Utils.getBadgedIcon(mContext, appInfo);
} catch (PackageManager.NameNotFoundException e) {
badge = mPackageManager.getDefaultActivityIcon();
}
return badge;
}
/**
* Returns a {@link Drawable} for the entire conversation. The shortcut icon will be badged
* with the launcher icon of the app specified by packageName.
*/
public Drawable getPeopleTileDrawable(RoundedBitmapDrawable headDrawable, String packageName,
int userId,
boolean important, boolean newStory) {
return new PeopleStoryIconDrawable(headDrawable, getAppBadge(packageName, userId),
mIconBitmapSize, mImportantConversationColor, important, mIconSize, mDensity,
mAccentColor, newStory);
}
/**
* Custom drawable which overlays a badge drawable on a head icon (conversation/person avatar),
* with decorations indicating Important conversations and having a New Story.
*/
public static class PeopleStoryIconDrawable extends Drawable {
private float mFullIconSize;
private RoundedBitmapDrawable mAvatar;
private Drawable mBadgeIcon;
private int mIconSize;
private Paint mPriorityRingPaint;
private boolean mShowImportantRing;
private boolean mShowStoryRing;
private Paint mStoryPaint;
private float mDensity;
PeopleStoryIconDrawable(RoundedBitmapDrawable avatar,
Drawable badgeIcon,
int iconSize,
@ColorInt int ringColor,
boolean showImportantRing, float fullIconSize, float density,
@ColorInt int accentColor, boolean showStoryRing) {
avatar.setCircular(true);
mAvatar = avatar;
mBadgeIcon = badgeIcon;
mIconSize = iconSize;
mShowImportantRing = showImportantRing;
mPriorityRingPaint = new Paint();
mPriorityRingPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPriorityRingPaint.setColor(ringColor);
mShowStoryRing = showStoryRing;
mStoryPaint = new Paint();
mStoryPaint.setStyle(Paint.Style.STROKE);
mStoryPaint.setColor(accentColor);
mFullIconSize = fullIconSize;
mDensity = density;
}
@Override
public int getIntrinsicWidth() {
return mIconSize;
}
@Override
public int getIntrinsicHeight() {
return mIconSize;
}
@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
final int minBound = Math.min(bounds.height(), bounds.width());
// Scale head icon and app icon to our canvas.
float scale = minBound / mFullIconSize;
int paddingInDp = (int) (PADDING * mDensity);
int ringStrokeWidth = (int) (RING_WIDTH * mDensity);
mPriorityRingPaint.setStrokeWidth(ringStrokeWidth);
mStoryPaint.setStrokeWidth(ringStrokeWidth);
int scaledFullIconSize = (int) (mFullIconSize * scale);
int avatarSize = scaledFullIconSize - (paddingInDp * 2);
if (mAvatar != null) {
int leftAndTopPadding = paddingInDp;
int rightAndBottomPadding = avatarSize + paddingInDp;
if (mShowStoryRing) {
int headCenter = scaledFullIconSize / 2;
canvas.drawCircle(headCenter, headCenter,
getRadius(avatarSize, ringStrokeWidth),
mStoryPaint);
leftAndTopPadding += (ringStrokeWidth + paddingInDp);
rightAndBottomPadding -= (ringStrokeWidth + paddingInDp);
}
mAvatar.setBounds(leftAndTopPadding,
leftAndTopPadding,
rightAndBottomPadding,
rightAndBottomPadding);
mAvatar.draw(canvas);
} else {
Log.w("PeopleStoryIconFactory", "Null avatar icon");
}
// Determine badge size from either the size relative to the head icon, or max size.
int maxBadgeSize = (int) (MAX_BADGE_SIZE * mDensity);
int badgeSizeRelativeToHead = (int) (avatarSize / 2.4);
int badgeSize = Math.min(maxBadgeSize, badgeSizeRelativeToHead);
if (mBadgeIcon != null) {
int leftAndTopPadding = scaledFullIconSize - badgeSize;
int rightAndBottomPadding = scaledFullIconSize;
if (mShowImportantRing) {
int badgeCenter = leftAndTopPadding + (badgeSize / 2);
canvas.drawCircle(badgeCenter, badgeCenter,
getRadius(badgeSize, ringStrokeWidth),
mPriorityRingPaint);
leftAndTopPadding += ringStrokeWidth;
rightAndBottomPadding -= ringStrokeWidth;
}
mBadgeIcon.setBounds(
leftAndTopPadding,
leftAndTopPadding,
rightAndBottomPadding,
rightAndBottomPadding);
mBadgeIcon.draw(canvas);
} else {
Log.w("PeopleStoryIconFactory", "Null badge icon");
}
}
private int getRadius(int circleWidth, int circleStrokeWidth) {
return (circleWidth - circleStrokeWidth) / 2;
}
@Override
public void setAlpha(int alpha) {
// unimplemented
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
if (mAvatar != null) mAvatar.setColorFilter(colorFilter);
if (mBadgeIcon != null) mBadgeIcon.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
@Override
public void close() {
}
}