diff options
author | Amith Yamasani <yamasani@google.com> | 2013-12-19 23:30:35 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-12-19 23:30:35 +0000 |
commit | 49782e46c0eb85a25ae2abcf80880c48dbab5aea (patch) | |
tree | 9fab2a40c41004d78b7001dc766d85f61d24f582 /services/core/java/com/android/server/search/SearchManagerService.java | |
parent | 4dace6f66d498c2d119adf265776aa83b28452af (diff) | |
parent | 9158825f9c41869689d6b1786d7c7aa8bdd524ce (diff) | |
download | frameworks_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.java | 277 |
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(); + } + } + } +} |