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
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server.search;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringertimport com.android.internal.content.PackageMonitor;
2064442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport com.android.internal.util.IndentingPrintWriter;
21ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert
22c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.app.ActivityManager;
23c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.app.ActivityManagerNative;
24c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.app.AppGlobals;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ISearchManager;
268d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.SearchManager;
272126aac7f992b57fc52141a8bd09fa7a45ac2509Bjorn Bringertimport android.app.SearchableInfo;
282c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.content.BroadcastReceiver;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
30ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.ContentResolver;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
332c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.content.IntentFilter;
34c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.content.pm.IPackageManager;
35c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.content.pm.PackageManager;
36ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.pm.ResolveInfo;
37ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.database.ContentObserver;
385bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.os.Binder;
392c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.os.Process;
40c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.os.RemoteException;
41f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
42258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager;
43ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.provider.Settings;
448d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.util.Log;
45c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasaniimport android.util.Slog;
465bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.util.SparseArray;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4864442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.FileDescriptor;
4964442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.PrintWriter;
506d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringertimport java.util.List;
516d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
53444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * The search manager service handles the search UI, and maintains a registry of searchable
54444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * activities.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
56444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertpublic class SearchManagerService extends ISearchManager.Stub {
57444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert
58444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    // general debugging support
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SearchManagerService";
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    // Context that the service is running in.
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
63f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
64ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert    // This field is initialized lazily in getSearchables(), and then never modified.
6564442c11555d828a41af0b8a58ab933357889061Amith Yamasani    private final SparseArray<Searchables> mSearchables = new SparseArray<Searchables>();
66ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
68875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * Initializes the Search Manager service in the provided system context.
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Only one instance of this object should be created!
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context to use for accessing DB, window manager, etc.
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
73f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    public SearchManagerService(Context context)  {
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
752c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert        mContext.registerReceiver(new BootCompletedReceiver(),
762c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
77e6687942308b64e32d292ae1e5d38beeb86c951fAmith Yamasani        mContext.registerReceiver(new UserReceiver(),
7864442c11555d828a41af0b8a58ab933357889061Amith Yamasani                new IntentFilter(Intent.ACTION_USER_REMOVED));
7964442c11555d828a41af0b8a58ab933357889061Amith Yamasani        new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
80444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    }
81444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert
8264442c11555d828a41af0b8a58ab933357889061Amith Yamasani    private Searchables getSearchables(int userId) {
8364442c11555d828a41af0b8a58ab933357889061Amith Yamasani        long origId = Binder.clearCallingIdentity();
8464442c11555d828a41af0b8a58ab933357889061Amith Yamasani        try {
8564442c11555d828a41af0b8a58ab933357889061Amith Yamasani            boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
8664442c11555d828a41af0b8a58ab933357889061Amith Yamasani                    .getUserInfo(userId) != null;
8764442c11555d828a41af0b8a58ab933357889061Amith Yamasani            if (!userExists) return null;
8864442c11555d828a41af0b8a58ab933357889061Amith Yamasani        } finally {
8964442c11555d828a41af0b8a58ab933357889061Amith Yamasani            Binder.restoreCallingIdentity(origId);
90ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert        }
9164442c11555d828a41af0b8a58ab933357889061Amith Yamasani        synchronized (mSearchables) {
9264442c11555d828a41af0b8a58ab933357889061Amith Yamasani            Searchables searchables = mSearchables.get(userId);
935bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani
9464442c11555d828a41af0b8a58ab933357889061Amith Yamasani            if (searchables == null) {
9564442c11555d828a41af0b8a58ab933357889061Amith Yamasani                Log.i(TAG, "Building list of searchable activities for userId=" + userId);
9664442c11555d828a41af0b8a58ab933357889061Amith Yamasani                searchables = new Searchables(mContext, userId);
9764442c11555d828a41af0b8a58ab933357889061Amith Yamasani                searchables.buildSearchableList();
9864442c11555d828a41af0b8a58ab933357889061Amith Yamasani                mSearchables.append(userId, searchables);
9964442c11555d828a41af0b8a58ab933357889061Amith Yamasani            }
10064442c11555d828a41af0b8a58ab933357889061Amith Yamasani            return searchables;
10164442c11555d828a41af0b8a58ab933357889061Amith Yamasani        }
10264442c11555d828a41af0b8a58ab933357889061Amith Yamasani    }
1035bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani
10464442c11555d828a41af0b8a58ab933357889061Amith Yamasani    private void onUserRemoved(int userId) {
10564442c11555d828a41af0b8a58ab933357889061Amith Yamasani        if (userId != UserHandle.USER_OWNER) {
10664442c11555d828a41af0b8a58ab933357889061Amith Yamasani            synchronized (mSearchables) {
10764442c11555d828a41af0b8a58ab933357889061Amith Yamasani                mSearchables.remove(userId);
10864442c11555d828a41af0b8a58ab933357889061Amith Yamasani            }
1095bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani        }
1109bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert    }
1113ed6a3342b89651e8359956cefcc0076b6a4a30aKarl Rosaen
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1132c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert     * Creates the initial searchables list after boot.
1142c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert     */
1152c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert    private final class BootCompletedReceiver extends BroadcastReceiver {
1162c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert        @Override
1172c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert        public void onReceive(Context context, Intent intent) {
1182c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert            new Thread() {
1192c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                @Override
1202c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                public void run() {
1212c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1222c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                    mContext.unregisterReceiver(BootCompletedReceiver.this);
1235bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                    getSearchables(0);
1242c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert                }
1252c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert            }.start();
1262c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert        }
1272c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert    }
1282c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert
12964442c11555d828a41af0b8a58ab933357889061Amith Yamasani    private final class UserReceiver extends BroadcastReceiver {
13064442c11555d828a41af0b8a58ab933357889061Amith Yamasani        @Override
13164442c11555d828a41af0b8a58ab933357889061Amith Yamasani        public void onReceive(Context context, Intent intent) {
13264442c11555d828a41af0b8a58ab933357889061Amith Yamasani            onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_OWNER));
13364442c11555d828a41af0b8a58ab933357889061Amith Yamasani        }
13464442c11555d828a41af0b8a58ab933357889061Amith Yamasani    }
13564442c11555d828a41af0b8a58ab933357889061Amith Yamasani
1362c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert    /**
137444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert     * Refreshes the "searchables" list when packages are added/removed.
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
139ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert    class MyPackageMonitor extends PackageMonitor {
14013bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
142ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert        public void onSomePackagesChanged() {
14313bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani            updateSearchables();
14413bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani        }
14513bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani
14613bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani        @Override
14713bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani        public void onPackageModified(String pkg) {
14813bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani            updateSearchables();
14913bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani        }
15013bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani
15113bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani        private void updateSearchables() {
15264442c11555d828a41af0b8a58ab933357889061Amith Yamasani            final int changingUserId = getChangingUserId();
15364442c11555d828a41af0b8a58ab933357889061Amith Yamasani            synchronized (mSearchables) {
1545bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                // Update list of searchable activities
1555bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                for (int i = 0; i < mSearchables.size(); i++) {
15664442c11555d828a41af0b8a58ab933357889061Amith Yamasani                    if (changingUserId == mSearchables.keyAt(i)) {
15764442c11555d828a41af0b8a58ab933357889061Amith Yamasani                        getSearchables(mSearchables.keyAt(i)).buildSearchableList();
15864442c11555d828a41af0b8a58ab933357889061Amith Yamasani                        break;
15964442c11555d828a41af0b8a58ab933357889061Amith Yamasani                    }
1605bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                }
1615bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani            }
162ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert            // Inform all listeners that the list of searchables has been updated.
163ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert            Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
164e6687942308b64e32d292ae1e5d38beeb86c951fAmith Yamasani            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
165e6687942308b64e32d292ae1e5d38beeb86c951fAmith Yamasani                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
16664442c11555d828a41af0b8a58ab933357889061Amith Yamasani            mContext.sendBroadcastAsUser(intent, new UserHandle(changingUserId));
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
170ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath    class GlobalSearchProviderObserver extends ContentObserver {
171ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        private final ContentResolver mResolver;
172ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
173ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        public GlobalSearchProviderObserver(ContentResolver resolver) {
174ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath            super(null);
175ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath            mResolver = resolver;
176ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath            mResolver.registerContentObserver(
177ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath                    Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
178ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath                    false /* notifyDescendants */,
179ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath                    this);
180ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        }
181ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
182ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        @Override
183ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        public void onChange(boolean selfChange) {
18464442c11555d828a41af0b8a58ab933357889061Amith Yamasani            synchronized (mSearchables) {
1855bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                for (int i = 0; i < mSearchables.size(); i++) {
1865bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                    getSearchables(mSearchables.keyAt(i)).buildSearchableList();
1875bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani                }
1885bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani            }
189ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath            Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
190ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
1915ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
192ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath        }
193ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
194ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath    }
195ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
196444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    //
197444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    // Searchable activities API
198444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert    //
199a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert
200a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert    /**
201444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert     * Returns the SearchableInfo for a given activity.
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param launchActivity The activity from which we're launching this search.
204875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * @return Returns a SearchableInfo record describing the parameters of the search,
205875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen     * or null if no searchable metadata was available.
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2076cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert    public SearchableInfo getSearchableInfo(final ComponentName launchActivity) {
2086cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert        if (launchActivity == null) {
2096cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert            Log.e(TAG, "getSearchableInfo(), activity == null");
2106cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert            return null;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
212f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getSearchables(UserHandle.getCallingUserId()).getSearchableInfo(launchActivity);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
214f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
2156d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    /**
2166d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     * Returns a list of the searchable activities that can be included in global search.
2176d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert     */
2186d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    public List<SearchableInfo> getSearchablesInGlobalSearch() {
219f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getSearchables(UserHandle.getCallingUserId()).getSearchablesInGlobalSearchList();
2206d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert    }
221875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen
222ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath    public List<ResolveInfo> getGlobalSearchActivities() {
223f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivities();
224ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath    }
225ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath
226f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
2276cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert     * Gets the name of the global search activity.
228f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
2296cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert    public ComponentName getGlobalSearchActivity() {
230f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivity();
231f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
232f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
233f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    /**
2346cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert     * Gets the name of the web search activity.
235f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath     */
2366cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert    public ComponentName getWebSearchActivity() {
237f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getSearchables(UserHandle.getCallingUserId()).getWebSearchActivity();
238f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath    }
239f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath
240c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani    @Override
241c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani    public ComponentName getAssistIntent(int userHandle) {
242c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani        try {
243f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            if (userHandle != UserHandle.getCallingUserId()) {
244c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                // Requesting a different user, make sure that they have the permission
245c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                if (ActivityManager.checkComponentPermission(
246c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
247c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        Binder.getCallingUid(), -1, true)
248c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        == PackageManager.PERMISSION_GRANTED) {
249c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    // Translate to the current user id, if caller wasn't aware
250f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn                    if (userHandle == UserHandle.USER_CURRENT) {
251c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        long identity = Binder.clearCallingIdentity();
252c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        userHandle = ActivityManagerNative.getDefault().getCurrentUser().id;
253c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        Binder.restoreCallingIdentity(identity);
254c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    }
255c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                } else {
256c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    String msg = "Permission Denial: "
257c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                            + "Request to getAssistIntent for " + userHandle
258f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn                            + " but is calling from user " + UserHandle.getCallingUserId()
259c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                            + "; this requires "
260c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                            + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
261c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    Slog.w(TAG, msg);
262c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    return null;
263c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                }
264c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            }
265c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            IPackageManager pm = AppGlobals.getPackageManager();
266c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
267c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            ResolveInfo info =
268c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    pm.resolveIntent(assistIntent,
269c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
270c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                    PackageManager.MATCH_DEFAULT_ONLY, userHandle);
271c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            if (info != null) {
272c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                return new ComponentName(
273c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        info.activityInfo.applicationInfo.packageName,
274c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani                        info.activityInfo.name);
275c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            }
276c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani        } catch (RemoteException re) {
277c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            // Local call
278c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            Log.e(TAG, "RemoteException in getAssistIntent: " + re);
279c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani        } catch (Exception e) {
280c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani            Log.e(TAG, "Exception in getAssistIntent: " + e);
281c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani        }
282c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani        return null;
283c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791Amith Yamasani    }
28464442c11555d828a41af0b8a58ab933357889061Amith Yamasani
28564442c11555d828a41af0b8a58ab933357889061Amith Yamasani    @Override
28664442c11555d828a41af0b8a58ab933357889061Amith Yamasani    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
28752801aae89196b7ad16ef21b07d2d621e7d0bb61Jeff Sharkey        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
28852801aae89196b7ad16ef21b07d2d621e7d0bb61Jeff Sharkey
28964442c11555d828a41af0b8a58ab933357889061Amith Yamasani        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
29064442c11555d828a41af0b8a58ab933357889061Amith Yamasani        synchronized (mSearchables) {
29164442c11555d828a41af0b8a58ab933357889061Amith Yamasani            for (int i = 0; i < mSearchables.size(); i++) {
29264442c11555d828a41af0b8a58ab933357889061Amith Yamasani                ipw.print("\nUser: "); ipw.println(mSearchables.keyAt(i));
29364442c11555d828a41af0b8a58ab933357889061Amith Yamasani                ipw.increaseIndent();
29464442c11555d828a41af0b8a58ab933357889061Amith Yamasani                mSearchables.valueAt(i).dump(fd, ipw, args);
29564442c11555d828a41af0b8a58ab933357889061Amith Yamasani                ipw.decreaseIndent();
29664442c11555d828a41af0b8a58ab933357889061Amith Yamasani            }
29764442c11555d828a41af0b8a58ab933357889061Amith Yamasani        }
29864442c11555d828a41af0b8a58ab933357889061Amith Yamasani    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
300