From: Dianne Hackborn Date: Wed, 1 Nov 2017 23:14:26 +0000 (-0700) Subject: Give VoiceInteractionService access to shortcuts. X-Git-Tag: android-x86-9.0-r1~336^2~53^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c160fa4cc4f0ae85b3dd4169a0cd1165c183b0cf;p=android-x86%2Fframeworks-base.git Give VoiceInteractionService access to shortcuts. The shortcut manager now has a set of additional packages that have access, which the voice interaction system service feeds in to. Bug: 68760723 Test: CtsVoiceInteractionTestCases Change-Id: I2a69f83569eb350f405bdd548998570ceef9ea7e --- diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index b94a410b0ba0..05c555685384 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -671,9 +671,13 @@ public class LauncherApps { } /** - * Returns whether the caller can access the shortcut information. + * Returns whether the caller can access the shortcut information. Access is currently + * available to: * - *

Only the default launcher can access the shortcut information. + *

* *

Note when this method returns {@code false}, it may be a temporary situation because * the user is trying a new launcher application. The user may decide to change the default diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java index 7fc25d82870c..dadfaa9f1a66 100644 --- a/core/java/android/content/pm/ShortcutServiceInternal.java +++ b/core/java/android/content/pm/ShortcutServiceInternal.java @@ -73,6 +73,9 @@ public abstract class ShortcutServiceInternal { public abstract boolean hasShortcutHostPermission(int launcherUserId, @NonNull String callingPackage, int callingPid, int callingUid); + public abstract void setShortcutHostPackage(@NonNull String type, @Nullable String packageName, + int userId); + public abstract boolean requestPinAppWidget(@NonNull String callingPackage, @NonNull AppWidgetProviderInfo appWidget, @Nullable Bundle extras, @Nullable IntentSender resultIntent, int userId); diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 1c002aa43512..25e923994789 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -2262,6 +2262,10 @@ public class ShortcutService extends IShortcutService.Stub { final ShortcutUser user = getUserShortcutsLocked(userId); + if (user.hasHostPackage(packageName)) { + return true; + } + // Always trust the cached component. final ComponentName cached = user.getCachedLauncher(); if (cached != null) { @@ -2361,6 +2365,16 @@ public class ShortcutService extends IShortcutService.Stub { } } + public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName, + int userId) { + synchronized (mLock) { + throwIfUserLockedL(userId); + + final ShortcutUser user = getUserShortcutsLocked(userId); + user.setShortcutHostPackage(type, packageName); + } + } + // === House keeping === private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId, @@ -2697,6 +2711,12 @@ public class ShortcutService extends IShortcutService.Stub { } @Override + public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName, + int userId) { + ShortcutService.this.setShortcutHostPackage(type, packageName, userId); + } + + @Override public boolean requestPinAppWidget(@NonNull String callingPackage, @NonNull AppWidgetProviderInfo appWidget, @Nullable Bundle extras, @Nullable IntentSender resultIntent, int userId) { diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java index 48eccd02db64..1efd765b18fa 100644 --- a/services/core/java/com/android/server/pm/ShortcutUser.java +++ b/services/core/java/com/android/server/pm/ShortcutUser.java @@ -23,6 +23,7 @@ import android.content.pm.ShortcutManager; import android.text.TextUtils; import android.text.format.Formatter; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.Slog; @@ -123,6 +124,20 @@ class ShortcutUser { /** In-memory-cached default launcher. */ private ComponentName mCachedLauncher; + /** + * Keep track of additional packages that other parts of the system have said are + * allowed to access shortcuts. The key is the part of the system it came from, + * the value is the package name that has access. We don't persist these because + * at boot all relevant system services will push this data back to us they do their + * normal evaluation of the state of the world. + */ + private final ArrayMap mHostPackages = new ArrayMap<>(); + + /** + * Set of package name values from above. + */ + private final ArraySet mHostPackageSet = new ArraySet<>(); + private String mKnownLocales; private long mLastAppScanTime; @@ -467,6 +482,23 @@ class ShortcutUser { return mCachedLauncher; } + public void setShortcutHostPackage(@NonNull String type, @Nullable String packageName) { + if (packageName != null) { + mHostPackages.put(type, packageName); + } else { + mHostPackages.remove(type); + } + + mHostPackageSet.clear(); + for (int i = 0; i < mHostPackages.size(); i++) { + mHostPackageSet.add(mHostPackages.valueAt(i)); + } + } + + public boolean hasHostPackage(@NonNull String packageName) { + return mHostPackageSet.contains(packageName); + } + public void resetThrottling() { for (int i = mPackages.size() - 1; i >= 0; i--) { mPackages.valueAt(i).resetThrottling(); @@ -555,6 +587,18 @@ class ShortcutUser { pw.print("Last known launcher: "); pw.print(mLastKnownLauncher); pw.println(); + + if (mHostPackages.size() > 0) { + pw.print(prefix); + pw.println("Host packages:"); + for (int i = 0; i < mHostPackages.size(); i++) { + pw.print(prefix); + pw.print(" "); + pw.print(mHostPackages.keyAt(i)); + pw.print(": "); + pw.println(mHostPackages.valueAt(i)); + } + } } for (int i = 0; i < mLaunchers.size(); i++) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 1569ac32128b..44e5314ff7dd 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.ShortcutServiceInternal; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.soundtrigger.IRecognitionStatusCallback; @@ -44,6 +45,7 @@ import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; @@ -53,6 +55,7 @@ import android.service.voice.VoiceInteractionServiceInfo; import android.service.voice.VoiceInteractionSession; import android.speech.RecognitionService; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import android.util.Slog; @@ -63,6 +66,7 @@ import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; +import com.android.internal.util.Preconditions; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; @@ -84,7 +88,9 @@ public class VoiceInteractionManagerService extends SystemService { final ContentResolver mResolver; final DatabaseHelper mDbHelper; final ActivityManagerInternal mAmInternal; - final TreeSet mLoadedKeyphraseIds; + final UserManager mUserManager; + final ArraySet mLoadedKeyphraseIds = new ArraySet<>(); + ShortcutServiceInternal mShortcutServiceInternal; SoundTriggerInternal mSoundTriggerInternal; private final RemoteCallbackList @@ -96,8 +102,10 @@ public class VoiceInteractionManagerService extends SystemService { mResolver = context.getContentResolver(); mDbHelper = new DatabaseHelper(context); mServiceStub = new VoiceInteractionManagerServiceStub(); - mAmInternal = LocalServices.getService(ActivityManagerInternal.class); - mLoadedKeyphraseIds = new TreeSet(); + mAmInternal = Preconditions.checkNotNull( + LocalServices.getService(ActivityManagerInternal.class)); + mUserManager = Preconditions.checkNotNull( + context.getSystemService(UserManager.class)); PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); @@ -124,6 +132,8 @@ public class VoiceInteractionManagerService extends SystemService { @Override public void onBootPhase(int phase) { if (PHASE_SYSTEM_SERVICES_READY == phase) { + mShortcutServiceInternal = Preconditions.checkNotNull( + LocalServices.getService(ShortcutServiceInternal.class)); mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { mServiceStub.systemRunning(isSafeMode()); @@ -180,6 +190,7 @@ public class VoiceInteractionManagerService extends SystemService { private boolean mSafeMode; private int mCurUser; + private boolean mCurUserUnlocked; private final boolean mEnableService; VoiceInteractionManagerServiceStub() { @@ -381,6 +392,7 @@ public class VoiceInteractionManagerService extends SystemService { public void switchUser(int userHandle) { synchronized (this) { mCurUser = userHandle; + mCurUserUnlocked = false; switchImplementationIfNeededLocked(false); } } @@ -409,13 +421,24 @@ public class VoiceInteractionManagerService extends SystemService { } } + final boolean hasComponent = serviceComponent != null && serviceInfo != null; + + if (mUserManager.isUserUnlockingOrUnlocked(mCurUser)) { + if (hasComponent) { + mShortcutServiceInternal.setShortcutHostPackage(TAG, + serviceComponent.getPackageName(), mCurUser); + } else { + mShortcutServiceInternal.setShortcutHostPackage(TAG, null, mCurUser); + } + } + if (force || mImpl == null || mImpl.mUser != mCurUser || !mImpl.mComponent.equals(serviceComponent)) { unloadAllKeyphraseModels(); if (mImpl != null) { mImpl.shutdownLocked(); } - if (serviceComponent != null && serviceInfo != null) { + if (hasComponent) { mImpl = new VoiceInteractionManagerServiceImpl(mContext, UiThread.getHandler(), this, mCurUser, serviceComponent); mImpl.startLocked(); @@ -953,12 +976,14 @@ public class VoiceInteractionManagerService extends SystemService { } private synchronized void unloadAllKeyphraseModels() { - for (int keyphraseId : mLoadedKeyphraseIds) { + for (int i = 0; i < mLoadedKeyphraseIds.size(); i++) { final long caller = Binder.clearCallingIdentity(); try { - int status = mSoundTriggerInternal.unloadKeyphraseModel(keyphraseId); + int status = mSoundTriggerInternal.unloadKeyphraseModel( + mLoadedKeyphraseIds.valueAt(i)); if (status != SoundTriggerInternal.STATUS_OK) { - Slog.w(TAG, "Failed to unload keyphrase " + keyphraseId + ":" + status); + Slog.w(TAG, "Failed to unload keyphrase " + mLoadedKeyphraseIds.valueAt(i) + + ":" + status); } } finally { Binder.restoreCallingIdentity(caller);