Merge "Re-add partial hotword indicator exemption" into udc-qpr-dev

This commit is contained in:
Felix Oghina
2023-07-24 16:07:14 +00:00
committed by Android (Google) Code Review
3 changed files with 56 additions and 19 deletions

View File

@@ -27,6 +27,7 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPH
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH;
import android.app.AppOpsManager;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.ChangeId;
@@ -548,13 +549,15 @@ final class HotwordDetectionConnection {
static final class SoundTriggerCallback extends IRecognitionStatusCallback.Stub {
private final HotwordDetectionConnection mHotwordDetectionConnection;
private final IHotwordRecognitionStatusCallback mExternalCallback;
private final int mVoiceInteractionServiceUid;
private final Identity mVoiceInteractorIdentity;
private final Context mContext;
SoundTriggerCallback(IHotwordRecognitionStatusCallback callback,
HotwordDetectionConnection connection, int uid) {
SoundTriggerCallback(Context context, IHotwordRecognitionStatusCallback callback,
HotwordDetectionConnection connection, Identity voiceInteractorIdentity) {
mContext = context;
mHotwordDetectionConnection = connection;
mExternalCallback = callback;
mVoiceInteractionServiceUid = uid;
mVoiceInteractorIdentity = voiceInteractorIdentity;
}
@Override
@@ -568,15 +571,30 @@ final class HotwordDetectionConnection {
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP,
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER,
mVoiceInteractionServiceUid);
mVoiceInteractorIdentity.uid);
mHotwordDetectionConnection.detectFromDspSource(
recognitionEvent, mExternalCallback);
} else {
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR,
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER,
mVoiceInteractionServiceUid);
mExternalCallback.onKeyphraseDetected(recognitionEvent, null);
// We have to attribute ops here, since we configure all st clients as trusted to
// enable a partial exemption.
// TODO (b/292012931) remove once trusted uniformly required.
int result = mContext.getSystemService(AppOpsManager.class)
.noteOpNoThrow(AppOpsManager.OP_RECORD_AUDIO_HOTWORD,
mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
mVoiceInteractorIdentity.attributionTag,
"Non-HDS keyphrase recognition to VoiceInteractionService");
if (result != AppOpsManager.MODE_ALLOWED) {
Slog.w(TAG, "onKeyphraseDetected suppressed, permission check returned: "
+ result);
mExternalCallback.onRecognitionPaused();
} else {
HotwordMetricsLogger.writeKeyphraseTriggerEvent(
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR,
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER,
mVoiceInteractorIdentity.uid);
mExternalCallback.onKeyphraseDetected(recognitionEvent, null);
}
}
}

View File

@@ -104,6 +104,7 @@ import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.policy.AppOpsPolicy;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -336,6 +337,9 @@ public class VoiceInteractionManagerService extends SystemService {
/** The start value of showSessionId */
private static final int SHOW_SESSION_START_ID = 0;
private final boolean IS_HDS_REQUIRED = AppOpsPolicy.isHotwordDetectionServiceRequired(
mContext.getPackageManager());
@GuardedBy("this")
private int mShowSessionId = SHOW_SESSION_START_ID;
@@ -393,8 +397,14 @@ public class VoiceInteractionManagerService extends SystemService {
}
try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
originatorIdentity)) {
if (!IS_HDS_REQUIRED) {
// For devices which still have hotword exemption, any client (not just HDS
// clients) are trusted.
// TODO (b/292012931) remove once trusted uniformly required.
forHotwordDetectionService = true;
}
return new SoundTriggerSession(mSoundTriggerInternal.attach(client,
moduleProperties, forHotwordDetectionService));
moduleProperties, forHotwordDetectionService), originatorIdentity);
}
}
@@ -1674,10 +1684,13 @@ public class VoiceInteractionManagerService extends SystemService {
final SoundTriggerInternal.Session mSession;
private IHotwordRecognitionStatusCallback mSessionExternalCallback;
private IRecognitionStatusCallback mSessionInternalCallback;
private final Identity mVoiceInteractorIdentity;
SoundTriggerSession(
SoundTriggerInternal.Session session) {
SoundTriggerInternal.Session session,
Identity voiceInteractorIdentity) {
mSession = session;
mVoiceInteractorIdentity = voiceInteractorIdentity;
}
@Override
@@ -1731,7 +1744,8 @@ public class VoiceInteractionManagerService extends SystemService {
if (mSessionExternalCallback == null
|| mSessionInternalCallback == null
|| callback.asBinder() != mSessionExternalCallback.asBinder()) {
mSessionInternalCallback = createSoundTriggerCallbackLocked(callback);
mSessionInternalCallback = createSoundTriggerCallbackLocked(callback,
mVoiceInteractorIdentity);
mSessionExternalCallback = callback;
}
}
@@ -1752,7 +1766,8 @@ public class VoiceInteractionManagerService extends SystemService {
if (mSessionExternalCallback == null
|| mSessionInternalCallback == null
|| callback.asBinder() != mSessionExternalCallback.asBinder()) {
soundTriggerCallback = createSoundTriggerCallbackLocked(callback);
soundTriggerCallback = createSoundTriggerCallbackLocked(callback,
mVoiceInteractorIdentity);
Slog.w(TAG, "stopRecognition() called with a different callback than"
+ "startRecognition()");
} else {
@@ -2090,6 +2105,7 @@ public class VoiceInteractionManagerService extends SystemService {
pw.println(" mTemporarilyDisabled: " + mTemporarilyDisabled);
pw.println(" mCurUser: " + mCurUser);
pw.println(" mCurUserSupported: " + mCurUserSupported);
pw.println(" mIsHdsRequired: " + IS_HDS_REQUIRED);
dumpSupportedUsers(pw, " ");
mDbHelper.dump(pw);
if (mImpl == null) {
@@ -2165,11 +2181,13 @@ public class VoiceInteractionManagerService extends SystemService {
}
private IRecognitionStatusCallback createSoundTriggerCallbackLocked(
IHotwordRecognitionStatusCallback callback) {
IHotwordRecognitionStatusCallback callback,
Identity voiceInteractorIdentity) {
if (mImpl == null) {
return null;
}
return mImpl.createSoundTriggerCallbackLocked(callback);
return mImpl.createSoundTriggerCallbackLocked(mContext, callback,
voiceInteractorIdentity);
}
class RoleObserver implements OnRoleHoldersChangedListener {

View File

@@ -877,12 +877,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
public IRecognitionStatusCallback createSoundTriggerCallbackLocked(
IHotwordRecognitionStatusCallback callback) {
Context context, IHotwordRecognitionStatusCallback callback,
Identity voiceInteractorIdentity) {
if (DEBUG) {
Slog.d(TAG, "createSoundTriggerCallbackLocked");
}
return new HotwordDetectionConnection.SoundTriggerCallback(callback,
mHotwordDetectionConnection, mInfo.getServiceInfo().applicationInfo.uid);
return new HotwordDetectionConnection.SoundTriggerCallback(context, callback,
mHotwordDetectionConnection, voiceInteractorIdentity);
}
private static ServiceInfo getServiceInfoLocked(@NonNull ComponentName componentName,