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

Commit b8def990 authored by Ze Li's avatar Ze Li Committed by Android (Google) Code Review
Browse files

Merge "[Bluetooth Diagnosis] Add a banner preference type in device details page" into main

parents a004cb0c 7364ae99
Loading
Loading
Loading
Loading
+238 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.bluetooth.devicesettings;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/** A data class representing a banner preference. */
public class BannerPreference extends DeviceSettingPreference implements Parcelable {
    private final String mTitle;
    private final String mMessage;
    private final DeviceSettingIcon mIcon;
    private final ImmutableList<ButtonInfo> mButtonInfos;
    private final Bundle mExtras;

    BannerPreference(
            @NonNull String title,
            @NonNull String message,
            @Nullable DeviceSettingIcon icon,
            @Nullable List<ButtonInfo> buttonInfos,
            Bundle extras) {
        super(DeviceSettingType.DEVICE_SETTING_TYPE_BANNER);
        validate(title, message);
        mTitle = title;
        mMessage = message;
        mIcon = Objects.requireNonNullElseGet(icon, () -> DeviceSettingIcon.NO_ICON);
        if (buttonInfos == null) {
            mButtonInfos = ImmutableList.of();
        } else {
            mButtonInfos = ImmutableList.copyOf(buttonInfos);
        }
        mExtras = extras;
    }

    private static void validate(String title, String message) {
        if (Objects.isNull(title)) {
            throw new IllegalArgumentException("Title must be set");
        }
        if (Objects.isNull(message)) {
            throw new IllegalArgumentException("Message must be set");
        }
    }

    /** Read a {@link BannerPreference} from {@link Parcel}. */
    @NonNull
    public static BannerPreference readFromParcel(@NonNull Parcel in) {
        String title = in.readString();
        String message = in.readString();
        DeviceSettingIcon icon = DeviceSettingIcon.readFromParcel(in);
        List<ButtonInfo> buttonInfos = new ArrayList<>();
        in.readTypedList(buttonInfos, ButtonInfo.CREATOR);
        Bundle extras = in.readBundle(Bundle.class.getClassLoader());
        return new BannerPreference(title, message, icon, buttonInfos, extras);
    }

    public static final Creator<BannerPreference> CREATOR =
            new Creator<>() {
                @Override
                @NonNull
                public BannerPreference createFromParcel(@NonNull Parcel in) {
                    in.readInt();
                    return readFromParcel(in);
                }

                @Override
                @NonNull
                public BannerPreference[] newArray(int size) {
                    return new BannerPreference[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeString(mTitle);
        dest.writeString(mMessage);
        mIcon.writeToParcel(dest, flags);
        dest.writeTypedList(mButtonInfos, flags);
        dest.writeBundle(mExtras);
    }

    /** Builder class for {@link BannerPreference}. */
    public static final class Builder {
        private String mTitle;
        private String mMessage;
        private DeviceSettingIcon mIcon;
        private final ImmutableList.Builder<ButtonInfo> mButtonInfos =
                new ImmutableList.Builder<>();
        private Bundle mExtras = Bundle.EMPTY;

        /**
         * Sets the title of the preference.
         *
         * @param title The title of the preference.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setTitle(@NonNull String title) {
            mTitle = title;
            return this;
        }

        /**
         * Sets the message of the preference.
         *
         * @param message The title of the preference.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setMessage(@NonNull String message) {
            mMessage = message;
            return this;
        }

        /**
         * Sets the icon of the preference.
         *
         * @param icon The icon.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setIcon(DeviceSettingIcon icon) {
            mIcon = icon;
            return this;
        }

        /**
         * Adds a button in the preference.
         *
         * @param buttonInfo The button to add.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder addButtonInfo(@NonNull ButtonInfo buttonInfo) {
            mButtonInfos.add(buttonInfo);
            return this;
        }

        /**
         * Sets the extras bundle.
         *
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setExtras(@NonNull Bundle extras) {
            mExtras = extras;
            return this;
        }

        /**
         * Builds the {@link BannerPreference} object.
         *
         * @return Returns the built {@link BannerPreference} object.
         */
        @NonNull
        public BannerPreference build() {
            return new BannerPreference(mTitle, mMessage, mIcon, mButtonInfos.build(), mExtras);
        }
    }

    /**
     * Gets the title of the preference.
     *
     * @return The title.
     */
    @NonNull
    public String getTitle() {
        return mTitle;
    }

    /**
     * Gets the message of the preference.
     *
     * @return The message.
     */
    @NonNull
    public String getMessage() {
        return mMessage;
    }

    /**
     * Gets the icon of the {@link BannerPreference}.
     *
     * @return Returns the index of the icon.
     */
    public DeviceSettingIcon getIcon() {
        return mIcon;
    }

    /**
     * Gets the button list in the preference.
     *
     * @return the button list.
     */
    @NonNull
    public List<ButtonInfo> getButtonInfos() {
        return mButtonInfos;
    }

    /**
     * Gets the extras Bundle.
     *
     * @return Returns a Bundle object.
     */
    @NonNull
    public Bundle getExtras() {
        return mExtras;
    }
}
+166 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.bluetooth.devicesettings;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;

import java.util.Objects;

/** A data class representing a button in {@link BannerPreference}. */
public class ButtonInfo implements Parcelable {
    private final String mLabel;
    private final DeviceSettingAction mAction;
    private final Bundle mExtras;

    ButtonInfo(@NonNull String label, @NonNull DeviceSettingAction action, @NonNull Bundle extras) {
        validate(label, action);
        mLabel = label;
        mAction = action;
        mExtras = extras;
    }

    private static void validate(String label, DeviceSettingAction action) {
        if (Objects.isNull(label)) {
            throw new IllegalArgumentException("Label must be set");
        }
        if (Objects.isNull(action)) {
            throw new IllegalArgumentException("Action must be set");
        }
    }

    /** Read a {@link ButtonInfo} instance from {@link Parcel}. */
    @NonNull
    public static ButtonInfo readFromParcel(@NonNull Parcel in) {
        String label = in.readString();
        DeviceSettingAction action = DeviceSettingAction.readFromParcel(in);
        Bundle extras = in.readBundle(Bundle.class.getClassLoader());
        return new ButtonInfo(label, action, extras);
    }

    public static final Creator<ButtonInfo> CREATOR =
            new Creator<>() {
                @Override
                @NonNull
                public ButtonInfo createFromParcel(@NonNull Parcel in) {
                    return readFromParcel(in);
                }

                @Override
                @NonNull
                public ButtonInfo[] newArray(int size) {
                    return new ButtonInfo[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeString(mLabel);
        mAction.writeToParcel(dest, flags);
        dest.writeBundle(mExtras);
    }

    /** Builder class for {@link ButtonInfo}. */
    public static final class Builder {
        private String mLabel;
        private DeviceSettingAction mAction = DeviceSettingAction.EMPTY_ACTION;
        private Bundle mExtras = Bundle.EMPTY;

        /**
         * Sets the label of the button.
         *
         * @param label The label of the button.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setLabel(@NonNull String label) {
            mLabel = label;
            return this;
        }

        /**
         * Sets the action of the button.
         *
         * @param action The action of the button.
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setAction(@NonNull DeviceSettingAction action) {
            mAction = action;
            return this;
        }

        /**
         * Sets the extras bundle.
         *
         * @return Returns the Builder object.
         */
        @NonNull
        public Builder setExtras(@NonNull Bundle extras) {
            mExtras = extras;
            return this;
        }

        /**
         * Builds the {@link ButtonInfo} object.
         *
         * @return Returns the built {@link ButtonInfo} object.
         */
        @NonNull
        public ButtonInfo build() {
            return new ButtonInfo(mLabel, mAction, mExtras);
        }
    }

    /**
     * Gets the label of the button.
     *
     * @return the label to be shown under the button
     */
    @NonNull
    public String getLabel() {
        return mLabel;
    }

    /**
     * Gets the action of the button.
     *
     * @return the action in button
     */
    @NonNull
    public DeviceSettingAction getAction() {
        return mAction;
    }

    /**
     * Gets the extras Bundle.
     *
     * @return Returns a Bundle object.
     */
    @NonNull
    public Bundle getExtras() {
        return mExtras;
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.bluetooth.devicesettings;

import androidx.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.SOURCE)
@IntDef(
        value = {
            DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_NONE,
            DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_INFO,
            DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_WARNING,
            DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_ERROR,
        },
        open = true)
public @interface DeviceSettingDefaultIcon {
    /** Default icon is not used. */
    int DEVICE_SETTING_DEFAULT_ICON_NONE = 0;

    /** The default icon is info icon. */
    int DEVICE_SETTING_DEFAULT_ICON_INFO = 1;

    /** The default icon is warning icon. */
    int DEVICE_SETTING_DEFAULT_ICON_WARNING = 2;

    /** The default icon is error icon. */
    int DEVICE_SETTING_DEFAULT_ICON_ERROR = 3;
}
+172 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.settingslib.bluetooth.devicesettings;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Objects;

/** A data class representing a device setting icon. */
public class DeviceSettingIcon implements Parcelable {
    @DeviceSettingDefaultIcon private final int mDefaultIcon;
    private final Bitmap mCustomizedIcon;
    private final Bundle mExtras;

    DeviceSettingIcon(
            @DeviceSettingDefaultIcon int defaultIcon,
            @Nullable Bitmap customizedIcon,
            @NonNull Bundle extras) {
        mDefaultIcon = defaultIcon;
        mCustomizedIcon = customizedIcon;
        mExtras = extras;
    }

    public static final DeviceSettingIcon NO_ICON = new DeviceSettingIcon(
            DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_NONE, null, Bundle.EMPTY);

    /** Reads a {@link DeviceSettingIcon} from {@link Parcel}. */
    @NonNull
    public static DeviceSettingIcon readFromParcel(@NonNull Parcel in) {
        int defaultIcon = in.readInt();
        Bitmap customizedIcon = in.readParcelable(Bitmap.class.getClassLoader());
        Bundle extra = in.readBundle(Bundle.class.getClassLoader());
        return new DeviceSettingIcon(defaultIcon, customizedIcon, extra);
    }

    public static final Creator<DeviceSettingIcon> CREATOR =
            new Creator<>() {
                @Override
                @NonNull
                public DeviceSettingIcon createFromParcel(@NonNull Parcel in) {
                    return readFromParcel(in);
                }

                @Override
                @NonNull
                public DeviceSettingIcon[] newArray(int size) {
                    return new DeviceSettingIcon[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    /** Writes the instance to {@link Parcel}. */
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mDefaultIcon);
        dest.writeParcelable(mCustomizedIcon, flags);
        dest.writeBundle(mExtras);
    }

    /** Builder class for {@link DeviceSettingIcon}. */
    public static final class Builder {
        @DeviceSettingDefaultIcon
        private int mDefaultIcon = DeviceSettingDefaultIcon.DEVICE_SETTING_DEFAULT_ICON_NONE;
        private Bitmap mCustomizedIcon = null;
        private Bundle mExtras = Bundle.EMPTY;

        /**
         * Sets the default icon index, as defined by IntDef {@link DeviceSettingDefaultIcon}.
         *
         * @return Returns the Builder object.
         */
        @NonNull
        public DeviceSettingIcon.Builder setDefaultIcon(@DeviceSettingDefaultIcon int defaultIcon) {
            mDefaultIcon = defaultIcon;
            return this;
        }

        /**
         * Sets the customized icon.
         *
         * @return Returns the Builder object.
         */
        @NonNull
        public DeviceSettingIcon.Builder setCustomizedIcon(Bitmap customizedIcon) {
            mCustomizedIcon = customizedIcon;
            return this;
        }

        /**
         * Sets the extras bundle.
         *
         * @return Returns the Builder object.
         */
        @NonNull
        public DeviceSettingIcon.Builder setExtras(@NonNull Bundle extras) {
            mExtras = extras;
            return this;
        }

        /** Build the object. */
        @NonNull
        public DeviceSettingIcon build() {
            return new DeviceSettingIcon(mDefaultIcon, mCustomizedIcon, mExtras);
        }
    }

    /**
     * Gets the default icon index, as defined by IntDef {@link DeviceSettingDefaultIcon}.
     *
     * @return the setting ID.
     */
    @DeviceSettingDefaultIcon
    public int getDefaultIcon() {
        return mDefaultIcon;
    }

    /**
     * Gets the customized icon.
     *
     * @return the customized icon.
     */
    @Nullable
    public Bitmap getCustomizedIcon() {
        return mCustomizedIcon;
    }

    /**
     * Gets the extras Bundle.
     *
     * @return Returns a Bundle object.
     */
    @NonNull
    public Bundle getExtras() {
        return mExtras;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (!(obj instanceof DeviceSettingIcon other)) return false;
        return mDefaultIcon == other.mDefaultIcon
                && Objects.equals(mCustomizedIcon, other.mCustomizedIcon);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mDefaultIcon, mCustomizedIcon);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
            DeviceSettingType.DEVICE_SETTING_TYPE_MULTI_TOGGLE,
            DeviceSettingType.DEVICE_SETTING_TYPE_FOOTER,
            DeviceSettingType.DEVICE_SETTING_TYPE_HELP,
            DeviceSettingType.DEVICE_SETTING_TYPE_BANNER,
        },
        open = true)
public @interface DeviceSettingType {
@@ -46,4 +47,7 @@ public @interface DeviceSettingType {

    /** Device setting type is "help" preference. */
    int DEVICE_SETTING_TYPE_HELP = 4;
    /** Device setting type is banner preference. */

    int DEVICE_SETTING_TYPE_BANNER = 5;
}
Loading