Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3de17107 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Adding helper methods to caching DB" into main

parents a1d45250 b596d5eb
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.launcher3.icons
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.CompressFormat.PNG
import android.graphics.BitmapFactory
import android.graphics.BitmapFactory.Options
import android.graphics.BlendMode
import android.graphics.BlendModeColorFilter
import android.graphics.Canvas
@@ -35,7 +37,6 @@ import android.graphics.RegionIterator
import android.util.Log
import androidx.annotation.ColorInt
import androidx.core.graphics.ColorUtils.compositeColors
import com.android.launcher3.icons.GraphicsUtils.resize
import com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR
import com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR
import java.io.ByteArrayOutputStream
@@ -73,6 +74,20 @@ object GraphicsUtils {
        }
    }

    /** Tries to decode the [ByteArray] into a [Bitmap] consuming any parsing errors */
    fun ByteArray.parseBitmapSafe(config: Bitmap.Config): Bitmap? =
        try {
            BitmapFactory.decodeByteArray(
                /* data= */ this,
                /* offset= */ 0,
                /* length= */ size,
                Options().apply { inPreferredConfig = config },
            )
        } catch (e: Exception) {
            Log.e(TAG, "Error parsing persisted bitmap", e)
            null
        }

    /**
     * Try go guesstimate how much space the icon will take when serialized to avoid unnecessary
     * allocations/copies during the write (4 bytes per pixel).
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ interface IconThemeController {
    ): ThemedBitmap

    fun decode(
        data: ByteArray,
        bytes: ByteArray,
        info: BitmapInfo,
        factory: BaseIconFactory,
        sourceHint: SourceHint,
+26 −39
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@ import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteException
import android.database.sqlite.SQLiteReadOnlyDatabaseException
import android.graphics.Bitmap
import android.graphics.Bitmap.Config.HARDWARE
@@ -93,7 +91,7 @@ constructor(

    @JvmField val workerHandler = Handler(bgLooper)

    @JvmField protected var iconDb = IconDB(context, dbFileName, iconPixelSize)
    @JvmField protected var iconDb = createIconDb(iconPixelSize)

    private var defaultIcon: BitmapInfo? = null
    private val userFlagOpMap = SparseArray<FlagOp>()
@@ -133,7 +131,7 @@ constructor(
            userFlagOpMap.clear()
            iconDb.clear()
            iconDb.close()
            iconDb = IconDB(context, dbFileName, iconPixelSize)
            iconDb = createIconDb(iconPixelSize)
            cache.clear()
        } catch (e: SQLiteReadOnlyDatabaseException) {
            // This is known to happen during repeated backup and restores, if the Launcher is in
@@ -486,28 +484,22 @@ constructor(
        lookupFlags: CacheLookupFlag,
        cachingLogic: CachingLogic<*>,
    ): Boolean {
        var c: Cursor? = null
        Trace.beginSection("loadIconIndividually")
        try {
            c =
                iconDb.query(
            return iconDb.querySingleEntry(
                lookupFlags.toLookupColumns(),
                "$COLUMN_COMPONENT = ? AND $COLUMN_USER = ?",
                arrayOf(
                    cacheKey.componentName.flattenToString(),
                    getSerialNumberForUser(cacheKey.user).toString(),
                ),
                )
            if (c.moveToNext()) {
                return updateTitleAndIconLocked(cacheKey, entry, c, lookupFlags, cachingLogic)
                false,
            ) {
                updateTitleAndIconLocked(cacheKey, entry, it, lookupFlags, cachingLogic)
            }
        } catch (e: SQLiteException) {
            Log.d(TAG, "Error reading icon cache", e)
        } finally {
            c?.close()
            Trace.endSection()
        }
        return false
    }

    private fun updateTitleAndIconLocked(
@@ -561,7 +553,7 @@ constructor(
                    if (themeController != null && monoIconData != null) {
                        entry.bitmap.themedBitmap =
                            themeController.decode(
                                data = monoIconData,
                                bytes = monoIconData,
                                info = entry.bitmap,
                                factory = factory,
                                sourceHint =
@@ -614,18 +606,15 @@ constructor(
        Log.d(TAG, message, e)
    }

    /** Cache class to store the actual entries on disk */
    class IconDB(context: Context, dbFileName: String?, iconPixelSize: Int) :
    /** Creates a cache class to store the actual entries on disk */
    private fun createIconDb(iconPixelSize: Int) =
        SQLiteCacheHelper(
            context,
            dbFileName,
            (RELEASE_VERSION shl 16) + iconPixelSize,
            TABLE_NAME,
        ) {

        override fun onCreateTable(db: SQLiteDatabase) {
            db.execSQL(
                ("CREATE TABLE IF NOT EXISTS $TABLE_NAME (" +
            "CREATE TABLE IF NOT EXISTS $TABLE_NAME (" +
                "$COLUMN_COMPONENT TEXT NOT NULL, " +
                "$COLUMN_USER INTEGER NOT NULL, " +
                "$COLUMN_FRESHNESS_ID TEXT, " +
@@ -635,9 +624,7 @@ constructor(
                "$COLUMN_FLAGS INTEGER NOT NULL DEFAULT 0, " +
                "$COLUMN_LABEL TEXT, " +
                "PRIMARY KEY ($COLUMN_COMPONENT, $COLUMN_USER) " +
                    ");")
            )
        }
                ");"
        }

    companion object {
+3 −3
Original line number Diff line number Diff line
@@ -111,16 +111,16 @@ class MonoIconThemeController(
    }

    override fun decode(
        data: ByteArray,
        bytes: ByteArray,
        info: BitmapInfo,
        factory: BaseIconFactory,
        sourceHint: SourceHint,
    ): ThemedBitmap {
        val icon = info.icon
        if (data.size != icon.height * icon.width) return ThemedBitmap.NOT_SUPPORTED
        if (bytes.size != icon.height * icon.width) return ThemedBitmap.NOT_SUPPORTED

        var monoBitmap = Bitmap.createBitmap(icon.width, icon.height, ALPHA_8)
        monoBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(data))
        monoBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(bytes))

        val hwMonoBitmap = monoBitmap.copy(HARDWARE, false /*isMutable*/)
        if (hwMonoBitmap != null) {
+0 −58
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.launcher3.util;

import static android.database.sqlite.SQLiteDatabase.NO_LOCALIZED_COLLATORS;

import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDatabase.OpenParams;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;

/**
 * Extension of {@link SQLiteOpenHelper} which avoids creating default locale table by
 * A context wrapper which creates databases without support for localized collators.
 */
public abstract class NoLocaleSQLiteHelper extends SQLiteOpenHelper {

    private static final boolean ATLEAST_P =
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;

    public NoLocaleSQLiteHelper(Context context, String name, int version) {
        super(ATLEAST_P ? context : new NoLocalContext(context), name, null, version);
        if (ATLEAST_P) {
            setOpenParams(new OpenParams.Builder().addOpenFlags(NO_LOCALIZED_COLLATORS).build());
        }
    }

    private static class NoLocalContext extends ContextWrapper {
        public NoLocalContext(Context base) {
            super(base);
        }

        @Override
        public SQLiteDatabase openOrCreateDatabase(
                String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler) {
            return super.openOrCreateDatabase(
                    name, mode | Context.MODE_NO_LOCALIZED_COLLATORS, factory, errorHandler);
        }
    }
}
Loading