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 package com.android.launcher3.icons 17 18 import android.content.Context 19 import android.graphics.Canvas 20 import android.graphics.Color 21 import android.graphics.Path 22 import android.graphics.Rect 23 import android.graphics.drawable.AdaptiveIconDrawable 24 import android.os.UserHandle 25 import com.android.launcher3.Flags 26 import com.android.launcher3.InvariantDeviceProfile 27 import com.android.launcher3.dagger.ApplicationContext 28 import com.android.launcher3.dagger.LauncherAppSingleton 29 import com.android.launcher3.dagger.LauncherComponentProvider.appComponent 30 import com.android.launcher3.graphics.ThemeManager 31 import com.android.launcher3.pm.UserCache 32 import com.android.launcher3.util.UserIconInfo 33 import dagger.assisted.Assisted 34 import dagger.assisted.AssistedFactory 35 import dagger.assisted.AssistedInject 36 import java.util.concurrent.ConcurrentLinkedQueue 37 import javax.inject.Inject 38 39 /** 40 * Wrapper class to provide access to [BaseIconFactory] and also to provide pool of this class that 41 * are threadsafe. 42 */ 43 class LauncherIcons 44 @AssistedInject 45 internal constructor( 46 @ApplicationContext context: Context, 47 idp: InvariantDeviceProfile, 48 private var themeManager: ThemeManager, 49 private var userCache: UserCache, 50 @Assisted private val pool: ConcurrentLinkedQueue<LauncherIcons>, 51 ) : BaseIconFactory(context, idp.fillResIconDpi, idp.iconBitmapSize), AutoCloseable { 52 53 private val iconScale = themeManager.iconState.iconScale 54 55 init { 56 mThemeController = themeManager.themeController 57 } 58 59 /** Recycles a LauncherIcons that may be in-use. */ recyclenull60 fun recycle() { 61 clear() 62 pool.add(this) 63 } 64 getUserInfonull65 override fun getUserInfo(user: UserHandle): UserIconInfo { 66 return userCache.getUserInfo(user) 67 } 68 getShapePathnull69 override fun getShapePath(drawable: AdaptiveIconDrawable, iconBounds: Rect): Path { 70 if (!Flags.enableLauncherIconShapes()) return super.getShapePath(drawable, iconBounds) 71 return themeManager.iconShape.getPath(iconBounds) 72 } 73 getIconScalenull74 override fun getIconScale(): Float { 75 if (!Flags.enableLauncherIconShapes()) return super.getIconScale() 76 return themeManager.iconState.iconScale 77 } 78 drawAdaptiveIconnull79 override fun drawAdaptiveIcon( 80 canvas: Canvas, 81 drawable: AdaptiveIconDrawable, 82 overridePath: Path, 83 ) { 84 if (!Flags.enableLauncherIconShapes()) { 85 super.drawAdaptiveIcon(canvas, drawable, overridePath) 86 return 87 } 88 canvas.clipPath(overridePath) 89 canvas.drawColor(Color.BLACK) 90 canvas.save() 91 canvas.scale(iconScale, iconScale, canvas.width / 2f, canvas.height / 2f) 92 if (drawable.background != null) { 93 drawable.background.draw(canvas) 94 } 95 if (drawable.foreground != null) { 96 drawable.foreground.draw(canvas) 97 } 98 canvas.restore() 99 } 100 closenull101 override fun close() { 102 recycle() 103 } 104 105 @AssistedFactory 106 internal interface LauncherIconsFactory { createnull107 fun create(pool: ConcurrentLinkedQueue<LauncherIcons>): LauncherIcons 108 } 109 110 @LauncherAppSingleton 111 class IconPool @Inject internal constructor(private val factory: LauncherIconsFactory) { 112 private var pool = ConcurrentLinkedQueue<LauncherIcons>() 113 114 fun obtain(): LauncherIcons = pool.let { it.poll() ?: factory.create(it) } 115 116 fun clear() { 117 pool = ConcurrentLinkedQueue() 118 } 119 } 120 121 companion object { 122 123 /** 124 * Return a new LauncherIcons instance from the global pool. Allows us to avoid allocating 125 * new objects in many cases. 126 */ 127 @JvmStatic obtainnull128 fun obtain(context: Context): LauncherIcons = context.appComponent.iconPool.obtain() 129 130 @JvmStatic fun clearPool(context: Context) = context.appComponent.iconPool.clear() 131 } 132 } 133