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