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

Commit f509d7e6 authored by Jason Monk's avatar Jason Monk
Browse files

Add suggestions parsing to SettingsLib

Add a parser that will parse an XML of the suggestion categories
and ordering and query those categories into Tiles.

Change-Id: I3154c94e176108358163bbe36feb48e889fe00d1
parent 472a5669
Loading
Loading
Loading
Loading
+177 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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;

import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.util.Xml;
import android.view.InflateException;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SuggestionParser {

    private static final String TAG = "SuggestionParser";

    private final Context mContext;
    private final List<SuggestionCategory> mSuggestionList;
    private final ArrayMap<Pair<String, String>, Tile> addCache = new ArrayMap<>();

    public SuggestionParser(Context context, int orderXml) {
        mContext = context;
        mSuggestionList = (List<SuggestionCategory>) new SuggestionOrderInflater(mContext)
                .parse(orderXml);
    }

    public List<Tile> getSuggestions() {
        List<Tile> suggestions = new ArrayList<>();
        final int N = mSuggestionList.size();
        for (int i = 0; i < N; i++) {
            readSuggestions(mSuggestionList.get(i), suggestions);
        }
        return suggestions;
    }

    private void readSuggestions(SuggestionCategory category, List<Tile> suggestions) {
        int countBefore = suggestions.size();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(category.category);
        if (category.pkg != null) {
            intent.setPackage(category.pkg);
        }
        TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
                addCache, null, suggestions, true, false);
        if (!category.multiple && suggestions.size() > (countBefore + 1)) {
            // If there are too many, remove them all and only re-add the one with the highest
            // priority.
            Tile item = suggestions.remove(suggestions.size() - 1);
            while (suggestions.size() > countBefore) {
                Tile last = suggestions.remove(suggestions.size() - 1);
                if (last.priority > item.priority) {
                    item = last;
                }
            }
            suggestions.add(item);
        }
    }

    private static class SuggestionCategory {
        public String category;
        public String pkg;
        public boolean multiple;
    }

    private static class SuggestionOrderInflater {
        private static final String TAG_LIST = "optional-steps";
        private static final String TAG_ITEM = "step";

        private static final String ATTR_CATEGORY = "category";
        private static final String ATTR_PACKAGE = "package";
        private static final String ATTR_MULTIPLE = "multiple";

        private final Context mContext;

        public SuggestionOrderInflater(Context context) {
            mContext = context;
        }

        public Object parse(int resource) {
            XmlPullParser parser = mContext.getResources().getXml(resource);
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            try {
                // Look for the root node.
                int type;
                do {
                    type = parser.next();
                } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }

                // Temp is the root that was found in the xml
                Object xmlRoot = onCreateItem(parser.getName(), attrs);

                // Inflate all children under temp
                rParse(parser, xmlRoot, attrs);
                return xmlRoot;
            } catch (XmlPullParserException | IOException e) {
                Log.w(TAG, "Problem parser resource " + resource, e);
                return null;
            }
        }

        /**
         * Recursive method used to descend down the xml hierarchy and instantiate
         * items, instantiate their children.
         */
        private void rParse(XmlPullParser parser, Object parent, final AttributeSet attrs)
                throws XmlPullParserException, IOException {
            final int depth = parser.getDepth();

            int type;
            while (((type = parser.next()) != XmlPullParser.END_TAG ||
                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                if (type != XmlPullParser.START_TAG) {
                    continue;
                }

                final String name = parser.getName();

                Object item = onCreateItem(name, attrs);
                onAddChildItem(parent, item);
                rParse(parser, item, attrs);
            }
        }

        protected void onAddChildItem(Object parent, Object child) {
            if (parent instanceof List<?> && child instanceof SuggestionCategory) {
                ((List<SuggestionCategory>) parent).add((SuggestionCategory) child);
            } else {
                throw new IllegalArgumentException("Parent was not a list");
            }
        }

        protected Object onCreateItem(String name, AttributeSet attrs) {
            if (name.equals(TAG_LIST)) {
                return new ArrayList<SuggestionCategory>();
            } else if (name.equals(TAG_ITEM)) {
                SuggestionCategory category = new SuggestionCategory();
                category.category = attrs.getAttributeValue(null, ATTR_CATEGORY);
                category.pkg = attrs.getAttributeValue(null, ATTR_PACKAGE);
                String multiple = attrs.getAttributeValue(null, ATTR_MULTIPLE);
                category.multiple = !TextUtils.isEmpty(multiple) && Boolean.parseBoolean(multiple);
                return category;
            } else {
                throw new IllegalArgumentException("Unknown item " + name);
            }
        }
    }
}
+7 −7
Original line number Diff line number Diff line
@@ -43,22 +43,22 @@ public class DashboardCategory implements Parcelable {
    /**
     * List of the category's children
     */
    public List<DashboardTile> tiles = new ArrayList<DashboardTile>();
    public List<Tile> tiles = new ArrayList<Tile>();


    public DashboardCategory() {
        // Empty
    }

    public void addTile(DashboardTile tile) {
    public void addTile(Tile tile) {
        tiles.add(tile);
    }

    public void addTile(int n, DashboardTile tile) {
    public void addTile(int n, Tile tile) {
        tiles.add(n, tile);
    }

    public void removeTile(DashboardTile tile) {
    public void removeTile(Tile tile) {
        tiles.remove(tile);
    }

@@ -70,7 +70,7 @@ public class DashboardCategory implements Parcelable {
        return tiles.size();
    }

    public DashboardTile getTile(int n) {
    public Tile getTile(int n) {
        return tiles.get(n);
    }

@@ -89,7 +89,7 @@ public class DashboardCategory implements Parcelable {
        dest.writeInt(count);

        for (int n = 0; n < count; n++) {
            DashboardTile tile = tiles.get(n);
            Tile tile = tiles.get(n);
            tile.writeToParcel(dest, flags);
        }
    }
@@ -102,7 +102,7 @@ public class DashboardCategory implements Parcelable {
        final int count = in.readInt();

        for (int n = 0; n < count; n++) {
            DashboardTile tile = DashboardTile.CREATOR.createFromParcel(in);
            Tile tile = Tile.CREATOR.createFromParcel(in);
            tiles.add(tile);
        }
    }
+2 −2
Original line number Diff line number Diff line
@@ -30,9 +30,9 @@ public class ProfileSelectDialog extends DialogFragment implements OnClickListen

    private static final String ARG_SELECTED_TILE = "selectedTile";

    private DashboardTile mSelectedTile;
    private Tile mSelectedTile;

    public static void show(FragmentManager manager, DashboardTile tile) {
    public static void show(FragmentManager manager, Tile tile) {
        ProfileSelectDialog dialog = new ProfileSelectDialog();
        Bundle args = new Bundle();
        args.putParcelable(ARG_SELECTED_TILE, tile);
+3 −3
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public class SettingsDrawerActivity extends Activity {
    private static final String TAG = "SettingsDrawerActivity";

    private static List<DashboardCategory> sDashboardCategories;
    private static HashMap<Pair<String, String>, DashboardTile> sTileCache;
    private static HashMap<Pair<String, String>, Tile> sTileCache;

    private final PackageReceiver mPackageReceiver = new PackageReceiver();
    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
@@ -194,7 +194,7 @@ public class SettingsDrawerActivity extends Activity {
        }
    }

    public boolean openTile(DashboardTile tile) {
    public boolean openTile(Tile tile) {
        closeDrawer();
        if (tile == null) {
            return false;
@@ -211,7 +211,7 @@ public class SettingsDrawerActivity extends Activity {
        return true;
    }

    protected void onTileClicked(DashboardTile tile) {
    protected void onTileClicked(Tile tile) {
        if (openTile(tile)) {
            finish();
        }
+3 −3
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public class SettingsDrawerAdapter extends BaseAdapter {
            mItems.add(category);
            for (int j = 0; j < dashboardCategory.tiles.size(); j++) {
                Item tile = new Item();
                DashboardTile dashboardTile = dashboardCategory.tiles.get(j);
                Tile dashboardTile = dashboardCategory.tiles.get(j);
                tile.label = dashboardTile.title;
                tile.icon = dashboardTile.icon;
                tile.tile = dashboardTile;
@@ -58,7 +58,7 @@ public class SettingsDrawerAdapter extends BaseAdapter {
        notifyDataSetChanged();
    }

    public DashboardTile getTile(int position) {
    public Tile getTile(int position) {
        return mItems.get(position).tile;
    }

@@ -101,6 +101,6 @@ public class SettingsDrawerAdapter extends BaseAdapter {
    private static class Item {
        public Icon icon;
        public CharSequence label;
        public DashboardTile tile;
        public Tile tile;
    }
}
Loading