From c1d07a4bd26c0ecf87bfa151ae43cb92c0c73791 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Tue, 14 Aug 2012 09:32:02 -0700 Subject: [PATCH] Launch ASSIST intent on the current user Lockscreen and statusbar now launch the intent on the current user. Make sure that the intent resolution is made to the package manager for the specific user, as the app could have been disabled for that user or may have an alternative app installed. Change-Id: I93b0f972d6c7e8880b146da83dc3d08a68fe7e51 --- core/java/android/app/ISearchManager.aidl | 1 + core/java/android/app/SearchManager.java | 29 ++++++++--- .../server/search/SearchManagerService.java | 51 +++++++++++++++++++ .../com/android/systemui/SearchPanelView.java | 12 +++-- .../internal/policy/impl/LockScreen.java | 18 +++++-- .../policy/impl/PhoneWindowManager.java | 8 +-- 6 files changed, 101 insertions(+), 18 deletions(-) diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl index 688cdfd66eb5c..074d34398379a 100644 --- a/core/java/android/app/ISearchManager.aidl +++ b/core/java/android/app/ISearchManager.aidl @@ -30,4 +30,5 @@ interface ISearchManager { List getGlobalSearchActivities(); ComponentName getGlobalSearchActivity(); ComponentName getWebSearchActivity(); + ComponentName getAssistIntent(int userHandle); } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index d1d51310d6f8e..b8c99373e4076 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -31,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserId; import android.text.TextUtils; import android.util.Log; import android.util.Slog; @@ -845,14 +846,28 @@ public class SearchManager * * @hide */ - public static final Intent getAssistIntent(Context context) { - PackageManager pm = context.getPackageManager(); - Intent intent = new Intent(Intent.ACTION_ASSIST); - ComponentName component = intent.resolveActivity(pm); - if (component != null) { - intent.setComponent(component); + public Intent getAssistIntent(Context context) { + return getAssistIntent(context, UserId.myUserId()); + } + + /** + * Gets an intent for launching installed assistant activity, or null if not available. + * @return The assist intent. + * + * @hide + */ + public Intent getAssistIntent(Context context, int userHandle) { + try { + ComponentName comp = mService.getAssistIntent(userHandle); + if (comp == null) { + return null; + } + Intent intent = new Intent(Intent.ACTION_ASSIST); + intent.setComponent(comp); return intent; + } catch (RemoteException re) { + Log.e(TAG, "getAssistIntent() failed: " + re); + return null; } - return null; } } diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java index a1f6735db34e7..b4f5e121d2083 100644 --- a/core/java/android/server/search/SearchManagerService.java +++ b/core/java/android/server/search/SearchManagerService.java @@ -18,6 +18,9 @@ package android.server.search; import com.android.internal.content.PackageMonitor; +import android.app.ActivityManager; +import android.app.ActivityManagerNative; +import android.app.AppGlobals; import android.app.ISearchManager; import android.app.SearchManager; import android.app.SearchableInfo; @@ -27,14 +30,18 @@ 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.UserId; import android.os.UserManager; import android.provider.Settings; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import java.util.List; @@ -207,4 +214,48 @@ public class SearchManagerService extends ISearchManager.Stub { return getSearchables(UserId.getCallingUserId()).getWebSearchActivity(); } + @Override + public ComponentName getAssistIntent(int userHandle) { + try { + if (userHandle != UserId.getCallingUserId()) { + // Requesting a different user, make sure that they have the permission + if (ActivityManager.checkComponentPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Binder.getCallingUid(), -1, true) + == PackageManager.PERMISSION_GRANTED) { + // Translate to the current user id, if caller wasn't aware + if (userHandle == UserId.USER_CURRENT) { + long identity = Binder.clearCallingIdentity(); + userHandle = ActivityManagerNative.getDefault().getCurrentUser().id; + Binder.restoreCallingIdentity(identity); + } + } else { + String msg = "Permission Denial: " + + "Request to getAssistIntent for " + userHandle + + " but is calling from user " + UserId.getCallingUserId() + + "; this requires " + + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; + Slog.w(TAG, msg); + return 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; + } } diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java index 475fb6d20214c..b36e71a00cf39 100644 --- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java @@ -24,6 +24,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.UserId; import android.os.Vibrator; import android.provider.Settings; import android.util.AttributeSet; @@ -73,14 +74,15 @@ public class SearchPanelView extends FrameLayout implements // Close Recent Apps if needed mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL); // Launch Assist - Intent intent = SearchManager.getAssistIntent(mContext); + Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT); if (intent == null) return; try { ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, R.anim.search_launch_enter, R.anim.search_launch_exit, getHandler(), this); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent, opts.toBundle()); + mContext.startActivityAsUser(intent, opts.toBundle(), UserId.USER_CURRENT); } catch (ActivityNotFoundException e) { Slog.w(TAG, "Activity not found for " + intent.getAction()); onAnimationStarted(); @@ -140,7 +142,8 @@ public class SearchPanelView extends FrameLayout implements } private void maybeSwapSearchIcon() { - Intent intent = SearchManager.getAssistIntent(mContext); + Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT); if (intent != null) { ComponentName component = intent.getComponent(); if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component, @@ -277,6 +280,7 @@ public class SearchPanelView extends FrameLayout implements } public boolean isAssistantAvailable() { - return SearchManager.getAssistIntent(mContext) != null; + return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT) != null; } } diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 82181d36359c5..86451721adb6a 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -32,6 +32,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.UserId; import android.os.Vibrator; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -275,7 +276,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen { // Update the search icon with drawable from the search .apk if (!mSearchDisabled) { - Intent intent = SearchManager.getAssistIntent(mContext); + Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT); if (intent != null) { // XXX Hack. We need to substitute the icon here but haven't formalized // the public API. The "_google" metadata will be going away, so @@ -309,7 +311,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen { final int resId = mGlowPadView.getResourceIdForTarget(target); switch (resId) { case com.android.internal.R.drawable.ic_action_assist_generic: - Intent assistIntent = SearchManager.getAssistIntent(mContext); + Intent assistIntent = + ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT); if (assistIntent != null) { launchActivity(assistIntent); } else { @@ -335,6 +339,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen { } } + /** + * Launches the said intent for the current foreground user. + * @param intent + */ private void launchActivity(Intent intent) { intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK @@ -346,7 +354,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen { Log.w(TAG, "can't dismiss keyguard on launch"); } try { - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, UserId.USER_CURRENT); } catch (ActivityNotFoundException e) { Log.w(TAG, "Activity not found for intent + " + intent.getAction()); } @@ -522,7 +530,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen { } else if (disabledBySimState) { Log.v(TAG, "Camera disabled by Sim State"); } - boolean searchActionAvailable = SearchManager.getAssistIntent(mContext) != null; + boolean searchActionAvailable = + ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT) != null; mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent; mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent; mUnlockWidgetMethods.updateResources(); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 8c627a3d6f3b9..769b513559826 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -55,6 +55,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UEventObserver; +import android.os.UserId; import android.os.Vibrator; import android.provider.Settings; @@ -2110,7 +2111,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (searchManager != null) { searchManager.stopSearch(); } - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, UserId.USER_CURRENT); } catch (ActivityNotFoundException e) { Slog.w(TAG, "No activity to handle assist long press action.", e); } @@ -2118,13 +2119,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void launchAssistAction() { sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); - Intent intent = SearchManager.getAssistIntent(mContext); + Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) + .getAssistIntent(mContext, UserId.USER_CURRENT); if (intent != null) { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); try { - mContext.startActivity(intent); + mContext.startActivityAsUser(intent, UserId.USER_CURRENT); } catch (ActivityNotFoundException e) { Slog.w(TAG, "No activity to handle assist action.", e); }