Merge "Update the proximity feature to return proximity levels" into tm-qpr-dev

This commit is contained in:
Daniel Kim
2022-11-16 16:42:44 +00:00
committed by Android (Google) Code Review
3 changed files with 133 additions and 38 deletions

View File

@@ -32,6 +32,8 @@ import com.android.internal.R;
import com.android.internal.util.DataClass;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -100,14 +102,42 @@ public final class HotwordDetectedResult implements Parcelable {
private static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE = 63;
/**
* The bundle key for proximity value
* The bundle key for proximity
*
* TODO(b/238896013): Move the proximity logic out of bundle to proper API.
*/
private static final String EXTRA_PROXIMITY =
"android.service.voice.extra.PROXIMITY";
/**
* Users’ proximity is unknown (proximity sensing was inconclusive and is unsupported).
*
* @hide
*/
public static final String EXTRA_PROXIMITY_METERS =
"android.service.voice.extra.PROXIMITY_METERS";
public static final int PROXIMITY_UNKNOWN = -1;
/**
* Proximity value that represents that the object is near.
*
* @hide
*/
public static final int PROXIMITY_NEAR = 1;
/**
* Proximity value that represents that the object is far.
*
* @hide
*/
public static final int PROXIMITY_FAR = 2;
/** @hide */
@IntDef(prefix = {"PROXIMITY"}, value = {
PROXIMITY_UNKNOWN,
PROXIMITY_NEAR,
PROXIMITY_FAR
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProximityValue {}
/** Confidence level in the trigger outcome. */
@HotwordConfidenceLevelValue
@@ -223,12 +253,14 @@ public final class HotwordDetectedResult implements Parcelable {
* versions of Android.
*
* <p>After the trigger happens, a special case of proximity-related extra, with the key of
* 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
* will be stored to enable proximity logic. The proximity meters is provided by the system,
* on devices that support detecting proximity of nearby users, to help disambiguate which
* nearby device should respond. When the proximity is unknown, the proximity value will not
* be stored. This mapping will be excluded from the max bundle size calculation because this
* mapping is included after the result is returned from the hotword detector service.
* 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
* will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
* indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
* proximity. The proximity value is provided by the system, on devices that support detecting
* proximity of nearby users, to help disambiguate which nearby device should respond. When the
* proximity is unknown, the proximity value will not be stored. This mapping will be excluded
* from the max bundle size calculation because this mapping is included after the result is
* returned from the hotword detector service.
*
* <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
* that can be used to communicate with other processes.
@@ -351,16 +383,16 @@ public final class HotwordDetectedResult implements Parcelable {
// Remove the proximity key from the bundle before checking the bundle size. The
// proximity value is added after the privileged module and can avoid the
// maxBundleSize limitation.
if (mExtras.containsKey(EXTRA_PROXIMITY_METERS)) {
double proximityMeters = mExtras.getDouble(EXTRA_PROXIMITY_METERS);
mExtras.remove(EXTRA_PROXIMITY_METERS);
if (mExtras.containsKey(EXTRA_PROXIMITY)) {
int proximityValue = mExtras.getInt(EXTRA_PROXIMITY);
mExtras.remove(EXTRA_PROXIMITY);
// Skip checking parcelable size if the new bundle size is 0. Newly empty bundle
// has parcelable size of 4, but the default bundle has parcelable size of 0.
if (mExtras.size() > 0) {
Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
getMaxBundleSize(), "extras");
}
mExtras.putDouble(EXTRA_PROXIMITY_METERS, proximityMeters);
mExtras.putInt(EXTRA_PROXIMITY, proximityValue);
} else {
Preconditions.checkArgumentInRange(getParcelableSize(mExtras), 0,
getMaxBundleSize(), "extras");
@@ -416,6 +448,42 @@ public final class HotwordDetectedResult implements Parcelable {
.setExtras(mExtras);
}
/**
* Adds proximity level, either near or far, that is mapped for the given distance into
* the bundle. The proximity value is provided by the system, on devices that support detecting
* proximity of nearby users, to help disambiguate which nearby device should respond.
* This mapping will be excluded from the max bundle size calculation because this mapping is
* included after the result is returned from the hotword detector service. The value will not
* be included if the proximity was unknown.
*
* @hide
*/
public void setProximity(double distance) {
int proximityLevel = convertToProximityLevel(distance);
if (proximityLevel != PROXIMITY_UNKNOWN) {
mExtras.putInt(EXTRA_PROXIMITY, proximityLevel);
}
}
/**
* Mapping of the proximity distance (meters) to proximity values, unknown, near, and far.
* Currently, this mapping is handled by HotwordDetectedResult because it handles just
* HotwordDetectionConnection which we know the mapping of. However, the mapping will need to
* move to a more centralized place once there are more clients.
*
* TODO(b/258531144): Move the proximity mapping to a central location
*/
@ProximityValue
private int convertToProximityLevel(double distance) {
if (distance < 0) {
return PROXIMITY_UNKNOWN;
} else if (distance <= 3) {
return PROXIMITY_NEAR;
} else {
return PROXIMITY_FAR;
}
}
// Code below generated by codegen v1.0.23.
@@ -441,7 +509,7 @@ public final class HotwordDetectedResult implements Parcelable {
CONFIDENCE_LEVEL_HIGH,
CONFIDENCE_LEVEL_VERY_HIGH
})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
public @interface ConfidenceLevel {}
@@ -472,7 +540,7 @@ public final class HotwordDetectedResult implements Parcelable {
LIMIT_HOTWORD_OFFSET_MAX_VALUE,
LIMIT_AUDIO_CHANNEL_MAX_VALUE
})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
/* package-private */ @interface Limit {}
@@ -488,6 +556,30 @@ public final class HotwordDetectedResult implements Parcelable {
}
}
/** @hide */
@IntDef(prefix = "PROXIMITY_", value = {
PROXIMITY_UNKNOWN,
PROXIMITY_NEAR,
PROXIMITY_FAR
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
public @interface Proximity {}
/** @hide */
@DataClass.Generated.Member
public static String proximityToString(@Proximity int value) {
switch (value) {
case PROXIMITY_UNKNOWN:
return "PROXIMITY_UNKNOWN";
case PROXIMITY_NEAR:
return "PROXIMITY_NEAR";
case PROXIMITY_FAR:
return "PROXIMITY_FAR";
default: return Integer.toHexString(value);
}
}
@DataClass.Generated.Member
/* package-private */ HotwordDetectedResult(
@HotwordConfidenceLevelValue int confidenceLevel,
@@ -614,12 +706,14 @@ public final class HotwordDetectedResult implements Parcelable {
* versions of Android.
*
* <p>After the trigger happens, a special case of proximity-related extra, with the key of
* 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
* will be stored to enable proximity logic. The proximity meters is provided by the system,
* on devices that support detecting proximity of nearby users, to help disambiguate which
* nearby device should respond. When the proximity is unknown, the proximity value will not
* be stored. This mapping will be excluded from the max bundle size calculation because this
* mapping is included after the result is returned from the hotword detector service.
* 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
* will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
* indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
* proximity. The proximity value is provided by the system, on devices that support detecting
* proximity of nearby users, to help disambiguate which nearby device should respond. When the
* proximity is unknown, the proximity value will not be stored. This mapping will be excluded
* from the max bundle size calculation because this mapping is included after the result is
* returned from the hotword detector service.
*
* <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
* that can be used to communicate with other processes.
@@ -932,12 +1026,14 @@ public final class HotwordDetectedResult implements Parcelable {
* versions of Android.
*
* <p>After the trigger happens, a special case of proximity-related extra, with the key of
* 'android.service.voice.extra.PROXIMITY_METERS' and the value of distance in meters (double),
* will be stored to enable proximity logic. The proximity meters is provided by the system,
* on devices that support detecting proximity of nearby users, to help disambiguate which
* nearby device should respond. When the proximity is unknown, the proximity value will not
* be stored. This mapping will be excluded from the max bundle size calculation because this
* mapping is included after the result is returned from the hotword detector service.
* 'android.service.voice.extra.PROXIMITY_VALUE' and the value of proximity value (integer)
* will be stored to enable proximity logic. {@link HotwordDetectedResult#PROXIMITY_NEAR} will
* indicate 'NEAR' proximity and {@link HotwordDetectedResult#PROXIMITY_FAR} will indicate 'FAR'
* proximity. The proximity value is provided by the system, on devices that support detecting
* proximity of nearby users, to help disambiguate which nearby device should respond. When the
* proximity is unknown, the proximity value will not be stored. This mapping will be excluded
* from the max bundle size calculation because this mapping is included after the result is
* returned from the hotword detector service.
*
* <p>This is a PersistableBundle so it doesn't allow any remotable objects or other contents
* that can be used to communicate with other processes.
@@ -1012,10 +1108,10 @@ public final class HotwordDetectedResult implements Parcelable {
}
@DataClass.Generated(
time = 1668466781144L,
time = 1668528946960L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\npublic static final java.lang.String EXTRA_PROXIMITY_METERS\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final java.lang.String EXTRA_PROXIMITY\npublic static final int PROXIMITY_UNKNOWN\npublic static final int PROXIMITY_NEAR\npublic static final int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic android.service.voice.HotwordDetectedResult.Builder buildUpon()\npublic void setProximity(double)\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.compat.annotation.UnsupportedAppUsage @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}

View File

@@ -92,7 +92,7 @@ public abstract class HotwordDetectionService extends Service {
* TODO(b/247920386): Add TestApi annotation
* @hide
*/
public static final boolean ENABLE_PROXIMITY_RESULT = false;
public static final boolean ENABLE_PROXIMITY_RESULT = true;
/**
* Indicates that the updated status is successful.

View File

@@ -19,7 +19,6 @@ package com.android.server.voiceinteraction;
import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.service.attention.AttentionService.PROXIMITY_UNKNOWN;
import static android.service.voice.HotwordDetectedResult.EXTRA_PROXIMITY_METERS;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_EXTERNAL;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPHONE;
import static android.service.voice.HotwordDetectionService.ENABLE_PROXIMITY_RESULT;
@@ -193,7 +192,7 @@ final class HotwordDetectionConnection {
@Nullable AttentionManagerInternal mAttentionManagerInternal = null;
final AttentionManagerInternal.ProximityUpdateCallbackInternal mProximityCallbackInternal =
this::setProximityMeters;
this::setProximityValue;
volatile HotwordDetectionServiceIdentity mIdentity;
@@ -488,7 +487,7 @@ final class HotwordDetectionConnection {
mSoftwareCallback.onError();
return;
}
saveProximityMetersToBundle(result);
saveProximityValueToBundle(result);
HotwordDetectedResult newResult;
try {
newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result);
@@ -599,7 +598,7 @@ final class HotwordDetectionConnection {
externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
return;
}
saveProximityMetersToBundle(result);
saveProximityValueToBundle(result);
externalCallback.onKeyphraseDetected(recognitionEvent, result);
if (result != null) {
Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result)
@@ -680,7 +679,7 @@ final class HotwordDetectionConnection {
externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
return;
}
saveProximityMetersToBundle(result);
saveProximityValueToBundle(result);
HotwordDetectedResult newResult;
try {
newResult = mHotwordAudioStreamManager.startCopyingAudioStreams(result);
@@ -1244,15 +1243,15 @@ final class HotwordDetectionConnection {
});
}
private void saveProximityMetersToBundle(HotwordDetectedResult result) {
private void saveProximityValueToBundle(HotwordDetectedResult result) {
synchronized (mLock) {
if (result != null && mProximityMeters != PROXIMITY_UNKNOWN) {
result.getExtras().putDouble(EXTRA_PROXIMITY_METERS, mProximityMeters);
result.setProximity(mProximityMeters);
}
}
}
private void setProximityMeters(double proximityMeters) {
private void setProximityValue(double proximityMeters) {
synchronized (mLock) {
mProximityMeters = proximityMeters;
}