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

Commit b5de8125 authored by Peter Zhang's avatar Peter Zhang Committed by Automerger Merge Worker
Browse files

Merge "Expand SettingsLib ProviderTile to support non-switch type of...

Merge "Expand SettingsLib ProviderTile to support non-switch type of Preferences" into udc-d1-dev am: af98c616 am: f8441c3c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23061005



Change-Id: I719bc79101bc6514266880c2630034791967114c
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents b080ebad f8441c3c
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -16,7 +16,7 @@


package com.android.settingslib.drawer;
package com.android.settingslib.drawer;


/** Interface for {@link SwitchController} whose instances support dynamic summary */
/** Interface for {@link EntryController} whose instances support dynamic summary */
public interface DynamicSummary {
public interface DynamicSummary {
    /** @return the dynamic summary text */
    /** @return the dynamic summary text */
    String getDynamicSummary();
    String getDynamicSummary();
+1 −1
Original line number Original line Diff line number Diff line
@@ -16,7 +16,7 @@


package com.android.settingslib.drawer;
package com.android.settingslib.drawer;


/** Interface for {@link SwitchController} whose instances support dynamic title */
/** Interface for {@link EntryController} whose instances support dynamic title */
public interface DynamicTitle {
public interface DynamicTitle {
    /** @return the dynamic title text */
    /** @return the dynamic title text */
    String getDynamicTitle();
    String getDynamicTitle();
+222 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 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.drawer;

import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * An abstract class for injecting entries to Settings.
 */
public abstract class EntriesProvider extends ContentProvider {
    private static final String TAG = "EntriesProvider";

    public static final String METHOD_GET_ENTRY_DATA = "getEntryData";
    public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon";
    public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle";
    public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary";
    public static final String METHOD_IS_CHECKED = "isChecked";
    public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged";

    /**
     * @deprecated use {@link #METHOD_GET_ENTRY_DATA} instead.
     */
    @Deprecated
    public static final String METHOD_GET_SWITCH_DATA = "getSwitchData";

    public static final String EXTRA_ENTRY_DATA = "entry_data";
    public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state";
    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error";
    public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message";

    /**
     * @deprecated use {@link #EXTRA_ENTRY_DATA} instead.
     */
    @Deprecated
    public static final String EXTRA_SWITCH_DATA = "switch_data";

    private String mAuthority;
    private final Map<String, EntryController> mControllerMap = new LinkedHashMap<>();
    private final List<Bundle> mEntryDataList = new ArrayList<>();

    /**
     * Get a list of {@link EntryController} for this provider.
     */
    protected abstract List<? extends EntryController> createEntryControllers();

    protected EntryController getController(String key) {
        return mControllerMap.get(key);
    }

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        mAuthority = info.authority;
        Log.i(TAG, mAuthority);
        super.attachInfo(context, info);
    }

    @Override
    public boolean onCreate() {
        final List<? extends EntryController> controllers = createEntryControllers();
        if (controllers == null || controllers.isEmpty()) {
            throw new IllegalArgumentException();
        }

        for (EntryController controller : controllers) {
            final String key = controller.getKey();
            if (TextUtils.isEmpty(key)) {
                throw new NullPointerException("Entry key cannot be null: "
                        + controller.getClass().getSimpleName());
            } else if (mControllerMap.containsKey(key)) {
                throw new IllegalArgumentException("Entry key " + key + " is duplicated by: "
                        + controller.getClass().getSimpleName());
            }

            controller.setAuthority(mAuthority);
            mControllerMap.put(key, controller);
            if (!(controller instanceof PrimarySwitchController)) {
                mEntryDataList.add(controller.getBundle());
            }
        }
        return true;
    }

    @Override
    public Bundle call(String method, String uriString, Bundle extras) {
        final Bundle bundle = new Bundle();
        final String key = extras != null
                ? extras.getString(META_DATA_PREFERENCE_KEYHINT)
                : null;
        if (TextUtils.isEmpty(key)) {
            switch (method) {
                case METHOD_GET_ENTRY_DATA:
                    bundle.putParcelableList(EXTRA_ENTRY_DATA, mEntryDataList);
                    return bundle;
                case METHOD_GET_SWITCH_DATA:
                    bundle.putParcelableList(EXTRA_SWITCH_DATA, mEntryDataList);
                    return bundle;
                default:
                    return null;
            }
        }

        final EntryController controller = mControllerMap.get(key);
        if (controller == null) {
            return null;
        }

        switch (method) {
            case METHOD_GET_ENTRY_DATA:
            case METHOD_GET_SWITCH_DATA:
                if (!(controller instanceof PrimarySwitchController)) {
                    return controller.getBundle();
                }
                break;
            case METHOD_GET_PROVIDER_ICON:
                if (controller instanceof ProviderIcon) {
                    return ((ProviderIcon) controller).getProviderIcon();
                }
                break;
            case METHOD_GET_DYNAMIC_TITLE:
                if (controller instanceof DynamicTitle) {
                    bundle.putString(META_DATA_PREFERENCE_TITLE,
                            ((DynamicTitle) controller).getDynamicTitle());
                    return bundle;
                }
                break;
            case METHOD_GET_DYNAMIC_SUMMARY:
                if (controller instanceof DynamicSummary) {
                    bundle.putString(META_DATA_PREFERENCE_SUMMARY,
                            ((DynamicSummary) controller).getDynamicSummary());
                    return bundle;
                }
                break;
            case METHOD_IS_CHECKED:
                if (controller instanceof ProviderSwitch) {
                    bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE,
                            ((ProviderSwitch) controller).isSwitchChecked());
                    return bundle;
                }
                break;
            case METHOD_ON_CHECKED_CHANGED:
                if (controller instanceof ProviderSwitch) {
                    return onSwitchCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE),
                            (ProviderSwitch) controller);
                }
                break;
        }
        return null;
    }

    private Bundle onSwitchCheckedChanged(boolean checked, ProviderSwitch controller) {
        final boolean success = controller.onSwitchCheckedChanged(checked);
        final Bundle bundle = new Bundle();
        bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success);
        if (success) {
            if (controller instanceof DynamicSummary) {
                ((EntryController) controller).notifySummaryChanged(getContext());
            }
        } else {
            bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE,
                    controller.getSwitchErrorMessage(checked));
        }
        return bundle;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String getType(Uri uri) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }
}
+246 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 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.drawer;

import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY;
import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE;
import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;

import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;

/**
 * A controller that manages events for switch.
 */
public abstract class EntryController {

    private String mAuthority;

    /**
     * Returns the key for this switch.
     */
    public abstract String getKey();

    /**
     * Returns the {@link MetaData} for this switch.
     */
    protected abstract MetaData getMetaData();

    /**
     * Notify registered observers that title was updated and attempt to sync changes.
     */
    public void notifyTitleChanged(Context context) {
        if (this instanceof DynamicTitle) {
            notifyChanged(context, METHOD_GET_DYNAMIC_TITLE);
        }
    }

    /**
     * Notify registered observers that summary was updated and attempt to sync changes.
     */
    public void notifySummaryChanged(Context context) {
        if (this instanceof DynamicSummary) {
            notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY);
        }
    }

    void setAuthority(String authority) {
        mAuthority = authority;
    }

    Bundle getBundle() {
        final MetaData metaData = getMetaData();
        if (metaData == null) {
            throw new NullPointerException("Should not return null in getMetaData()");
        }

        final Bundle bundle = metaData.build();
        final String uriString = new Uri.Builder()
                .scheme(ContentResolver.SCHEME_CONTENT)
                .authority(mAuthority)
                .build()
                .toString();
        bundle.putString(META_DATA_PREFERENCE_KEYHINT, getKey());
        if (this instanceof ProviderIcon) {
            bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString);
        }
        if (this instanceof DynamicTitle) {
            bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString);
        }
        if (this instanceof DynamicSummary) {
            bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString);
        }
        if (this instanceof ProviderSwitch) {
            bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString);
        }
        return bundle;
    }

    private void notifyChanged(Context context, String method) {
        final Uri uri = TileUtils.buildUri(mAuthority, method, getKey());
        context.getContentResolver().notifyChange(uri, null);
    }

    /**
     * Collects all meta data of the item.
     */
    protected static class MetaData {
        private String mCategory;
        private int mOrder;
        @DrawableRes
        private int mIcon;
        private int mIconBackgroundHint;
        private int mIconBackgroundArgb;
        private Boolean mIconTintable;
        @StringRes
        private int mTitleId;
        private String mTitle;
        @StringRes
        private int mSummaryId;
        private String mSummary;
        private PendingIntent mPendingIntent;

        /**
         * @param category the category of the switch. This value must be from {@link CategoryKey}.
         */
        public MetaData(@NonNull String category) {
            mCategory = category;
        }

        /**
         * Set the order of the item that should be displayed on screen. Bigger value items displays
         * closer on top.
         */
        public MetaData setOrder(int order) {
            mOrder = order;
            return this;
        }

        /** Set the icon that should be displayed for the item. */
        public MetaData setIcon(@DrawableRes int icon) {
            mIcon = icon;
            return this;
        }

        /** Set the icon background color. The value may or may not be used by Settings app. */
        public MetaData setIconBackgoundHint(int hint) {
            mIconBackgroundHint = hint;
            return this;
        }

        /** Set the icon background color as raw ARGB. */
        public MetaData setIconBackgoundArgb(int argb) {
            mIconBackgroundArgb = argb;
            return this;
        }

        /** Specify whether the icon is tintable. */
        public MetaData setIconTintable(boolean tintable) {
            mIconTintable = tintable;
            return this;
        }

        /** Set the title that should be displayed for the item. */
        public MetaData setTitle(@StringRes int id) {
            mTitleId = id;
            return this;
        }

        /** Set the title that should be displayed for the item. */
        public MetaData setTitle(String title) {
            mTitle = title;
            return this;
        }

        /** Set the summary text that should be displayed for the item. */
        public MetaData setSummary(@StringRes int id) {
            mSummaryId = id;
            return this;
        }

        /** Set the summary text that should be displayed for the item. */
        public MetaData setSummary(String summary) {
            mSummary = summary;
            return this;
        }

        public MetaData setPendingIntent(PendingIntent pendingIntent) {
            mPendingIntent = pendingIntent;
            return this;
        }

        protected Bundle build() {
            final Bundle bundle = new Bundle();
            bundle.putString(EXTRA_CATEGORY_KEY, mCategory);

            if (mOrder != 0) {
                bundle.putInt(META_DATA_KEY_ORDER, mOrder);
            }

            if (mIcon != 0) {
                bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon);
            }
            if (mIconBackgroundHint != 0) {
                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint);
            }
            if (mIconBackgroundArgb != 0) {
                bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb);
            }
            if (mIconTintable != null) {
                bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable);
            }

            if (mTitleId != 0) {
                bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId);
            } else if (mTitle != null) {
                bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle);
            }

            if (mSummaryId != 0) {
                bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId);
            } else if (mSummary != null) {
                bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary);
            }

            if (mPendingIntent != null) {
                bundle.putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, mPendingIntent);
            }

            return bundle;
        }
    }
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.settingslib.drawer;
import android.os.Bundle;
import android.os.Bundle;


/**
/**
 *  Interface for {@link SwitchController} whose instances support icon provided from the content
 *  Interface for {@link EntryController} whose instances support icon provided from the content
 *  provider
 *  provider
 */
 */
public interface ProviderIcon {
public interface ProviderIcon {
Loading