Merge "Set assistant as a role"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a0f377fbe8
@@ -1053,6 +1053,7 @@ package android.app.role {
|
||||
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
|
||||
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
|
||||
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
|
||||
field public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT";
|
||||
}
|
||||
|
||||
public interface RoleManagerCallback {
|
||||
|
||||
@@ -14,6 +14,10 @@ package android {
|
||||
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
|
||||
}
|
||||
|
||||
public static final class R.array {
|
||||
field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.animation {
|
||||
@@ -332,6 +336,7 @@ package android.app.role {
|
||||
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
|
||||
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
|
||||
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.role.RoleManagerCallback);
|
||||
field public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT";
|
||||
}
|
||||
|
||||
public interface RoleManagerCallback {
|
||||
|
||||
@@ -171,6 +171,15 @@ public final class RoleManager {
|
||||
*/
|
||||
public static final String ROLE_CALL_COMPANION_APP = "android.app.role.CALL_COMPANION_APP";
|
||||
|
||||
/**
|
||||
* The name of the assistant app role.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@TestApi
|
||||
public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT";
|
||||
|
||||
/**
|
||||
* The action used to request user approval of a role for an application.
|
||||
*
|
||||
|
||||
@@ -7812,6 +7812,9 @@ public final class Settings {
|
||||
* or an activity that handles ACTION_ASSIST, or empty which means using the default
|
||||
* handling.
|
||||
*
|
||||
* <p>This should be set indirectly by setting the {@link
|
||||
* android.app.role.RoleManager#ROLE_ASSISTANT assistant role}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
|
||||
@@ -17,13 +17,10 @@
|
||||
package com.android.internal.app;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.SearchManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -31,8 +28,6 @@ import android.os.ServiceManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -44,14 +39,6 @@ public class AssistUtils {
|
||||
|
||||
private static final String TAG = "AssistUtils";
|
||||
|
||||
/**
|
||||
* Sentinel value for "no default assistant specified."
|
||||
*
|
||||
* Empty string is already used to represent an explicit setting of No Assistant. null cannot
|
||||
* be used because we can't represent a null value in XML.
|
||||
*/
|
||||
private static final String UNSET = "#+UNSET";
|
||||
|
||||
private final Context mContext;
|
||||
private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
|
||||
|
||||
@@ -186,37 +173,9 @@ public class AssistUtils {
|
||||
Settings.Secure.ASSISTANT, userId);
|
||||
if (setting != null) {
|
||||
return ComponentName.unflattenFromString(setting);
|
||||
}
|
||||
|
||||
final String defaultSetting = mContext.getResources().getString(
|
||||
R.string.config_defaultAssistantComponentName);
|
||||
if (defaultSetting != null && !defaultSetting.equals(UNSET)) {
|
||||
return ComponentName.unflattenFromString(defaultSetting);
|
||||
}
|
||||
|
||||
// Fallback to keep backward compatible behavior when there is no user setting.
|
||||
if (activeServiceSupportsAssistGesture()) {
|
||||
return getActiveServiceComponentName();
|
||||
}
|
||||
|
||||
if (UNSET.equals(defaultSetting)) {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
final SearchManager searchManager =
|
||||
(SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
|
||||
if (searchManager == null) {
|
||||
return null;
|
||||
}
|
||||
final Intent intent = searchManager.getAssistIntent(false);
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
|
||||
userId);
|
||||
if (info != null) {
|
||||
return new ComponentName(info.activityInfo.applicationInfo.packageName,
|
||||
info.activityInfo.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) {
|
||||
|
||||
@@ -3729,9 +3729,6 @@
|
||||
<!-- Whether or not the "SMS app service" feature is enabled -->
|
||||
<bool name="config_useSmsAppService">true</bool>
|
||||
|
||||
<!-- Component name for default assistant on this device -->
|
||||
<string name="config_defaultAssistantComponentName">#+UNSET</string>
|
||||
|
||||
<!-- Class name for the InputEvent compatibility processor override.
|
||||
Empty string means use the default compatibility processor
|
||||
(android.view.InputEventCompatProcessor). -->
|
||||
|
||||
@@ -2988,7 +2988,7 @@
|
||||
</public-group>
|
||||
|
||||
<public-group type="array" first-id="0x01070006">
|
||||
<!-- @hide @SystemApi -->
|
||||
<!-- @hide @TestApi @SystemApi -->
|
||||
<public name="config_defaultRoleHolders" />
|
||||
</public-group>
|
||||
|
||||
|
||||
@@ -3528,8 +3528,6 @@
|
||||
|
||||
<java-symbol type="bool" name="config_useSmsAppService" />
|
||||
|
||||
<java-symbol type="string" name="config_defaultAssistantComponentName" />
|
||||
|
||||
<java-symbol type="id" name="transition_overlay_view_tag" />
|
||||
|
||||
<java-symbol type="dimen" name="rounded_corner_radius" />
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.policy.role;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Debug;
|
||||
import android.provider.Settings;
|
||||
@@ -90,6 +91,17 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder
|
||||
|
||||
return CollectionUtils.singletonOrEmpty(result);
|
||||
}
|
||||
case RoleManager.ROLE_ASSISTANT: {
|
||||
String legacyAssistant = Settings.Secure.getStringForUser(
|
||||
mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId);
|
||||
|
||||
if (legacyAssistant == null || legacyAssistant.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.singletonList(
|
||||
ComponentName.unflattenFromString(legacyAssistant).getPackageName());
|
||||
}
|
||||
}
|
||||
default: {
|
||||
Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName);
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -198,6 +198,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
|
||||
// Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
|
||||
// for a given role before adding a migration statement for it here
|
||||
migrateRoleIfNecessary(RoleManager.ROLE_SMS, userId);
|
||||
migrateRoleIfNecessary(RoleManager.ROLE_ASSISTANT, userId);
|
||||
|
||||
// Some vital packages state has changed since last role grant
|
||||
// Run grants again
|
||||
|
||||
@@ -1561,6 +1561,12 @@ public final class SystemServer {
|
||||
traceEnd();
|
||||
}
|
||||
|
||||
// Grants default permissions and defines roles
|
||||
traceBeginAndSlog("StartRoleManagerService");
|
||||
mSystemServiceManager.startService(new RoleManagerService(
|
||||
mSystemContext, new LegacyRoleResolutionPolicy(mSystemContext)));
|
||||
traceEnd();
|
||||
|
||||
// We need to always start this service, regardless of whether the
|
||||
// FEATURE_VOICE_RECOGNIZERS feature is set, because it needs to take care
|
||||
// of initializing various settings. It will internally modify its behavior
|
||||
@@ -2011,12 +2017,6 @@ public final class SystemServer {
|
||||
}
|
||||
traceEnd();
|
||||
|
||||
// Grants default permissions and defines roles
|
||||
traceBeginAndSlog("StartRoleManagerService");
|
||||
mSystemServiceManager.startService(new RoleManagerService(
|
||||
mSystemContext, new LegacyRoleResolutionPolicy(mSystemContext)));
|
||||
traceEnd();
|
||||
|
||||
// No dependency on Webview preparation in system server. But this should
|
||||
// be completed before allowing 3rd party
|
||||
final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
|
||||
|
||||
@@ -17,13 +17,18 @@
|
||||
package com.android.server.voiceinteraction;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.role.OnRoleHoldersChangedListener;
|
||||
import android.app.role.RoleManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -78,6 +83,7 @@ import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* SystemService that publishes an IVoiceInteractionManagerService.
|
||||
@@ -200,6 +206,7 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
|
||||
VoiceInteractionManagerServiceStub() {
|
||||
mEnableService = shouldEnableService(mContext);
|
||||
new RoleObserver(mContext.getMainExecutor());
|
||||
}
|
||||
|
||||
// TODO: VI Make sure the caller is the current user or profile
|
||||
@@ -1268,6 +1275,106 @@ public class VoiceInteractionManagerService extends SystemService {
|
||||
getActiveServiceComponentName());
|
||||
}
|
||||
|
||||
class RoleObserver implements OnRoleHoldersChangedListener {
|
||||
private PackageManager mPm = mContext.getPackageManager();
|
||||
private RoleManager mRm = mContext.getSystemService(RoleManager.class);
|
||||
|
||||
RoleObserver(@NonNull @CallbackExecutor Executor executor) {
|
||||
mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
|
||||
}
|
||||
|
||||
private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
|
||||
ResolveInfo resolveInfo = mPm.resolveServiceAsUser(
|
||||
new Intent(RecognitionService.SERVICE_INTERFACE),
|
||||
PackageManager.GET_META_DATA, user.getIdentifier());
|
||||
|
||||
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
|
||||
Log.w(TAG, "Unable to resolve default voice recognition service.");
|
||||
return "";
|
||||
}
|
||||
|
||||
return new ComponentName(resolveInfo.serviceInfo.packageName,
|
||||
resolveInfo.serviceInfo.name).flattenToShortString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the assistant-role holder into settings. The rest of the system uses the
|
||||
* settings.
|
||||
*
|
||||
* @param roleName the name of the role whose holders are changed
|
||||
* @param user the user for this role holder change
|
||||
*/
|
||||
@Override
|
||||
public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
|
||||
if (!roleName.equals(RoleManager.ROLE_ASSISTANT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user);
|
||||
|
||||
if (roleHolders.isEmpty()) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, getDefaultRecognizer(user));
|
||||
} else {
|
||||
// Assistant is singleton role
|
||||
String pkg = roleHolders.get(0);
|
||||
|
||||
// Try to set role holder as VoiceInteractionService
|
||||
List<ResolveInfo> services = mPm.queryIntentServicesAsUser(
|
||||
new Intent(VoiceInteractionService.SERVICE_INTERFACE).setPackage(pkg),
|
||||
PackageManager.GET_META_DATA, user.getIdentifier());
|
||||
|
||||
for (ResolveInfo resolveInfo : services) {
|
||||
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
|
||||
|
||||
VoiceInteractionServiceInfo voiceInteractionServiceInfo =
|
||||
new VoiceInteractionServiceInfo(mPm, serviceInfo);
|
||||
if (!voiceInteractionServiceInfo.getSupportsAssist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String serviceComponentName = serviceInfo.getComponentName()
|
||||
.flattenToShortString();
|
||||
|
||||
String serviceRecognizerName = new ComponentName(pkg,
|
||||
voiceInteractionServiceInfo.getRecognitionService())
|
||||
.flattenToShortString();
|
||||
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.ASSISTANT, serviceComponentName);
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, serviceComponentName);
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE, serviceRecognizerName);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If no service could be found try to set assist activity
|
||||
final List<ResolveInfo> activities = mPm.queryIntentActivitiesAsUser(
|
||||
new Intent(Intent.ACTION_ASSIST).setPackage(pkg),
|
||||
PackageManager.MATCH_DEFAULT_ONLY, user.getIdentifier());
|
||||
|
||||
for (ResolveInfo resolveInfo : activities) {
|
||||
ActivityInfo activityInfo = resolveInfo.activityInfo;
|
||||
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.ASSISTANT,
|
||||
activityInfo.getComponentName().flattenToShortString());
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_INTERACTION_SERVICE, "");
|
||||
Settings.Secure.putString(getContext().getContentResolver(),
|
||||
Settings.Secure.VOICE_RECOGNITION_SERVICE,
|
||||
getDefaultRecognizer(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsObserver extends ContentObserver {
|
||||
SettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
|
||||
Reference in New Issue
Block a user