19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.search; 18ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert 19c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.app.ActivityManager; 20c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.app.AppGlobals; 21fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackbornimport android.app.IActivityManager; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ISearchManager; 238d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.SearchManager; 242126aac7f992b57fc52141a8bd09fa7a45ac2509Bjorn Bringertimport android.app.SearchableInfo; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 26ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.ContentResolver; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 29c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.content.pm.IPackageManager; 30c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.content.pm.PackageManager; 31ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.pm.ResolveInfo; 32ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.database.ContentObserver; 335bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.os.Binder; 340e5f110fc915a9b044eb04cd07ae7ac588eacc8fTim Kilbournimport android.os.Bundle; 357877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolovimport android.os.Handler; 36c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.os.RemoteException; 37f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle; 38258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager; 39ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.provider.Settings; 408d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.util.Log; 415bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.util.SparseArray; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 434175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkeyimport com.android.internal.annotations.GuardedBy; 447a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.content.PackageMonitor; 457877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolovimport com.android.internal.os.BackgroundThread; 46fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils; 477a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.util.IndentingPrintWriter; 48165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggiimport com.android.server.LocalServices; 494175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkeyimport com.android.server.SystemService; 50165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggiimport com.android.server.statusbar.StatusBarManagerInternal; 517a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey 5264442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.FileDescriptor; 5364442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.PrintWriter; 546d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringertimport java.util.List; 556d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 574175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey * The search manager service handles the search UI, and maintains a registry of 584175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey * searchable activities. 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 60444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertpublic class SearchManagerService extends ISearchManager.Stub { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "SearchManagerService"; 627877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov final Handler mHandler; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 644175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey public static class Lifecycle extends SystemService { 654175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey private SearchManagerService mService; 664175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 674175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey public Lifecycle(Context context) { 684175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey super(context); 694175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 704175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 714175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 724175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey public void onStart() { 734175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey mService = new SearchManagerService(getContext()); 744175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey publishBinderService(Context.SEARCH_SERVICE, mService); 754175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 764175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 774175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 787877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov public void onUnlockUser(final int userId) { 797877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov mService.mHandler.post(new Runnable() { 807877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov @Override 817877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov public void run() { 827877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov mService.onUnlockUser(userId); 837877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov } 847877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov }); 854175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 864175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 874175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 884175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey public void onCleanupUser(int userHandle) { 894175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey mService.onCleanupUser(userHandle); 904175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 914175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 924175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 93444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // Context that the service is running in. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 95f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 96ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert // This field is initialized lazily in getSearchables(), and then never modified. 974175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @GuardedBy("mSearchables") 984175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey private final SparseArray<Searchables> mSearchables = new SparseArray<>(); 99ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 101875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Initializes the Search Manager service in the provided system context. 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Only one instance of this object should be created! 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context to use for accessing DB, window manager, etc. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 106f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath public SearchManagerService(Context context) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 10864442c11555d828a41af0b8a58ab933357889061Amith Yamasani new MyPackageMonitor().register(context, null, UserHandle.ALL, true); 1094175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey new GlobalSearchProviderObserver(context.getContentResolver()); 1107877b8add811aafd7f57f731c8e22c9fe6a319c8Fyodor Kupolov mHandler = BackgroundThread.getHandler(); 111444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert } 112444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 11364442c11555d828a41af0b8a58ab933357889061Amith Yamasani private Searchables getSearchables(int userId) { 1144175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey return getSearchables(userId, false); 1154175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 1164175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey 1174175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey private Searchables getSearchables(int userId, boolean forceUpdate) { 1184175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey final long token = Binder.clearCallingIdentity(); 11964442c11555d828a41af0b8a58ab933357889061Amith Yamasani try { 1204175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey final UserManager um = mContext.getSystemService(UserManager.class); 1214175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey if (um.getUserInfo(userId) == null) { 1224175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey throw new IllegalStateException("User " + userId + " doesn't exist"); 1234175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 124ce18c8167766f92856f94a8e88e19de4698960e6Jeff Sharkey if (!um.isUserUnlockingOrUnlocked(userId)) { 1254175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey throw new IllegalStateException("User " + userId + " isn't unlocked"); 1264175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } 12764442c11555d828a41af0b8a58ab933357889061Amith Yamasani } finally { 1284175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey Binder.restoreCallingIdentity(token); 129ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert } 13064442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (mSearchables) { 13164442c11555d828a41af0b8a58ab933357889061Amith Yamasani Searchables searchables = mSearchables.get(userId); 13264442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (searchables == null) { 13364442c11555d828a41af0b8a58ab933357889061Amith Yamasani searchables = new Searchables(mContext, userId); 1344175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey searchables.updateSearchableList(); 13564442c11555d828a41af0b8a58ab933357889061Amith Yamasani mSearchables.append(userId, searchables); 1364175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey } else if (forceUpdate) { 1374175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey searchables.updateSearchableList(); 13864442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 13964442c11555d828a41af0b8a58ab933357889061Amith Yamasani return searchables; 14064442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 14164442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 1425bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani 1434175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey private void onUnlockUser(int userId) { 14438e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey try { 14538e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey getSearchables(userId, true); 14638e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey } catch (IllegalStateException ignored) { 14738e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey // We're just trying to warm a cache, so we don't mind if the user 14838e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey // was stopped or destroyed before we got here. 14938e0d0f512063ee8f863caf12b0bb4ff2000792dJeff Sharkey } 1502c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert } 1512c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert 1524175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey private void onCleanupUser(int userId) { 1534175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey synchronized (mSearchables) { 1544175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey mSearchables.remove(userId); 15564442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 15664442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 15764442c11555d828a41af0b8a58ab933357889061Amith Yamasani 1582c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert /** 159444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * Refreshes the "searchables" list when packages are added/removed. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 161ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert class MyPackageMonitor extends PackageMonitor { 16213bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 164ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert public void onSomePackagesChanged() { 16513bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani updateSearchables(); 16613bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani } 16713bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 16813bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani @Override 16913bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani public void onPackageModified(String pkg) { 17013bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani updateSearchables(); 17113bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani } 17213bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 17313bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani private void updateSearchables() { 17464442c11555d828a41af0b8a58ab933357889061Amith Yamasani final int changingUserId = getChangingUserId(); 17564442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (mSearchables) { 1765bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // Update list of searchable activities 1775bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani for (int i = 0; i < mSearchables.size(); i++) { 17864442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (changingUserId == mSearchables.keyAt(i)) { 1794175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey mSearchables.valueAt(i).updateSearchableList(); 18064442c11555d828a41af0b8a58ab933357889061Amith Yamasani break; 18164442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 1825bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 1835bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 184ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert // Inform all listeners that the list of searchables has been updated. 185ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); 186e6687942308b64e32d292ae1e5d38beeb86c951fAmith Yamasani intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING 187e6687942308b64e32d292ae1e5d38beeb86c951fAmith Yamasani | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 18864442c11555d828a41af0b8a58ab933357889061Amith Yamasani mContext.sendBroadcastAsUser(intent, new UserHandle(changingUserId)); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath class GlobalSearchProviderObserver extends ContentObserver { 193ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private final ContentResolver mResolver; 194ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 195ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public GlobalSearchProviderObserver(ContentResolver resolver) { 196ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath super(null); 197ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mResolver = resolver; 198ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mResolver.registerContentObserver( 199ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY), 200ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath false /* notifyDescendants */, 201ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath this); 202ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 203ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 204ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath @Override 205ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public void onChange(boolean selfChange) { 20664442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (mSearchables) { 2075bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani for (int i = 0; i < mSearchables.size(); i++) { 2084175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey mSearchables.valueAt(i).updateSearchableList(); 2095bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 2105bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 211ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); 212ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 2135ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 214ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 215ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 216ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 217444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // 218444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // Searchable activities API 219444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // 220a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert 221a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert /** 222444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * Returns the SearchableInfo for a given activity. 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param launchActivity The activity from which we're launching this search. 225875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @return Returns a SearchableInfo record describing the parameters of the search, 226875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or null if no searchable metadata was available. 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2284175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 2296cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public SearchableInfo getSearchableInfo(final ComponentName launchActivity) { 2306cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert if (launchActivity == null) { 2316cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.e(TAG, "getSearchableInfo(), activity == null"); 2326cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 234f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn return getSearchables(UserHandle.getCallingUserId()).getSearchableInfo(launchActivity); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 236f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 2376d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert /** 2386d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert * Returns a list of the searchable activities that can be included in global search. 2396d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert */ 2404175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 2416d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert public List<SearchableInfo> getSearchablesInGlobalSearch() { 242f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn return getSearchables(UserHandle.getCallingUserId()).getSearchablesInGlobalSearchList(); 2436d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 244875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 2454175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 246ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public List<ResolveInfo> getGlobalSearchActivities() { 247f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivities(); 248ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 249ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 250f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 2516cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the global search activity. 252f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 2534175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 2546cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public ComponentName getGlobalSearchActivity() { 255f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivity(); 256f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 257f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 258f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 2596cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the web search activity. 260f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 2614175be2f4e1e27490f38c387525d0c0cba88b47bJeff Sharkey @Override 2626cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public ComponentName getWebSearchActivity() { 263f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn return getSearchables(UserHandle.getCallingUserId()).getWebSearchActivity(); 264f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 265f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 266c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani @Override 267165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi public void launchAssist(Bundle args) { 268165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi StatusBarManagerInternal statusBarManager = 269165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi LocalServices.getService(StatusBarManagerInternal.class); 270165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi if (statusBarManager != null) { 271165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi statusBarManager.startAssist(args); 272165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi } 273165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi } 274165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi 275165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi private ComponentName getLegacyAssistComponent(int userHandle) { 276c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani try { 27705cb363bf3e714d0a5fb1bc97dfed639c9c9f950Ben Pietrzak userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 278165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi Binder.getCallingUid(), userHandle, true, false, "getLegacyAssistComponent", null); 279c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani IPackageManager pm = AppGlobals.getPackageManager(); 280c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani Intent assistIntent = new Intent(Intent.ACTION_ASSIST); 281c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani ResolveInfo info = 282c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani pm.resolveIntent(assistIntent, 283165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 284165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi PackageManager.MATCH_DEFAULT_ONLY, userHandle); 285c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani if (info != null) { 286c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani return new ComponentName( 287c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani info.activityInfo.applicationInfo.packageName, 288c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani info.activityInfo.name); 289c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani } 290c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani } catch (RemoteException re) { 291c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani // Local call 292165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi Log.e(TAG, "RemoteException in getLegacyAssistComponent: " + re); 293c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani } catch (Exception e) { 294165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi Log.e(TAG, "Exception in getLegacyAssistComponent: " + e); 295c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani } 296c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani return null; 297c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani } 29864442c11555d828a41af0b8a58ab933357889061Amith Yamasani 29964442c11555d828a41af0b8a58ab933357889061Amith Yamasani @Override 300165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) { 301719e70c9f2a1d15568da6e9040169016f7c1f891Powei Feng ComponentName comp = getLegacyAssistComponent(userHandle); 302fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn if (comp == null) { 303fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn return false; 304fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn } 305fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn long ident = Binder.clearCallingIdentity(); 306fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn try { 307fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn Intent intent = new Intent(Intent.ACTION_ASSIST); 308fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn intent.setComponent(comp); 309dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka IActivityManager am = ActivityManager.getService(); 310719e70c9f2a1d15568da6e9040169016f7c1f891Powei Feng return am.launchAssistIntent(intent, ActivityManager.ASSIST_CONTEXT_BASIC, hint, 311719e70c9f2a1d15568da6e9040169016f7c1f891Powei Feng userHandle, args); 312fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn } catch (RemoteException e) { 313fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn } finally { 314fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn Binder.restoreCallingIdentity(ident); 315fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn } 316fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn return true; 317fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn } 318fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn 319fdf5b35ab46639759d6389a4e2a4d5799cb6814bDianne Hackborn @Override 32064442c11555d828a41af0b8a58ab933357889061Amith Yamasani public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 321fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 32252801aae89196b7ad16ef21b07d2d621e7d0bb61Jeff Sharkey 32364442c11555d828a41af0b8a58ab933357889061Amith Yamasani IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 32464442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (mSearchables) { 32564442c11555d828a41af0b8a58ab933357889061Amith Yamasani for (int i = 0; i < mSearchables.size(); i++) { 32664442c11555d828a41af0b8a58ab933357889061Amith Yamasani ipw.print("\nUser: "); ipw.println(mSearchables.keyAt(i)); 32764442c11555d828a41af0b8a58ab933357889061Amith Yamasani ipw.increaseIndent(); 32864442c11555d828a41af0b8a58ab933357889061Amith Yamasani mSearchables.valueAt(i).dump(fd, ipw, args); 32964442c11555d828a41af0b8a58ab933357889061Amith Yamasani ipw.decreaseIndent(); 33064442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 33164442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 33264442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 334