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

Commit 9d32323c authored by Sunny Goyal's avatar Sunny Goyal
Browse files

First pass at using hardware bitmaps

Bug: 35428783
Change-Id: Ife67b85f6e7e268826597ed9bccd9659841f67de
parent 30d276cb
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.launcher3.uioverrides;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.View.AccessibilityDelegate;
import android.widget.PopupMenu;
import android.widget.Toast;
@@ -24,11 +26,16 @@ import android.widget.Toast;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.widget.WidgetsFullSheet;
import com.android.systemui.shared.recents.view.RecentsTransition;

public class UiFactory {

    public static final boolean USE_HARDWARE_BITMAP = FeatureFlags.IS_DOGFOOD_BUILD;

    public static TouchController[] createTouchControllers(Launcher launcher) {

        if (launcher.getDeviceProfile().isVerticalBarLayout()) {
@@ -77,4 +84,15 @@ public class UiFactory {
        }
        menu.show();
    }

    public static Bitmap createFromRenderer(int width, int height, boolean forceSoftwareRenderer,
            BitmapRenderer renderer) {
        if (USE_HARDWARE_BITMAP && !forceSoftwareRenderer) {
            return RecentsTransition.createHardwareBitmap(width, height, renderer::render);
        } else {
            Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            renderer.render(new Canvas(result));
            return result;
        }
    }
}
+13 −2
Original line number Diff line number Diff line
@@ -41,17 +41,20 @@ import android.os.UserHandle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
import com.android.launcher3.util.Thunk;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -102,6 +105,7 @@ public class IconCache {
    @Thunk final Handler mWorkerHandler;

    private final BitmapFactory.Options mLowResOptions;
    private final BitmapFactory.Options mHighResOptions;

    public IconCache(Context context, InvariantDeviceProfile inv) {
        mContext = context;
@@ -120,6 +124,13 @@ public class IconCache {
        // Always prefer RGB_565 config for low res. If the bitmap has transparency, it will
        // automatically be loaded as ALPHA_8888.
        mLowResOptions.inPreferredConfig = Bitmap.Config.RGB_565;

        if (UiFactory.USE_HARDWARE_BITMAP) {
            mHighResOptions = new BitmapFactory.Options();
            mHighResOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
        } else {
            mHighResOptions = null;
        }
    }

    private Drawable getFullResDefaultActivityIcon() {
@@ -625,7 +636,7 @@ public class IconCache {
                    Bitmap icon = LauncherIcons.createBadgedIconBitmap(
                            appInfo.loadIcon(mPackageManager), user, mContext, appInfo.targetSdkVersion);
                    if (mInstantAppResolver.isInstantApp(appInfo)) {
                        icon = LauncherIcons.badgeWithDrawable(icon,
                        LauncherIcons.badgeWithDrawable(icon,
                                mContext.getDrawable(R.drawable.ic_instant_app_badge), mContext);
                    }
                    Bitmap lowResIcon =  generateLowResIcon(icon);
@@ -665,7 +676,7 @@ public class IconCache {
                new String[]{cacheKey.componentName.flattenToString(),
                        Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
            if (c.moveToNext()) {
                entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : null);
                entry.icon = loadIconNoResize(c, 0, lowRes ? mLowResOptions : mHighResOptions);
                entry.isLowResIcon = lowRes;
                entry.title = c.getString(1);
                if (entry.title == null) {
+21 −25
Original line number Diff line number Diff line
@@ -36,10 +36,9 @@ import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.Preconditions;

import java.util.concurrent.Callable;

/**
 * {@link AdaptiveIconDrawable} representation of a {@link FolderIcon}
 */
@@ -66,7 +65,7 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
    }

    public static FolderAdaptiveIcon createFolderAdaptiveIcon(
            final Launcher launcher, final long folderId, Point dragViewSize) {
            Launcher launcher, long folderId, Point dragViewSize) {
        Preconditions.assertNonUiThread();
        int margin = launcher.getResources()
                .getDimensionPixelSize(R.dimen.blur_size_medium_outline);
@@ -75,21 +74,12 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
        final Bitmap badge = Bitmap.createBitmap(
                dragViewSize.x - margin, dragViewSize.y - margin, Bitmap.Config.ARGB_8888);

        // The bitmap for the preview is generated larger than needed to allow for the spring effect
        float sizeScaleFactor = 1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction();
        final Bitmap preview = Bitmap.createBitmap(
                (int) (dragViewSize.x * sizeScaleFactor), (int) (dragViewSize.y * sizeScaleFactor),
                Bitmap.Config.ARGB_8888);

        // Create the actual drawable on the UI thread to avoid race conditions with
        // FolderIcon draw pass
        try {
            return new MainThreadExecutor().submit(new Callable<FolderAdaptiveIcon>() {
                @Override
                public FolderAdaptiveIcon call() throws Exception {
            return new MainThreadExecutor().submit(() -> {
                FolderIcon icon = launcher.findFolderIcon(folderId);
                    return icon == null ? null : createDrawableOnUiThread(icon, badge, preview);
                }
                return icon == null ? null : createDrawableOnUiThread(icon, badge, dragViewSize);
            }).get();
        } catch (Exception e) {
            Log.e(TAG, "Unable to create folder icon", e);
@@ -101,7 +91,7 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
     * Initializes various bitmaps on the UI thread and returns the final drawable.
     */
    private static FolderAdaptiveIcon createDrawableOnUiThread(FolderIcon icon,
            Bitmap badgeBitmap, Bitmap previewBitmap) {
            Bitmap badgeBitmap, Point dragViewSize) {
        Preconditions.assertUIThread();
        float margin = icon.getResources().getDimension(R.dimen.blur_size_medium_outline) / 2;

@@ -115,15 +105,21 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
        icon.drawBadge(c);

        // Initialize preview
        float shiftFactor = AdaptiveIconDrawable.getExtraInsetFraction() /
                (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
        float previewShiftX = shiftFactor * previewBitmap.getWidth();
        float previewShiftY = shiftFactor * previewBitmap.getHeight();

        c.setBitmap(previewBitmap);
        c.translate(previewShiftX, previewShiftY);
        icon.getPreviewItemManager().draw(c);
        c.setBitmap(null);
        final float sizeScaleFactor = 1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction();
        final int previewWidth = (int) (dragViewSize.x * sizeScaleFactor);
        final int previewHeight = (int) (dragViewSize.y * sizeScaleFactor);

        final float shiftFactor = AdaptiveIconDrawable.getExtraInsetFraction() / sizeScaleFactor;
        final float previewShiftX = shiftFactor * previewWidth;
        final float previewShiftY = shiftFactor * previewHeight;

        Bitmap previewBitmap = UiFactory.createFromRenderer(previewWidth, previewHeight, false,
                (canvas) -> {
                    int count = canvas.save();
                    canvas.translate(previewShiftX, previewShiftY);
                    icon.getPreviewItemManager().draw(canvas);
                    canvas.restoreToCount(count);
                });

        // Initialize mask
        Path mask = new Path();
+23 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.graphics;

import android.graphics.Canvas;

public interface BitmapRenderer {

     void render(Canvas out);
}
+11 −13
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.UiThreadHelper;

import java.nio.ByteBuffer;
@@ -77,8 +78,10 @@ public class DragPreviewProvider {
    /**
     * Draws the {@link #mView} into the given {@param destCanvas}.
     */
    private void drawDragView(Canvas destCanvas) {
    private void drawDragView(Canvas destCanvas, float scale) {
        destCanvas.save();
        destCanvas.scale(scale, scale);

        if (mView instanceof BubbleTextView) {
            Drawable d = ((BubbleTextView) mView).getIcon();
            Rect bounds = getDrawableBounds(d);
@@ -120,6 +123,7 @@ public class DragPreviewProvider {
        int width = mView.getWidth();
        int height = mView.getHeight();

        boolean forceSoftwareRenderer = false;
        if (mView instanceof BubbleTextView) {
            Drawable d = ((BubbleTextView) mView).getIcon();
            Rect bounds = getDrawableBounds(d);
@@ -129,20 +133,14 @@ public class DragPreviewProvider {
            scale = ((LauncherAppWidgetHostView) mView).getScaleToFit();
            width = (int) (mView.getWidth() * scale);
            height = (int) (mView.getHeight() * scale);
        }

        Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline,
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(b);

        canvas.save();
        canvas.scale(scale, scale);
        drawDragView(canvas);
        canvas.restore();

        canvas.setBitmap(null);
            // Use software renderer for widgets as we know that they already work
            forceSoftwareRenderer = true;
        }

        return b;
        final float scaleFinal = scale;
        return UiFactory.createFromRenderer(width + blurSizeOutline, height + blurSizeOutline,
                forceSoftwareRenderer, (c) -> drawDragView(c, scaleFinal));
    }

    public final void generateDragOutline(Bitmap preview) {
Loading