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

Commit 4219de7d authored by Pierre Barbier de Reuille's avatar Pierre Barbier de Reuille
Browse files

Framework implementation of go/widgets-dynamic-colors

Bug: 179783721
Test: atest CtsWidgetTestCases:android.widget.cts.RemoteViewsThemeColorsTest
Change-Id: I622e79ed8738dc862790191bf9fcf44b0af35c8e
parent 5f630223
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -8371,7 +8371,9 @@ package android.appwidget {
    method protected android.view.View getDefaultView();
    method protected android.view.View getDefaultView();
    method protected android.view.View getErrorView();
    method protected android.view.View getErrorView();
    method protected void prepareView(android.view.View);
    method protected void prepareView(android.view.View);
    method public void resetColorResources();
    method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
    method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
    method public void setColorResources(@NonNull android.util.SparseIntArray);
    method public void setCurrentSize(@NonNull android.graphics.PointF);
    method public void setCurrentSize(@NonNull android.graphics.PointF);
    method public void setExecutor(java.util.concurrent.Executor);
    method public void setExecutor(java.util.concurrent.Executor);
    method public void setOnLightBackground(boolean);
    method public void setOnLightBackground(boolean);
+61 −8
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.util.Pair;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View;
@@ -92,7 +93,10 @@ public class AppWidgetHostView extends FrameLayout {
    int mLayoutId = -1;
    int mLayoutId = -1;
    private InteractionHandler mInteractionHandler;
    private InteractionHandler mInteractionHandler;
    private boolean mOnLightBackground;
    private boolean mOnLightBackground;
    PointF mCurrentSize = null;
    private PointF mCurrentSize = null;
    private RemoteViews.ColorResources mColorResources = null;
    // Stores the last remote views last inflated.
    private RemoteViews mLastInflatedRemoteViews = null;


    private Executor mAsyncExecutor;
    private Executor mAsyncExecutor;
    private CancellationSignal mLastExecutionSignal;
    private CancellationSignal mLastExecutionSignal;
@@ -358,7 +362,7 @@ public class AppWidgetHostView extends FrameLayout {
        PointF newSize = new PointF(size.x - xPaddingDips, size.y - yPaddingDips);
        PointF newSize = new PointF(size.x - xPaddingDips, size.y - yPaddingDips);
        if (!newSize.equals(mCurrentSize)) {
        if (!newSize.equals(mCurrentSize)) {
            mCurrentSize = newSize;
            mCurrentSize = newSize;
            mLayoutId = -1; // Prevents recycling the view.
            reapplyLastRemoteViews();
        }
        }
    }
    }


@@ -368,7 +372,7 @@ public class AppWidgetHostView extends FrameLayout {
    public void clearCurrentSize() {
    public void clearCurrentSize() {
        if (mCurrentSize != null) {
        if (mCurrentSize != null) {
            mCurrentSize = null;
            mCurrentSize = null;
            mLayoutId = -1;
            reapplyLastRemoteViews();
        }
        }
    }
    }


@@ -477,9 +481,17 @@ public class AppWidgetHostView extends FrameLayout {
     * AppWidget provider. Will animate into these new views as needed
     * AppWidget provider. Will animate into these new views as needed
     */
     */
    public void updateAppWidget(RemoteViews remoteViews) {
    public void updateAppWidget(RemoteViews remoteViews) {
        this.mLastInflatedRemoteViews = remoteViews;
        applyRemoteViews(remoteViews, true);
        applyRemoteViews(remoteViews, true);
    }
    }


    /**
     * Reapply the last inflated remote views, or the default view is none was inflated.
     */
    private void reapplyLastRemoteViews() {
        applyRemoteViews(mLastInflatedRemoteViews, true);
    }

    /**
    /**
     * @hide
     * @hide
     */
     */
@@ -518,7 +530,8 @@ public class AppWidgetHostView extends FrameLayout {
            // layout matches, try recycling it
            // layout matches, try recycling it
            if (content == null && layoutId == mLayoutId) {
            if (content == null && layoutId == mLayoutId) {
                try {
                try {
                    remoteViews.reapply(mContext, mView, mInteractionHandler);
                    remoteViews.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
                            mColorResources);
                    content = mView;
                    content = mView;
                    recycled = true;
                    recycled = true;
                    if (LOGD) Log.d(TAG, "was able to recycle existing layout");
                    if (LOGD) Log.d(TAG, "was able to recycle existing layout");
@@ -530,7 +543,8 @@ public class AppWidgetHostView extends FrameLayout {
            // Try normal RemoteView inflation
            // Try normal RemoteView inflation
            if (content == null) {
            if (content == null) {
                try {
                try {
                    content = remoteViews.apply(mContext, this, mInteractionHandler, mCurrentSize);
                    content = remoteViews.apply(mContext, this, mInteractionHandler,
                            mCurrentSize, mColorResources);
                    if (LOGD) Log.d(TAG, "had to inflate new layout");
                    if (LOGD) Log.d(TAG, "had to inflate new layout");
                } catch (RuntimeException e) {
                } catch (RuntimeException e) {
                    exception = e;
                    exception = e;
@@ -583,7 +597,8 @@ public class AppWidgetHostView extends FrameLayout {
                        mAsyncExecutor,
                        mAsyncExecutor,
                        new ViewApplyListener(remoteViews, layoutId, true),
                        new ViewApplyListener(remoteViews, layoutId, true),
                        mInteractionHandler,
                        mInteractionHandler,
                        mCurrentSize);
                        mCurrentSize,
                        mColorResources);
            } catch (Exception e) {
            } catch (Exception e) {
                // Reapply failed. Try apply
                // Reapply failed. Try apply
            }
            }
@@ -594,7 +609,8 @@ public class AppWidgetHostView extends FrameLayout {
                    mAsyncExecutor,
                    mAsyncExecutor,
                    new ViewApplyListener(remoteViews, layoutId, false),
                    new ViewApplyListener(remoteViews, layoutId, false),
                    mInteractionHandler,
                    mInteractionHandler,
                    mCurrentSize);
                    mCurrentSize,
                    mColorResources);
        }
        }
    }
    }


@@ -662,9 +678,13 @@ public class AppWidgetHostView extends FrameLayout {
    protected Context getRemoteContext() {
    protected Context getRemoteContext() {
        try {
        try {
            // Return if cloned successfully, otherwise default
            // Return if cloned successfully, otherwise default
            return mContext.createApplicationContext(
            Context newContext = mContext.createApplicationContext(
                    mInfo.providerInfo.applicationInfo,
                    mInfo.providerInfo.applicationInfo,
                    Context.CONTEXT_RESTRICTED);
                    Context.CONTEXT_RESTRICTED);
            if (mColorResources != null) {
                mColorResources.apply(newContext);
            }
            return newContext;
        } catch (NameNotFoundException e) {
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Package name " +  mInfo.providerInfo.packageName + " not found");
            Log.e(TAG, "Package name " +  mInfo.providerInfo.packageName + " not found");
            return mContext;
            return mContext;
@@ -819,4 +839,37 @@ public class AppWidgetHostView extends FrameLayout {
            }
            }
        };
        };
    }
    }

    /**
     * Set the dynamically overloaded color resources.
     *
     * {@code colorMapping} maps a predefined set of color resources to their ARGB
     * representation. Any entry not in the predefined set of colors will be ignored.
     *
     * Calling this method will trigger a full re-inflation of the App Widget.
     *
     * The color resources that can be overloaded are the ones whose name is prefixed with
     * {@code system_primary_}, {@code system_secondary_} or {@code system_neutral_}, for example
     * {@link android.R.color#system_primary_500}.
     */
    public void setColorResources(@NonNull SparseIntArray colorMapping) {
        mColorResources = RemoteViews.ColorResources.create(mContext, colorMapping);
        mLayoutId = -1;
        reapplyLastRemoteViews();
    }

    /**
     * Reset the dynamically overloaded resources, reverting to the default values for
     * all the colors.
     *
     * If colors were defined before, calling this method will trigger a full re-inflation of the
     * App Widget.
     */
    public void resetColorResources() {
        if (mColorResources != null) {
            mColorResources = null;
            mLayoutId = -1;
            reapplyLastRemoteViews();
        }
    }
}
}
+262 −85

File changed.

Preview size limit exceeded, changes collapsed.

+6 −3
Original line number Original line Diff line number Diff line
@@ -31,12 +31,14 @@ public class RemoteViewsListAdapter extends BaseAdapter {
    private ArrayList<RemoteViews> mRemoteViewsList;
    private ArrayList<RemoteViews> mRemoteViewsList;
    private ArrayList<Integer> mViewTypes = new ArrayList<Integer>();
    private ArrayList<Integer> mViewTypes = new ArrayList<Integer>();
    private int mViewTypeCount;
    private int mViewTypeCount;
    private RemoteViews.ColorResources mColorResources;


    public RemoteViewsListAdapter(Context context, ArrayList<RemoteViews> remoteViews,
    public RemoteViewsListAdapter(Context context, ArrayList<RemoteViews> remoteViews,
            int viewTypeCount) {
            int viewTypeCount, RemoteViews.ColorResources colorResources) {
        mContext = context;
        mContext = context;
        mRemoteViewsList = remoteViews;
        mRemoteViewsList = remoteViews;
        mViewTypeCount = viewTypeCount;
        mViewTypeCount = viewTypeCount;
        mColorResources = colorResources;
        init();
        init();
    }
    }


@@ -90,9 +92,10 @@ public class RemoteViewsListAdapter extends BaseAdapter {
            if (convertView != null && rv != null &&
            if (convertView != null && rv != null &&
                    convertView.getId() == rv.getLayoutId()) {
                    convertView.getId() == rv.getLayoutId()) {
                v = convertView;
                v = convertView;
                rv.reapply(mContext, v);
                rv.reapply(mContext, v, null /* handler */, null /* size */, mColorResources);
            } else {
            } else {
                v = rv.apply(mContext, parent);
                v = rv.apply(mContext, parent, null /* handler */, null /* size */,
                        mColorResources);
            }
            }
            return v;
            return v;
        } else {
        } else {
+67 −0
Original line number Original line Diff line number Diff line
@@ -44,11 +44,73 @@ license {
    ],
    ],
}
}


genrule {
    name: "remote-color-resources-compile-public",
    tools: ["aapt2"],
    srcs: [
        "remote_color_resources_res/values/public.xml",
    ],
    out: ["values_public.arsc.flat"],
    cmd: "$(location aapt2) compile $(in) -o $(genDir)",
}

genrule {
    name: "remote-color-resources-compile-colors",
    tools: ["aapt2"],
    srcs: [
        "remote_color_resources_res/values/colors.xml",
    ],
    out: ["values_colors.arsc.flat"],
    cmd: "$(location aapt2) compile $(in) -o $(genDir)",
}

genrule {
    name: "remote-color-resources-apk",
    tools: ["aapt2"],
    // The first input file in the list must be the manifest
    srcs: [
        "RemoteThemeColorsAndroidManifest.xml",
        ":remote-color-resources-compile-public",
        ":remote-color-resources-compile-colors",
    ],
    out: ["remote-color-resources.apk"],
    cmd: "$(location aapt2) link -o $(out) --manifest $(in)"
}

genrule {
    name: "remote-color-resources-arsc",
    srcs: [":remote-color-resources-apk"],
    out: ["res/raw/remote_views_color_resources.arsc"],
    cmd: "mkdir -p $(genDir)/remote-color-resources-arsc && "
        + "unzip -x $(in) resources.arsc -d $(genDir)/remote-color-resources-arsc && "
        + "mkdir -p $$(dirname $(out)) && "
        + "mv $(genDir)/remote-color-resources-arsc/resources.arsc $(out) && "
        + "echo 'Created $(out)'"
}

genrule {
    name: "remote-color-resources-arsc-zip",
    tools: ["soong_zip"],
    srcs: [
        ":remote-color-resources-arsc",
        "remote_color_resources_res/symbols.xml",
    ],
    out: ["remote_views_color_resources.zip"],
    cmd: "INPUTS=($(in)) && "
        + "RES_DIR=$$(dirname $$(dirname $${INPUTS[0]})) && "
        + "mkdir -p $$RES_DIR/values && "
        + "cp $${INPUTS[1]} $$RES_DIR/values && "
        + "$(location soong_zip) -o $(out) -C $$RES_DIR -D $$RES_DIR && "
        + "cp $(out) ."
}

android_app {
android_app {
    name: "framework-res",
    name: "framework-res",
    sdk_version: "core_platform",
    sdk_version: "core_platform",
    certificate: "platform",
    certificate: "platform",


    srcs: [":remote-color-resources-arsc"],

    // Disable dexpreopt and verify_uses_libraries check as the app
    // Disable dexpreopt and verify_uses_libraries check as the app
    // contains no Java code to be dexpreopted.
    // contains no Java code to be dexpreopted.
    enforce_uses_libs: false,
    enforce_uses_libs: false,
@@ -72,6 +134,10 @@ android_app {
        "--auto-add-overlay",
        "--auto-add-overlay",
    ],
    ],


    resource_zips: [
        ":remote-color-resources-arsc-zip",
    ],

    // Create package-export.apk, which other packages can use to get
    // Create package-export.apk, which other packages can use to get
    // PRODUCT-agnostic resource data like IDs and type definitions.
    // PRODUCT-agnostic resource data like IDs and type definitions.
    export_package_resources: true,
    export_package_resources: true,
@@ -96,6 +162,7 @@ filegroup {
    srcs: [
    srcs: [
        "assets/**/*",
        "assets/**/*",
        "res/**/*",
        "res/**/*",
        ":remote-color-resources-arsc",
    ],
    ],
}
}


Loading