1 /* 2 * Copyright (C) 2018 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 static android.content.Intent.ACTION_MANAGED_PROFILE_ADDED; 19 import static android.content.Intent.ACTION_MANAGED_PROFILE_REMOVED; 20 21 import android.annotation.TargetApi; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.pm.ApplicationInfo; 27 import android.os.Build; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.Looper; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.util.SparseLongArray; 34 35 import androidx.annotation.NonNull; 36 37 import com.android.launcher3.icons.cache.BaseIconCache; 38 39 /** 40 * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class 41 * that are threadsafe. 42 */ 43 @TargetApi(Build.VERSION_CODES.P) 44 public class SimpleIconCache extends BaseIconCache { 45 46 private static SimpleIconCache sIconCache = null; 47 private static final Object CACHE_LOCK = new Object(); 48 49 private final SparseLongArray mUserSerialMap = new SparseLongArray(2); 50 private final UserManager mUserManager; 51 SimpleIconCache(Context context, String dbFileName, Looper bgLooper, int iconDpi, int iconPixelSize, boolean inMemoryCache)52 public SimpleIconCache(Context context, String dbFileName, Looper bgLooper, int iconDpi, 53 int iconPixelSize, boolean inMemoryCache) { 54 super(context, dbFileName, bgLooper, iconDpi, iconPixelSize, inMemoryCache); 55 mUserManager = context.getSystemService(UserManager.class); 56 57 // Listen for user cache changes. 58 IntentFilter filter = new IntentFilter(ACTION_MANAGED_PROFILE_ADDED); 59 filter.addAction(ACTION_MANAGED_PROFILE_REMOVED); 60 context.registerReceiver(new BroadcastReceiver() { 61 @Override 62 public void onReceive(Context context, Intent intent) { 63 resetUserCache(); 64 } 65 }, filter, null, new Handler(bgLooper), 0); 66 } 67 68 @Override getSerialNumberForUser(@onNull UserHandle user)69 public long getSerialNumberForUser(@NonNull UserHandle user) { 70 synchronized (mUserSerialMap) { 71 int index = mUserSerialMap.indexOfKey(user.getIdentifier()); 72 if (index >= 0) { 73 return mUserSerialMap.valueAt(index); 74 } 75 long serial = mUserManager.getSerialNumberForUser(user); 76 mUserSerialMap.put(user.getIdentifier(), serial); 77 return serial; 78 } 79 } 80 resetUserCache()81 private void resetUserCache() { 82 synchronized (mUserSerialMap) { 83 mUserSerialMap.clear(); 84 } 85 } 86 87 @Override isInstantApp(@onNull ApplicationInfo info)88 protected boolean isInstantApp(@NonNull ApplicationInfo info) { 89 return info.isInstantApp(); 90 } 91 92 @NonNull 93 @Override getIconFactory()94 public BaseIconFactory getIconFactory() { 95 return IconFactory.obtain(context); 96 } 97 getIconCache(Context context)98 public static SimpleIconCache getIconCache(Context context) { 99 synchronized (CACHE_LOCK) { 100 if (sIconCache != null) { 101 return sIconCache; 102 } 103 boolean inMemoryCache = 104 context.getResources().getBoolean(R.bool.simple_cache_enable_im_memory); 105 String dbFileName = context.getString(R.string.cache_db_name); 106 107 HandlerThread bgThread = new HandlerThread("simple-icon-cache"); 108 bgThread.start(); 109 110 sIconCache = new SimpleIconCache(context.getApplicationContext(), dbFileName, 111 bgThread.getLooper(), context.getResources().getConfiguration().densityDpi, 112 context.getResources().getDimensionPixelSize(R.dimen.default_icon_bitmap_size), 113 inMemoryCache); 114 return sIconCache; 115 } 116 } 117 } 118