diff options
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java | 7 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/CarUserSwitchingDialog.java | 114 |
2 files changed, 110 insertions, 11 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java index 5768fa2384e4..fc76f78e0b1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java @@ -38,6 +38,8 @@ import android.widget.TextView; import androidx.car.widget.PagedListView; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import com.android.internal.util.UserIcons; import com.android.settingslib.users.UserManagerHelper; import com.android.systemui.R; @@ -193,7 +195,10 @@ public class UserGridRecyclerView extends PagedListView implements @Override public void onBindViewHolder(UserAdapterViewHolder holder, int position) { UserRecord userRecord = mUsers.get(position); - holder.mUserAvatarImageView.setImageBitmap(getUserRecordIcon(userRecord)); + RoundedBitmapDrawable circleIcon = RoundedBitmapDrawableFactory.create(mRes, + getUserRecordIcon(userRecord)); + circleIcon.setCircular(true); + holder.mUserAvatarImageView.setImageDrawable(circleIcon); holder.mUserNameTextView.setText(userRecord.mInfo.name); holder.mView.setOnClickListener(v -> { if (userRecord == null) { diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java index 1149e8703a4f..7599afa3e04d 100644 --- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java +++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java @@ -20,33 +20,41 @@ import android.content.Context; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.UserManager; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.android.internal.R; -import com.android.server.pm.UserManagerService; -import java.io.FileDescriptor; + /** * Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the * screen immediately after the dialog shows so that the user is informed that something is * happening in the background rather than just freeze the screen and not know if the user-switch * affordance was being handled. - * */ final class CarUserSwitchingDialog extends UserSwitchingDialog { + private static final String TAG = "ActivityManagerCarUserSwitchingDialog"; public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser, - UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage, - String switchingToSystemUserMessage) { + UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage, + String switchingToSystemUserMessage) { super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage, - switchingToSystemUserMessage); + switchingToSystemUserMessage); getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); } @@ -58,18 +66,104 @@ final class CarUserSwitchingDialog extends UserSwitchingDialog { Resources res = getContext().getResources(); // Custom view due to alignment and font size requirements View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog, - null); + null); UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); Bitmap bitmap = userManager.getUserIcon(mNewUser.id); if (bitmap != null) { + CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap, + res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height)); ((ImageView) view.findViewById(R.id.user_loading_avatar)) - .setImageBitmap(bitmap); + .setImageDrawable(drawable); } ((TextView) view.findViewById(R.id.user_loading)) - .setText(res.getString(R.string.car_loading_profile)); + .setText(res.getString(R.string.car_loading_profile)); setView(view); } + + /** + * Converts the user icon to a circularly clipped one. This is used in the User Picker and + * Settings. + */ + static class CircleFramedDrawable extends Drawable { + + private final Bitmap mBitmap; + private final int mSize; + private final Paint mPaint; + + private float mScale; + private Rect mSrcRect; + private RectF mDstRect; + + public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) { + CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize); + return instance; + } + + public CircleFramedDrawable(Bitmap icon, int size) { + super(); + mSize = size; + + mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(mBitmap); + + final int width = icon.getWidth(); + final int height = icon.getHeight(); + final int square = Math.min(width, height); + + final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, + square, square); + final RectF circleRect = new RectF(0f, 0f, mSize, mSize); + + final Path fillPath = new Path(); + fillPath.addArc(circleRect, 0f, 360f); + + canvas.drawColor(0, PorterDuff.Mode.CLEAR); + + // opaque circle + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setColor(Color.BLACK); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawPath(fillPath, mPaint); + + // mask in the icon where the bitmap is opaque + mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + canvas.drawBitmap(icon, cropRect, circleRect, mPaint); + + // prepare paint for frame drawing + mPaint.setXfermode(null); + + mScale = 1f; + + mSrcRect = new Rect(0, 0, mSize, mSize); + mDstRect = new RectF(0, 0, mSize, mSize); + } + + @Override + public void draw(Canvas canvas) { + final float inside = mScale * mSize; + final float pad = (mSize - inside) / 2f; + + mDstRect.set(pad, pad, mSize - pad, mSize - pad); + canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setAlpha(int alpha) { + // Needed to implement abstract method. Do nothing. + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + // Needed to implement abstract method. Do nothing. + } + } } |