OSDN Git Service

Speed up setting launch
authorJason Monk <jmonk@google.com>
Wed, 2 Dec 2015 20:39:19 +0000 (15:39 -0500)
committerJason Monk <jmonk@google.com>
Wed, 2 Dec 2015 20:54:29 +0000 (15:54 -0500)
Try to avoid too many calls to the PM and cache the info we get
from it to avoid too much stuff during settings launch.

Change-Id: I64132cbe47cf8eac6080c8c82583b0b5eeb75a28

packages/SettingsLib/src/com/android/settingslib/drawer/DashboardTile.java
packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java

index 6fef134..347e9f7 100644 (file)
@@ -74,6 +74,11 @@ public class DashboardTile implements Parcelable {
      */
     public int priority;
 
+    /**
+     * The metaData from the activity that defines this tile.
+     */
+    public Bundle metaData;
+
     public DashboardTile() {
         // Empty
     }
@@ -107,6 +112,7 @@ public class DashboardTile implements Parcelable {
         dest.writeBundle(extras);
         dest.writeString(category);
         dest.writeInt(priority);
+        dest.writeBundle(metaData);
     }
 
     public void readFromParcel(Parcel in) {
@@ -125,6 +131,7 @@ public class DashboardTile implements Parcelable {
         extras = in.readBundle();
         category = in.readString();
         priority = in.readInt();
+        metaData = in.readBundle();
     }
 
     DashboardTile(Parcel in) {
index 00dadb8..581c810 100644 (file)
@@ -18,9 +18,15 @@ package com.android.settingslib.drawer;
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.TypedArray;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.support.v4.widget.DrawerLayout;
+import android.util.Log;
 import android.util.Pair;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -33,21 +39,30 @@ import android.widget.ListView;
 import android.widget.Toolbar;
 import com.android.settingslib.R;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
 public class SettingsDrawerActivity extends Activity {
 
+    protected static final boolean DEBUG_TIMING = false;
+    private static final String TAG = "SettingsDrawerActivity";
+
+    private static List<DashboardCategory> sDashboardCategories;
+    private static HashMap<Pair<String, String>, DashboardTile> sTileCache;
+
+    private final PackageReceiver mPackageReceiver = new PackageReceiver();
+    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
+
     private SettingsDrawerAdapter mDrawerAdapter;
-    // Hold on to a cache of tiles to avoid loading the info multiple times.
-    private final HashMap<Pair<String, String>, DashboardTile> mTileCache = new HashMap<>();
-    private List<DashboardCategory> mDashboardCategories;
     private DrawerLayout mDrawerLayout;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        long startTime = System.currentTimeMillis();
+
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         super.setContentView(R.layout.settings_with_drawer);
         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
@@ -62,6 +77,10 @@ public class SettingsDrawerActivity extends Activity {
             mDrawerLayout = null;
             return;
         }
+        if (sDashboardCategories == null) {
+            sTileCache = new HashMap<>();
+            sDashboardCategories = TileUtils.getCategories(this, sTileCache);
+        }
         setActionBar(toolbar);
         mDrawerAdapter = new SettingsDrawerAdapter(this);
         ListView listView = (ListView) findViewById(R.id.left_drawer);
@@ -72,6 +91,8 @@ public class SettingsDrawerActivity extends Activity {
                 onTileClicked(mDrawerAdapter.getTile(position));
             };
         });
+        if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+                + " ms");
     }
 
     @Override
@@ -88,7 +109,29 @@ public class SettingsDrawerActivity extends Activity {
     protected void onResume() {
         super.onResume();
 
-        updateDrawer();
+        final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+        filter.addDataScheme("package");
+        registerReceiver(mPackageReceiver, filter);
+
+        new CategoriesUpdater().execute();
+    }
+
+    @Override
+    protected void onPause() {
+        unregisterReceiver(mPackageReceiver);
+
+        super.onPause();
+    }
+
+    public void addCategoryListener(CategoryListener listener) {
+        mCategoryListeners.add(listener);
+    }
+
+    public void remCategoryListener(CategoryListener listener) {
+        mCategoryListeners.remove(listener);
     }
 
     public void openDrawer() {
@@ -134,11 +177,16 @@ public class SettingsDrawerActivity extends Activity {
         }
     }
 
-    public List<DashboardCategory> getDashboardCategories(boolean force) {
-        if (force) {
-            mDashboardCategories = TileUtils.getCategories(this, mTileCache);
+    public List<DashboardCategory> getDashboardCategories() {
+        return sDashboardCategories;
+    }
+
+    protected void onCategoriesChanged() {
+        updateDrawer();
+        final int N = mCategoryListeners.size();
+        for (int i = 0; i < N; i++) {
+            mCategoryListeners.get(i).onCategoriesChanged();
         }
-        return mDashboardCategories;
     }
 
     public boolean openTile(DashboardTile tile) {
@@ -167,4 +215,28 @@ public class SettingsDrawerActivity extends Activity {
     public void onProfileTileOpen() {
         finish();
     }
+
+    public interface CategoryListener {
+        void onCategoriesChanged();
+    }
+
+    private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
+        @Override
+        protected List<DashboardCategory> doInBackground(Void... params) {
+            return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
+        }
+
+        @Override
+        protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
+            sDashboardCategories = dashboardCategories;
+            onCategoriesChanged();
+        }
+    }
+
+    private class PackageReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            new CategoriesUpdater().execute();
+        }
+    }
 }
index fef716c..24c6ae8 100644 (file)
@@ -38,7 +38,7 @@ public class SettingsDrawerAdapter extends BaseAdapter {
     }
 
     void updateCategories() {
-        List<DashboardCategory> categories = mActivity.getDashboardCategories(true);
+        List<DashboardCategory> categories = mActivity.getDashboardCategories();
         mItems.clear();
         for (int i = 0; i < categories.size(); i++) {
             Item category = new Item();
index 18e8d31..6b36680 100644 (file)
@@ -14,6 +14,7 @@ import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -35,6 +36,7 @@ import java.util.Map;
 public class TileUtils {
 
     private static final boolean DEBUG = false;
+    private static final boolean DEBUG_TIMING = true;
 
     private static final String LOG_TAG = "TileUtils";
 
@@ -105,12 +107,9 @@ public class TileUtils {
 
     private static final String SETTING_PKG = "com.android.settings";
 
-    public static List<DashboardCategory> getCategories(Context context) {
-        return getCategories(context, new HashMap<Pair<String, String>, DashboardTile>());
-    }
-
     public static List<DashboardCategory> getCategories(Context context,
             HashMap<Pair<String, String>, DashboardTile> cache) {
+        final long startTime = System.currentTimeMillis();
         ArrayList<DashboardTile> tiles = new ArrayList<>();
         UserManager userManager = UserManager.get(context);
         for (UserHandle user : userManager.getUserProfiles()) {
@@ -143,6 +142,8 @@ public class TileUtils {
             Collections.sort(category.tiles, TILE_COMPARATOR);
         }
         Collections.sort(categories, CATEGORY_COMPARATOR);
+        if (DEBUG_TIMING) Log.d(LOG_TAG, "getCategories took "
+                + (System.currentTimeMillis() - startTime) + " ms");
         return categories;
     }
 
@@ -207,7 +208,9 @@ public class TileUtils {
                         activityInfo.packageName, activityInfo.name);
                 tile.category = categoryKey;
                 tile.priority = requireSettings ? resolved.priority : 0;
-                updateTileData(context, tile);
+                tile.metaData = activityInfo.metaData;
+                updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
+                        pm);
                 if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
 
                 addedCache.put(key, tile);
@@ -231,64 +234,52 @@ public class TileUtils {
         return null;
     }
 
-    private static boolean updateTileData(Context context, DashboardTile tile) {
-        Intent intent = tile.intent;
-        if (intent != null) {
-            // Find the activity that is in the system image
-            PackageManager pm = context.getPackageManager();
-            List<ResolveInfo> list = tile.userHandle.size() != 0
-                    ? pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA,
-                            tile.userHandle.get(0).getIdentifier())
-                    : pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-            int listSize = list.size();
-            for (int i = 0; i < listSize; i++) {
-                ResolveInfo resolveInfo = list.get(i);
-                if (resolveInfo.activityInfo.applicationInfo.isSystemApp()) {
-                    int icon = 0;
-                    CharSequence title = null;
-                    String summary = null;
-
-                    // Get the activity's meta-data
-                    try {
-                        Resources res = pm.getResourcesForApplication(
-                                resolveInfo.activityInfo.packageName);
-                        Bundle metaData = resolveInfo.activityInfo.metaData;
-
-                        if (res != null && metaData != null) {
-                            if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
-                                icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
-                            }
-                            if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
-                                title = metaData.getString(META_DATA_PREFERENCE_TITLE);
-                            }
-                            if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
-                                summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
-                            }
-                        }
-                    } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
-                        if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
+    private static boolean updateTileData(Context context, DashboardTile tile,
+            ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
+        if (applicationInfo.isSystemApp()) {
+            int icon = 0;
+            CharSequence title = null;
+            String summary = null;
+
+            // Get the activity's meta-data
+            try {
+                Resources res = pm.getResourcesForApplication(
+                        applicationInfo.packageName);
+                Bundle metaData = activityInfo.metaData;
+
+                if (res != null && metaData != null) {
+                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
+                        icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
                     }
-
-                    // Set the preference title to the activity's label if no
-                    // meta-data is found
-                    if (TextUtils.isEmpty(title)) {
-                        title = resolveInfo.loadLabel(pm).toString();
+                    if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
+                        title = metaData.getString(META_DATA_PREFERENCE_TITLE);
                     }
-                    if (icon == 0) {
-                        icon = resolveInfo.activityInfo.icon;
+                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
+                        summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
                     }
-
-                    // Set icon, title and summary for the preference
-                    tile.icon = Icon.createWithResource(resolveInfo.activityInfo.packageName, icon);
-                    tile.title = title;
-                    tile.summary = summary;
-                    // Replace the intent with this specific activity
-                    tile.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
-                            resolveInfo.activityInfo.name);
-
-                    return true;
                 }
+            } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
+                if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
             }
+
+            // Set the preference title to the activity's label if no
+            // meta-data is found
+            if (TextUtils.isEmpty(title)) {
+                title = activityInfo.loadLabel(pm).toString();
+            }
+            if (icon == 0) {
+                icon = activityInfo.icon;
+            }
+
+            // Set icon, title and summary for the preference
+            tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
+            tile.title = title;
+            tile.summary = summary;
+            // Replace the intent with this specific activity
+            tile.intent = new Intent().setClassName(activityInfo.packageName,
+                    activityInfo.name);
+
+            return true;
         }
 
         return false;