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

Commit a96b11f6 authored by Fan Zhang's avatar Fan Zhang
Browse files

Build a sitemap manager to keep track of breadcrumbs

- Have a new db to track parent-child page relation at index time.
- Make a registry class to track (in IA) which page host what type of
  sub pages.
- Make a manager class that queries the db as well as IA to compute
  breadcrumbs

Fix: 32936784
Test: RunSettingsRoboTest

Change-Id: I5f1583fae772c3d477d2ad186e111b79cc3e41aa
parent 03cd212f
Loading
Loading
Loading
Loading
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.settings.dashboard;

import android.util.ArrayMap;

import com.android.settings.DevelopmentSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.SecuritySettings;
import com.android.settings.accounts.UserAndAccountDashboardFragment;
import com.android.settings.applications.AdvancedAppSettings;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.inputmethod.InputAndGestureSettings;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.notification.SoundSettings;
import com.android.settings.system.SystemDashboardFragment;
import com.android.settingslib.drawer.CategoryKey;

import java.util.Map;

/**
 * A registry to keep track of which page hosts which category.
 * TODO: Remove DashboardFragment#getCategoryKey() and just use this registry instead.
 */
public class DashboardFragmentRegistry {

    /**
     * Map from parent fragment to category key. The parent fragment hosts child with
     * category_key.
     */
    public static final Map<String, String> PARENT_TO_CATEGORY_KEY_MAP;

    /**
     * Map from category_key to parent. This is a helper to look up which fragment hosts the
     * category_key.
     */
    public static final Map<String, String> CATEGORY_KEY_TO_PARENT_MAP;

    static {
        PARENT_TO_CATEGORY_KEY_MAP = new ArrayMap<>();
        PARENT_TO_CATEGORY_KEY_MAP.put(
                NetworkDashboardFragment.class.getName(), CategoryKey.CATEGORY_NETWORK);
        PARENT_TO_CATEGORY_KEY_MAP.put(ConnectedDeviceDashboardFragment.class.getName(),
                CategoryKey.CATEGORY_DEVICE);
        PARENT_TO_CATEGORY_KEY_MAP.put(AppAndNotificationDashboardFragment.class.getName(),
                CategoryKey.CATEGORY_APPS);
        PARENT_TO_CATEGORY_KEY_MAP.put(AdvancedAppSettings.class.getName(),
                CategoryKey.CATEGORY_APPS_DEFAULT);
        PARENT_TO_CATEGORY_KEY_MAP.put(DisplaySettings.class.getName(),
                CategoryKey.CATEGORY_DISPLAY);
        PARENT_TO_CATEGORY_KEY_MAP.put(SoundSettings.class.getName(),
                CategoryKey.CATEGORY_SOUND);
        PARENT_TO_CATEGORY_KEY_MAP.put(StorageDashboardFragment.class.getName(),
                CategoryKey.CATEGORY_STORAGE);
        PARENT_TO_CATEGORY_KEY_MAP.put(SecuritySettings.class.getName(),
                CategoryKey.CATEGORY_SECURITY);
        PARENT_TO_CATEGORY_KEY_MAP.put(UserAndAccountDashboardFragment.class.getName(),
                CategoryKey.CATEGORY_ACCOUNT);
        PARENT_TO_CATEGORY_KEY_MAP.put(UserAndAccountDashboardFragment.class.getName(),
                CategoryKey.CATEGORY_ACCOUNT);
        PARENT_TO_CATEGORY_KEY_MAP.put(
                SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM);
        PARENT_TO_CATEGORY_KEY_MAP.put(
                InputAndGestureSettings.class.getName(), CategoryKey.CATEGORY_SYSTEM_INPUT);
        PARENT_TO_CATEGORY_KEY_MAP.put(InputMethodAndLanguageSettings.class.getName(),
                CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
        PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
                CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);

        CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());

        for (Map.Entry<String, String> parentToKey : PARENT_TO_CATEGORY_KEY_MAP.entrySet()) {
            CATEGORY_KEY_TO_PARENT_MAP.put(parentToKey.getValue(), parentToKey.getKey());
        }
    }
}
+212 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.settings.dashboard;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import android.util.Log;

import com.android.settings.SettingsActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.IndexDatabaseHelper;
import com.android.settings.search.IndexDatabaseHelper.IndexColumns;
import com.android.settings.search.IndexDatabaseHelper.SiteMapColumns;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;

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

import static com.android.settings.dashboard.DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP;

/**
 * A manager class that maintains a "site map" and look up breadcrumb for a certain page on demand.
 * <p/>
 * The methods on this class can only be called on a background thread.
 */
public class SiteMapManager {

    private static final String TAG = "SiteMapManager";
    private static final boolean DEBUG_TIMING = false;

    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    public static final String[] SITE_MAP_COLUMNS = {
            SiteMapColumns.PARENT_CLASS,
            SiteMapColumns.PARENT_TITLE,
            SiteMapColumns.CHILD_CLASS,
            SiteMapColumns.CHILD_TITLE
    };

    private static final String[] CLASS_TO_SCREEN_TITLE_COLUMNS = {
            IndexColumns.CLASS_NAME,
            IndexColumns.SCREEN_TITLE,
    };

    private final List<SiteMapPair> mPairs = new ArrayList<>();

    private boolean mInitialized;

    /**
     * Given a fragment class name and its screen title, build a breadcrumb from Settings root to
     * this screen.
     * <p/>
     * Not all screens have a full breadcrumb path leading up to root, it's because either some
     * page in the breadcrumb path is not indexed, or it's only reachable via search.
     */
    @WorkerThread
    public synchronized List<String> buildBreadCrumb(Context context, String clazz,
            String screenTitle) {
        init(context);
        final long startTime = System.currentTimeMillis();
        final List<String> breadcrumbs = new ArrayList<>();
        if (!mInitialized) {
            Log.w(TAG, "SiteMap is not initialized yet, skipping");
            return breadcrumbs;
        }
        breadcrumbs.add(screenTitle);
        String currentClass = clazz;
        String currentTitle = screenTitle;
        // Look up current page's parent, if found add it to breadcrumb string list, and repeat.
        while (true) {
            final SiteMapPair pair = lookUpParent(currentClass, currentTitle);
            if (pair == null) {
                if (DEBUG_TIMING) {
                    Log.d(TAG, "BreadCrumb timing: " + (System.currentTimeMillis() - startTime));
                }
                return breadcrumbs;
            }
            breadcrumbs.add(0, pair.parentTitle);
            currentClass = pair.parentClass;
            currentTitle = pair.parentTitle;
        }
    }

    /**
     * Initialize a list of {@link SiteMapPair}s. Each pair knows about a single parent-child
     * page relationship.
     *
     * We get the knowledge of such mPairs from 2 sources:
     * 1. Static indexing time: we know which page(s) a parent can open by parsing its pref xml.
     * 2. IA: We know from {@link DashboardFeatureProvider} which page can be dynamically
     * injected to where.
     */
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    @WorkerThread
    synchronized void init(Context context) {
        if (mInitialized) {
            // Make sure only init once.
            return;
        }
        final long startTime = System.currentTimeMillis();
        // First load site map from static index table.
        final Context appContext = context.getApplicationContext();
        final SQLiteDatabase db = IndexDatabaseHelper.getInstance(appContext).getReadableDatabase();
        Cursor sitemap = db.query(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, SITE_MAP_COLUMNS, null,
                null, null, null, null);
        while (sitemap.moveToNext()) {
            final SiteMapPair pair = new SiteMapPair(
                    sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.PARENT_CLASS)),
                    sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.PARENT_TITLE)),
                    sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.CHILD_CLASS)),
                    sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.CHILD_TITLE)));
            mPairs.add(pair);
        }
        sitemap.close();

        // Then prepare a local map that contains class name -> screen title mapping. This is needed
        // to figure out the display name for any fragment if it's injected dynamically through IA.
        final Map<String, String> classToTitleMap = new HashMap<>();
        final Cursor titleQuery = db.query(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX,
                CLASS_TO_SCREEN_TITLE_COLUMNS, null, null, null, null, null);
        while (titleQuery.moveToNext()) {
            classToTitleMap.put(
                    titleQuery.getString(titleQuery.getColumnIndex(IndexColumns.CLASS_NAME)),
                    titleQuery.getString(titleQuery.getColumnIndex(IndexColumns.SCREEN_TITLE)));
        }
        titleQuery.close();

        // Loop through all IA categories and pages and build additional SiteMapPairs
        List<DashboardCategory> categories = FeatureFactory.getFactory(context)
                .getDashboardFeatureProvider(context).getAllCategories();

        for (DashboardCategory category : categories) {
            // Find the category key first.
            final String parentClass = CATEGORY_KEY_TO_PARENT_MAP.get(category.key);
            if (parentClass == null) {
                continue;
            }
            // Use the key to look up parent (which page hosts this key)
            final String parentName = classToTitleMap.get(parentClass);
            if (parentName == null) {
                continue;
            }
            // Build parent-child mPairs for all children listed under this key.
            for (Tile tile : category.tiles) {
                final String childTitle = tile.title.toString();
                String childClass = null;
                if (tile.metaData != null) {
                    childClass = tile.metaData.getString(
                            SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
                }
                if (childClass == null) {
                    continue;
                }
                mPairs.add(new SiteMapPair(parentClass, parentName, childClass, childTitle));
            }
        }
        // Done.
        mInitialized = true;
        if (DEBUG_TIMING) {
            Log.d(TAG, "Init timing: " + (System.currentTimeMillis() - startTime));
        }
    }

    @WorkerThread
    private SiteMapPair lookUpParent(String clazz, String title) {
        for (SiteMapPair pair : mPairs) {
            if (TextUtils.equals(pair.childClass, clazz)
                    && TextUtils.equals(title, pair.childTitle)) {
                return pair;
            }
        }
        return null;
    }

    /**
     * Data model for a parent-child page pair.
     */
    private static class SiteMapPair {
        public final String parentClass;
        public final String parentTitle;
        public final String childClass;
        public final String childTitle;

        public SiteMapPair(String parentClass, String parentTitle, String childClass,
                String childTitle) {
            this.parentClass = parentClass;
            this.parentTitle = parentTitle;
            this.childClass = childClass;
            this.childTitle = childTitle;
        }
    }
}
+23 −1
Original line number Diff line number Diff line
@@ -28,12 +28,13 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
    private static final String TAG = "IndexDatabaseHelper";

    private static final String DATABASE_NAME = "search_index.db";
    private static final int DATABASE_VERSION = 116;
    private static final int DATABASE_VERSION = 117;

    private static final String INDEX = "index";

    public interface Tables {
        String TABLE_PREFS_INDEX = "prefs_index";
        String TABLE_SITE_MAP = "site_map";
        String TABLE_META_INDEX = "meta_index";
        String TABLE_SAVED_QUERIES = "saved_queries";
    }
@@ -72,6 +73,14 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
        String TIME_STAMP = "timestamp";
    }

    public interface SiteMapColumns {
        String DOCID = "docid";
        String PARENT_CLASS = "parent_class";
        String CHILD_CLASS = "child_class";
        String PARENT_TITLE = "parent_title";
        String CHILD_TITLE = "child_title";
    }

    private static final String CREATE_INDEX_TABLE =
            "CREATE VIRTUAL TABLE " + Tables.TABLE_PREFS_INDEX + " USING fts4" +
                    "(" +
@@ -132,6 +141,17 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
                    SavedQueriesColumns.TIME_STAMP + " INTEGER" +
                    ")";

    private static final String CREATE_SITE_MAP_TABLE =
            "CREATE VIRTUAL TABLE " + Tables.TABLE_SITE_MAP + " USING fts4" +
                    "(" +
                    SiteMapColumns.PARENT_CLASS +
                    ", " +
                    SiteMapColumns.CHILD_CLASS +
                    ", " +
                    SiteMapColumns.PARENT_TITLE +
                    ", " +
                    SiteMapColumns.CHILD_TITLE +
                    ")";
    private static final String INSERT_BUILD_VERSION =
            "INSERT INTO " + Tables.TABLE_META_INDEX +
                    " VALUES ('" + Build.VERSION.INCREMENTAL + "');";
@@ -164,6 +184,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
        db.execSQL(CREATE_INDEX_TABLE);
        db.execSQL(CREATE_META_TABLE);
        db.execSQL(CREATE_SAVED_QUERIES_TABLE);
        db.execSQL(CREATE_SITE_MAP_TABLE);
        db.execSQL(INSERT_BUILD_VERSION);
        Log.i(TAG, "Bootstrapped database");
    }
@@ -241,5 +262,6 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
        db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_META_INDEX);
        db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_PREFS_INDEX);
        db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SAVED_QUERIES);
        db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SITE_MAP);
    }
}
+22 −18
Original line number Diff line number Diff line
@@ -28,8 +28,10 @@ import android.os.BadParcelableException;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.SiteMapManager;

import java.util.ArrayList;
import java.util.Collections;
@@ -39,18 +41,20 @@ import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_ID;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_SCREEN_TITLE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_TITLE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_SUMMARY_ON;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_CLASS_NAME;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_ICON;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_ID;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_INTENT_ACTION;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE;
import static com.android.settings.search2.DatabaseResultLoader
        .COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS;
import static com.android.settings.search2.DatabaseResultLoader
        .COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_KEY;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD_TYPE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD_TYPE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_SCREEN_TITLE;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_SUMMARY_ON;
import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_TITLE;

/**
 * Controller to Build search results from {@link Cursor} Objects.
@@ -78,7 +82,8 @@ class CursorToSearchResultConverter {
        mQueryText = queryText;
    }

    public List<SearchResult> convertCursor(Cursor cursorResults, int baseRank) {
    public List<SearchResult> convertCursor(SiteMapManager sitemapManager,
            Cursor cursorResults, int baseRank) {
        if (cursorResults == null) {
            return null;
        }
@@ -86,8 +91,8 @@ class CursorToSearchResultConverter {
        final List<SearchResult> results = new ArrayList<>();

        while (cursorResults.moveToNext()) {
            SearchResult result = buildSingleSearchResultFromCursor(contextMap, cursorResults,
                    baseRank);
            SearchResult result = buildSingleSearchResultFromCursor(sitemapManager,
                    contextMap, cursorResults, baseRank);
            if (result != null) {
                results.add(result);
            }
@@ -96,8 +101,8 @@ class CursorToSearchResultConverter {
        return results;
    }

    private SearchResult buildSingleSearchResultFromCursor(Map<String, Context> contextMap,
            Cursor cursor, int baseRank) {
    private SearchResult buildSingleSearchResultFromCursor(SiteMapManager sitemapManager,
            Map<String, Context> contextMap, Cursor cursor, int baseRank) {
        final String docId = cursor.getString(COLUMN_INDEX_ID);
        /* Make sure that this result has not yet been added as a result. Checking the docID
           covers the case of multiple queries matching the same row, but we need to also to check
@@ -128,7 +133,7 @@ class CursorToSearchResultConverter {
            return null;
        }

        final List<String> breadcrumbs = getBreadcrumbs(cursor);
        final List<String> breadcrumbs = getBreadcrumbs(sitemapManager, cursor);
        final int rank = getRank(breadcrumbs, baseRank);

        final SearchResult.Builder builder = new SearchResult.Builder();
@@ -210,12 +215,11 @@ class CursorToSearchResultConverter {
        return null;
    }

    private List<String> getBreadcrumbs(Cursor cursor) {
        final List<String> breadcrumbs = new ArrayList<>();
    private List<String> getBreadcrumbs(SiteMapManager siteMapManager, Cursor cursor) {
        final String screenTitle = cursor.getString(COLUMN_INDEX_SCREEN_TITLE);
        if (!TextUtils.isEmpty(screenTitle)) {
            breadcrumbs.add(screenTitle);
        }
        final String screenClass = cursor.getString(COLUMN_INDEX_CLASS_NAME);
        final List<String> breadcrumbs = siteMapManager.buildBreadCrumb(mContext, screenClass,
                screenTitle);
        return breadcrumbs;
    }

+25 −3
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import android.provider.SearchIndexableData;
import android.provider.SearchIndexableResource;
import android.provider.SearchIndexablesContract;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -582,12 +581,13 @@ public class DatabaseIndexingManager {
            String title;
            String summary;
            String keywords;
            String childFragment;
            ResultPayload payload;

            ArrayMap<String, PreferenceController> controllerUriMap = null;
            Map<String, PreferenceController> controllerUriMap = null;

            if (fragmentName != null) {
                controllerUriMap = (ArrayMap) DatabaseIndexingUtils
                controllerUriMap = DatabaseIndexingUtils
                        .getPreferenceControllerUriMap(fragmentName, context);
            }

@@ -655,8 +655,10 @@ public class DatabaseIndexingManager {
                    }

                    payload = DatabaseIndexingUtils.getPayloadFromUriMap(controllerUriMap, key);
                    childFragment = XmlParserUtils.getDataChildFragment(context, attrs);

                    builder.setEntries(entries)
                            .setChildClassName(childFragment)
                            .setPayload(payload);

                    // Insert rows for the child nodes of PreferenceScreen
@@ -811,6 +813,18 @@ public class DatabaseIndexingManager {
        values.put(IndexDatabaseHelper.IndexColumns.PAYLOAD, row.payload);

        database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);

        if (!TextUtils.isEmpty(row.className) && !TextUtils.isEmpty(row.childClassName)) {
            ContentValues siteMapPair = new ContentValues();
            final int pairDocId = Objects.hash(row.className, row.childClassName);
            siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.DOCID, pairDocId);
            siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_CLASS, row.className);
            siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.PARENT_TITLE, row.screenTitle);
            siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_CLASS, row.childClassName);
            siteMapPair.put(IndexDatabaseHelper.SiteMapColumns.CHILD_TITLE, row.updatedTitle);

            database.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, null, siteMapPair);
        }
    }

    /**
@@ -950,6 +964,7 @@ public class DatabaseIndexingManager {
        public final String normalizedSummaryOff;
        public final String entries;
        public final String className;
        public final String childClassName;
        public final String screenTitle;
        public final int iconResId;
        public final int rank;
@@ -973,6 +988,7 @@ public class DatabaseIndexingManager {
            normalizedSummaryOff = builder.mNormalizedSummaryOff;
            entries = builder.mEntries;
            className = builder.mClassName;
            childClassName = builder.mChildClassName;
            screenTitle = builder.mScreenTitle;
            iconResId = builder.mIconResId;
            rank = builder.mRank;
@@ -1008,6 +1024,7 @@ public class DatabaseIndexingManager {
            private String mNormalizedSummaryOff;
            private String mEntries;
            private String mClassName;
            private String mChildClassName;
            private String mScreenTitle;
            private int mIconResId;
            private int mRank;
@@ -1067,6 +1084,11 @@ public class DatabaseIndexingManager {
                return this;
            }

            public Builder setChildClassName(String childClassName) {
                mChildClassName = childClassName;
                return this;
            }

            public Builder setScreenTitle(String screenTitle) {
                mScreenTitle = screenTitle;
                return this;
Loading