summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/search/SearchManagerService.java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2013-12-19 23:30:35 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2013-12-19 23:30:35 +0000
commit49782e46c0eb85a25ae2abcf80880c48dbab5aea (patch)
tree9fab2a40c41004d78b7001dc766d85f61d24f582 /services/core/java/com/android/server/search/SearchManagerService.java
parent4dace6f66d498c2d119adf265776aa83b28452af (diff)
parent9158825f9c41869689d6b1786d7c7aa8bdd524ce (diff)
downloadframeworks_base-49782e46c0eb85a25ae2abcf80880c48dbab5aea.zip
frameworks_base-49782e46c0eb85a25ae2abcf80880c48dbab5aea.tar.gz
frameworks_base-49782e46c0eb85a25ae2abcf80880c48dbab5aea.tar.bz2
am 9158825f: Move some system services to separate directories
* commit '9158825f9c41869689d6b1786d7c7aa8bdd524ce': Move some system services to separate directories
Diffstat (limited to 'services/core/java/com/android/server/search/SearchManagerService.java')
-rw-r--r--services/core/java/com/android/server/search/SearchManagerService.java277
1 files changed, 277 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
new file mode 100644
index 0000000..486477a
--- /dev/null
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2007 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.server.search;
+
+import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.app.ISearchManager;
+import android.app.SearchManager;
+import android.app.SearchableInfo;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
+import android.os.Binder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * The search manager service handles the search UI, and maintains a registry of searchable
+ * activities.
+ */
+public class SearchManagerService extends ISearchManager.Stub {
+
+ // general debugging support
+ private static final String TAG = "SearchManagerService";
+
+ // Context that the service is running in.
+ private final Context mContext;
+
+ // This field is initialized lazily in getSearchables(), and then never modified.
+ private final SparseArray<Searchables> mSearchables = new SparseArray<Searchables>();
+
+ /**
+ * Initializes the Search Manager service in the provided system context.
+ * Only one instance of this object should be created!
+ *
+ * @param context to use for accessing DB, window manager, etc.
+ */
+ public SearchManagerService(Context context) {
+ mContext = context;
+ mContext.registerReceiver(new BootCompletedReceiver(),
+ new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ mContext.registerReceiver(new UserReceiver(),
+ new IntentFilter(Intent.ACTION_USER_REMOVED));
+ new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
+ }
+
+ private Searchables getSearchables(int userId) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+ .getUserInfo(userId) != null;
+ if (!userExists) return null;
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ synchronized (mSearchables) {
+ Searchables searchables = mSearchables.get(userId);
+
+ if (searchables == null) {
+ //Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+ searchables = new Searchables(mContext, userId);
+ searchables.buildSearchableList();
+ mSearchables.append(userId, searchables);
+ }
+ return searchables;
+ }
+ }
+
+ private void onUserRemoved(int userId) {
+ if (userId != UserHandle.USER_OWNER) {
+ synchronized (mSearchables) {
+ mSearchables.remove(userId);
+ }
+ }
+ }
+
+ /**
+ * Creates the initial searchables list after boot.
+ */
+ private final class BootCompletedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ new Thread() {
+ @Override
+ public void run() {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ mContext.unregisterReceiver(BootCompletedReceiver.this);
+ getSearchables(0);
+ }
+ }.start();
+ }
+ }
+
+ private final class UserReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_OWNER));
+ }
+ }
+
+ /**
+ * Refreshes the "searchables" list when packages are added/removed.
+ */
+ class MyPackageMonitor extends PackageMonitor {
+
+ @Override
+ public void onSomePackagesChanged() {
+ updateSearchables();
+ }
+
+ @Override
+ public void onPackageModified(String pkg) {
+ updateSearchables();
+ }
+
+ private void updateSearchables() {
+ final int changingUserId = getChangingUserId();
+ synchronized (mSearchables) {
+ // Update list of searchable activities
+ for (int i = 0; i < mSearchables.size(); i++) {
+ if (changingUserId == mSearchables.keyAt(i)) {
+ getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ break;
+ }
+ }
+ }
+ // Inform all listeners that the list of searchables has been updated.
+ Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(changingUserId));
+ }
+ }
+
+ class GlobalSearchProviderObserver extends ContentObserver {
+ private final ContentResolver mResolver;
+
+ public GlobalSearchProviderObserver(ContentResolver resolver) {
+ super(null);
+ mResolver = resolver;
+ mResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
+ false /* notifyDescendants */,
+ this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ synchronized (mSearchables) {
+ for (int i = 0; i < mSearchables.size(); i++) {
+ getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ }
+ }
+ Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ }
+
+ //
+ // Searchable activities API
+ //
+
+ /**
+ * Returns the SearchableInfo for a given activity.
+ *
+ * @param launchActivity The activity from which we're launching this search.
+ * @return Returns a SearchableInfo record describing the parameters of the search,
+ * or null if no searchable metadata was available.
+ */
+ public SearchableInfo getSearchableInfo(final ComponentName launchActivity) {
+ if (launchActivity == null) {
+ Log.e(TAG, "getSearchableInfo(), activity == null");
+ return null;
+ }
+ return getSearchables(UserHandle.getCallingUserId()).getSearchableInfo(launchActivity);
+ }
+
+ /**
+ * Returns a list of the searchable activities that can be included in global search.
+ */
+ public List<SearchableInfo> getSearchablesInGlobalSearch() {
+ return getSearchables(UserHandle.getCallingUserId()).getSearchablesInGlobalSearchList();
+ }
+
+ public List<ResolveInfo> getGlobalSearchActivities() {
+ return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivities();
+ }
+
+ /**
+ * Gets the name of the global search activity.
+ */
+ public ComponentName getGlobalSearchActivity() {
+ return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivity();
+ }
+
+ /**
+ * Gets the name of the web search activity.
+ */
+ public ComponentName getWebSearchActivity() {
+ return getSearchables(UserHandle.getCallingUserId()).getWebSearchActivity();
+ }
+
+ @Override
+ public ComponentName getAssistIntent(int userHandle) {
+ try {
+ userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userHandle, true, false, "getAssistIntent", null);
+ IPackageManager pm = AppGlobals.getPackageManager();
+ Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
+ ResolveInfo info =
+ pm.resolveIntent(assistIntent,
+ assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY, userHandle);
+ if (info != null) {
+ return new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name);
+ }
+ } catch (RemoteException re) {
+ // Local call
+ Log.e(TAG, "RemoteException in getAssistIntent: " + re);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception in getAssistIntent: " + e);
+ }
+ return null;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ synchronized (mSearchables) {
+ for (int i = 0; i < mSearchables.size(); i++) {
+ ipw.print("\nUser: "); ipw.println(mSearchables.keyAt(i));
+ ipw.increaseIndent();
+ mSearchables.valueAt(i).dump(fd, ipw, args);
+ ipw.decreaseIndent();
+ }
+ }
+ }
+}