OSDN Git Service

Rebuild search index if dynamic setting packages change.
authorSvetoslav <svetoslavganov@google.com>
Mon, 14 Apr 2014 17:10:25 +0000 (10:10 -0700)
committerSvetoslav <svetoslavganov@google.com>
Tue, 15 Apr 2014 00:13:02 +0000 (17:13 -0700)
We have some settings that are dynamically generated based on what packages are
installed. For example, accessibility services, etc. We now update the index when
the relevant installed packages change.

bug:14056852

Change-Id: I6143382bf2c7399d3c80abea0835d717935a9200

src/com/android/settings/SettingsActivity.java

index 68331b1..789ad2a 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.settings;
 
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.OnAccountsUpdateListener;
@@ -42,6 +44,7 @@ import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -51,6 +54,10 @@ import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
+import android.print.PrintManager;
+import android.printservice.PrintService;
+import android.printservice.PrintServiceInfo;
+import android.provider.SearchIndexableData;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -61,10 +68,12 @@ import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
 import android.widget.ListView;
 
 import android.widget.SearchView;
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.settings.accessibility.AccessibilitySettings;
@@ -94,6 +103,7 @@ import com.android.settings.nfc.AndroidBeam;
 import com.android.settings.nfc.PaymentSettings;
 import com.android.settings.print.PrintJobSettingsFragment;
 import com.android.settings.print.PrintSettingsFragment;
+import com.android.settings.search.SearchIndexableRaw;
 import com.android.settings.tts.TextToSpeechSettings;
 import com.android.settings.users.UserSettings;
 import com.android.settings.vpn2.VpnSettings;
@@ -109,6 +119,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 
 import static com.android.settings.dashboard.Header.HEADER_ID_UNDEFINED;
@@ -304,6 +315,9 @@ public class SettingsActivity extends Activity
         }
     };
 
+    private final DynamicIndexablePackageMonitor mDynamicIndexablePackageMonitor =
+            new DynamicIndexablePackageMonitor();
+
     private Button mNextButton;
     private ActionBar mActionBar;
     private boolean mDisplayHomeAsUpEnabled;
@@ -610,6 +624,8 @@ public class SettingsActivity extends Activity
         invalidateHeaders();
 
         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+        mDynamicIndexablePackageMonitor.register(this);
     }
 
     @Override
@@ -624,6 +640,8 @@ public class SettingsActivity extends Activity
                 mDevelopmentPreferencesListener);
 
         mDevelopmentPreferencesListener = null;
+
+        mDynamicIndexablePackageMonitor.unregister();
     }
 
     @Override
@@ -1271,4 +1289,145 @@ public class SettingsActivity extends Activity
                 FragmentManager.POP_BACK_STACK_INCLUSIVE);
         mSearchMenuItem.collapseActionView();
     }
+
+    private static final class DynamicIndexablePackageMonitor extends PackageMonitor {
+        private static final Intent ACCESSIBILITY_SERVICE_INTENT =
+                new Intent(AccessibilityService.SERVICE_INTERFACE);
+
+        private static final Intent PRINT_SERVICE_INTENT =
+                new Intent(PrintService.SERVICE_INTERFACE);
+
+        private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
+
+        private static final int MSG_PACKAGE_AVAILABLE = 1;
+        private static final int MSG_PACKAGE_UNAVAILABLE = 2;
+
+        private final List<String> mAccessibilityServices = new ArrayList<String>();
+        private final List<String> mPrintServices = new ArrayList<String>();
+
+        private final Handler mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_PACKAGE_AVAILABLE: {
+                        String packageName = (String) msg.obj;
+                        handlePackageAvailable(packageName);
+                    } break;
+
+                    case MSG_PACKAGE_UNAVAILABLE: {
+                        String packageName = (String) msg.obj;
+                        handlePackageUnavailable(packageName);
+                    } break;
+                }
+            }
+        };
+
+        private Context mContext;
+
+        public void register(Context context) {
+            mContext = context;
+
+            // Cache accessibility service packages to know when they go away.
+            AccessibilityManager accessibilityManager = (AccessibilityManager)
+                    mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+            List<AccessibilityServiceInfo> accessibilityServices = accessibilityManager
+                    .getInstalledAccessibilityServiceList();
+            final int accessibilityServiceCount = accessibilityServices.size();
+            for (int i = 0; i < accessibilityServiceCount; i++) {
+                AccessibilityServiceInfo accessibilityService = accessibilityServices.get(i);
+                mAccessibilityServices.add(accessibilityService.getResolveInfo()
+                        .serviceInfo.packageName);
+            }
+
+            // Cache print service packages to know when they go away.
+            PrintManager printManager = (PrintManager)
+                    mContext.getSystemService(Context.PRINT_SERVICE);
+            List<PrintServiceInfo> printServices = printManager.getInstalledPrintServices();
+            final int serviceCount = printServices.size();
+            for (int i = 0; i < serviceCount; i++) {
+                PrintServiceInfo printService = printServices.get(i);
+                mPrintServices.add(printService.getResolveInfo()
+                        .serviceInfo.packageName);
+            }
+
+            register(context, Looper.getMainLooper(), UserHandle.CURRENT, false);
+        }
+
+        public void unregister() {
+            super.unregister();
+            mAccessibilityServices.clear();
+            mPrintServices.clear();
+        }
+
+        // Covers installed, appeared external storage with the package, upgraded.
+        @Override
+        public void onPackageAppeared(String packageName, int uid) {
+            postMessage(MSG_PACKAGE_AVAILABLE, packageName);
+        }
+
+        // Covers uninstalled, removed external storage with the package.
+        @Override
+        public void onPackageDisappeared(String packageName, int uid) {
+            postMessage(MSG_PACKAGE_UNAVAILABLE, packageName);
+        }
+
+        // Covers enabled, disabled.
+        @Override
+        public void onPackageModified(String packageName) {
+            super.onPackageModified(packageName);
+            final int state = mContext.getPackageManager().getApplicationEnabledSetting(
+                    packageName);
+            if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+                    || state ==  PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+                postMessage(MSG_PACKAGE_AVAILABLE, packageName);
+            } else {
+                postMessage(MSG_PACKAGE_UNAVAILABLE, packageName);
+            }
+        }
+
+        private void postMessage(int what, String packageName) {
+            Message message = mHandler.obtainMessage(what, packageName);
+            mHandler.sendMessageDelayed(message, DELAY_PROCESS_PACKAGE_CHANGE);
+        }
+
+        private void handlePackageAvailable(String packageName) {
+            if (!mAccessibilityServices.contains(packageName)) {
+                Intent intent = ACCESSIBILITY_SERVICE_INTENT;
+                intent.setPackage(packageName);
+                if (!mContext.getPackageManager().queryIntentServices(intent, 0).isEmpty()) {
+                    mAccessibilityServices.add(packageName);
+                    Index.getInstance(mContext).updateFromClassNameResource(
+                            AccessibilitySettings.class.getName(), false, true);
+                }
+                intent.setPackage(null);
+            }
+
+            if (!mPrintServices.contains(packageName)) {
+                Intent intent = PRINT_SERVICE_INTENT;
+                intent.setPackage(packageName);
+                if (!mContext.getPackageManager().queryIntentServices(intent, 0).isEmpty()) {
+                    mPrintServices.add(packageName);
+                    Index.getInstance(mContext).updateFromClassNameResource(
+                            PrintSettingsFragment.class.getName(), false, true);
+                }
+                intent.setPackage(null);
+            }
+        }
+
+        private void handlePackageUnavailable(String packageName) {
+            final int accessibilityIndex = mAccessibilityServices.indexOf(packageName);
+            if (accessibilityIndex >= 0) {
+                mAccessibilityServices.remove(accessibilityIndex);
+                Index.getInstance(mContext).updateFromClassNameResource(
+                        AccessibilitySettings.class.getName(), true, true);
+            }
+
+            final int printIndex = mPrintServices.indexOf(packageName);
+            if (printIndex >= 0) {
+                mPrintServices.remove(printIndex);
+                Index.getInstance(mContext).updateFromClassNameResource(
+                        PrintSettingsFragment.class.getName(), true, true);
+            }
+        }
+    }
 }