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

Commit de35e9db authored by Willie Koomson's avatar Willie Koomson
Browse files

Write ColorStateList to proto

This change adds writeToProto/createFromProto APIs for ColorStateList,
to facilitate serialiazing RemoteView actions that contain
ColorStateLists.

Test: ColorStateListTest
Bug: 308041327
Flag: android.appwidget.flags.remote_views_proto
Change-Id: I4a0bd0e9e518306bf679f3f3ddfd980cb910fe0b
parent 0c95232c
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ import android.util.MathUtils;
import android.util.SparseArray;
import android.util.StateSet;
import android.util.Xml;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;

import com.android.internal.R;
import com.android.internal.graphics.ColorUtils;
@@ -44,7 +47,9 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
@@ -793,4 +798,61 @@ public class ColorStateList extends ComplexColor implements Parcelable {
            return new ColorStateList(stateSpecs, colors);
        }
    };

    /** @hide */
    public void writeToProto(ProtoOutputStream out) {
        for (int[] states : mStateSpecs) {
            long specToken = out.start(ColorStateListProto.STATE_SPECS);
            for (int state : states) {
                out.write(ColorStateListProto.StateSpec.STATE, state);
            }
            out.end(specToken);
        }
        for (int color : mColors) {
            out.write(ColorStateListProto.COLORS, color);
        }
    }

    /** @hide */
    public static ColorStateList createFromProto(ProtoInputStream in)
            throws Exception {
        List<int[]> stateSpecs = new ArrayList<>();
        List<Integer> colors = new ArrayList<>();


        while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (in.getFieldNumber()) {
                case (int) ColorStateListProto.COLORS:
                    colors.add(in.readInt(ColorStateListProto.COLORS));
                    break;
                case (int) ColorStateListProto.STATE_SPECS:
                    final long stateToken = in.start(ColorStateListProto.STATE_SPECS);
                    List<Integer> states = new ArrayList<>();
                    while (in.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
                        switch (in.getFieldNumber()) {
                            case (int) ColorStateListProto.StateSpec.STATE:
                                states.add(in.readInt(ColorStateListProto.StateSpec.STATE));
                                break;
                            default:
                                Log.w(TAG, "Unhandled field while reading Icon proto!\n"
                                        + ProtoUtils.currentFieldToString(in));
                        }
                    }
                    int[] statesArray = new int[states.size()];
                    Arrays.setAll(statesArray, states::get);
                    stateSpecs.add(statesArray);
                    in.end(stateToken);
                    break;
                default:
                    Log.w(TAG, "Unhandled field while reading Icon proto!\n"
                            + ProtoUtils.currentFieldToString(in));
            }
        }

        int[][] stateSpecsArray = new int[stateSpecs.size()][];
        Arrays.setAll(stateSpecsArray, stateSpecs::get);
        int[] colorsArray = new int[colors.size()];
        Arrays.setAll(colorsArray, colors::get);
        return new ColorStateList(stateSpecsArray, colorsArray);
    }
}
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 optional 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.
 */

syntax = "proto2";

option java_multiple_files = true;

package android.content.res;

import "frameworks/base/core/proto/android/privacy.proto";

/**
 * An android.content.res.ColorStateList object.
 */
message ColorStateListProto {
    option (android.msg_privacy).dest = DEST_AUTOMATIC;
    repeated StateSpec state_specs = 1;
    repeated int32 colors = 2 [packed = true];

    message StateSpec {
        repeated int32 state = 1 [packed = true];
    }
}
+27 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.graphics;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;

import androidx.test.filters.SmallTest;

@@ -48,6 +50,15 @@ public class ColorStateListTest extends AndroidTestCase {
        assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
    }

    @SmallTest
    public void testStateIsInList_proto() throws Exception {
        ColorStateList colorStateList = recreateFromProto(
                mResources.getColorStateList(R.color.color1));
        int[] focusedState = {android.R.attr.state_focused};
        int focusColor = colorStateList.getColorForState(focusedState, R.color.failColor);
        assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
    }

    @SmallTest
    public void testEmptyState() throws Exception {
        ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
@@ -56,6 +67,15 @@ public class ColorStateListTest extends AndroidTestCase {
        assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
    }

    @SmallTest
    public void testEmptyState_proto() throws Exception {
        ColorStateList colorStateList = recreateFromProto(
                mResources.getColorStateList(R.color.color1));
        int[] emptyState = {};
        int defaultColor = colorStateList.getColorForState(emptyState, mFailureColor);
        assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
    }

    @SmallTest
    public void testGetColor() throws Exception {
        int defaultColor = mResources.getColor(R.color.color1);
@@ -73,4 +93,11 @@ public class ColorStateListTest extends AndroidTestCase {
        int defaultColor = mResources.getColor(R.color.color_with_lstar);
        assertEquals(mResources.getColor(R.color.testcolor3), defaultColor);
    }

    private ColorStateList recreateFromProto(ColorStateList colorStateList) throws Exception {
        ProtoOutputStream out = new ProtoOutputStream();
        colorStateList.writeToProto(out);
        ProtoInputStream in = new ProtoInputStream(out.getBytes());
        return ColorStateList.createFromProto(in);
    }
}