Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18e3eb81 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Add SoundTriggerDetectionService

The service is meant to replace the PendingIntent based API. Once all
users of the PendingIntent based API switched the PendingIntent based API
will be removed.

To have as little as possible impact on the whole SoundTrigger framework
the RemoteSoundTriggerDetectionService class implements the same
interface as the PendingIntent based class. Hence the exising code has
very little change. Further once the old code can be removed the amount
of changed (and added) code is limited.

The RemoteSoundTriggerDetectionService -> SoundTriggerDetectionService
is a vanilla as possible service implementation. The special behaviors
are:
- The system holds a wakelock while service operations are in progress
and the service is bound as foreground. Hence the service can e.g.
listen to the microphone.
- Service operations have a certain amount of time they are allowed to
run. Once every operation is either finished or the the operation
exceeded the allotted time, the system calls onStopOperation for each
still pending operation. This is a similar model as for the commonly
used JobService.
  Please note that if the time allowed for an operation is 15s and
op1 was run as 0si, and op1 was run at 5s, the service is allowed to run
until 20s. Hence _both_ onStopOperations will happen at 20s. This is
done for ease of implementation but should not give the service more
power than calling onStopOperation exactly 15s after each operation is
triggered.
- If an operation is done before the allotted time is reached, the
service can declare the operation as finished manually by calling
onOperationFinished. This is a call back into the system, hence a
'client' binder is sent to the service. If the operation is finished
by calling this method onStopOperation will not be called.
- As the service instance might be killed and restored between
operations we add a opaque bundle 'params' to each operations. The users
of the API can use this to send data from the start command to the
operations. It can also just be set to null. The params are not meant to
store changing state in between operations. Such state needs to be
persisted using the regular methods (e.g. write it to disk)
- A service can be used for multiple recognition sessions. Each
recognition is uniquelity defined by its sound model UUID. Hence each
operation gets at least tree arguments: Operation ID, sound mode UUID, params
- As a small optimization the params are cached inside of the service
instance.

The time allowed for each operation is in a @SystemAPI global setting,
so the service can make sure it finishes the operations before they are
stopped. It might take some time to deliver the operations via the
binder, hence it is not recommended to try to use every last ms of
allotted time.

Test: atest SoundTriggerDetectionServiceTest (added in separate CL)
      atest android.provider.SettingsBackupTest
Change-Id: I47f813b7a5138a6f24732197813a605d29f85a93
Fixes: 73829108
parent a5fd0294
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -462,6 +462,8 @@ java_library {
        "media/java/android/media/session/ISessionController.aidl",
        "media/java/android/media/session/ISessionControllerCallback.aidl",
        "media/java/android/media/session/ISessionManager.aidl",
        "media/java/android/media/soundtrigger/ISoundTriggerDetectionService.aidl",
        "media/java/android/media/soundtrigger/ISoundTriggerDetectionServiceClient.aidl",
        "media/java/android/media/tv/ITvInputClient.aidl",
        "media/java/android/media/tv/ITvInputHardware.aidl",
        "media/java/android/media/tv/ITvInputHardwareCallback.aidl",
+12 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ package android {
    field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
    field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
    field public static final java.lang.String BIND_SETTINGS_SUGGESTIONS_SERVICE = "android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE";
    field public static final java.lang.String BIND_SOUND_TRIGGER_DETECTION_SERVICE = "android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE";
    field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
    field public static final java.lang.String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
    field public static final java.lang.String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
@@ -2750,6 +2751,16 @@ package android.media.session {

package android.media.soundtrigger {

  public abstract class SoundTriggerDetectionService extends android.app.Service {
    ctor public SoundTriggerDetectionService();
    method public void onConnected(java.util.UUID, android.os.Bundle);
    method public void onDisconnected(java.util.UUID, android.os.Bundle);
    method public void onError(java.util.UUID, android.os.Bundle, int, int);
    method public void onGenericRecognitionEvent(java.util.UUID, android.os.Bundle, int, android.hardware.soundtrigger.SoundTrigger.RecognitionEvent);
    method public abstract void onStopOperation(java.util.UUID, android.os.Bundle, int);
    method public final void operationFinished(java.util.UUID, int);
  }

  public final class SoundTriggerDetector {
    method public boolean startRecognition(int);
    method public boolean stopRecognition();
@@ -2774,6 +2785,7 @@ package android.media.soundtrigger {
  public final class SoundTriggerManager {
    method public android.media.soundtrigger.SoundTriggerDetector createSoundTriggerDetector(java.util.UUID, android.media.soundtrigger.SoundTriggerDetector.Callback, android.os.Handler);
    method public void deleteModel(java.util.UUID);
    method public int getDetectionServiceOperationsTimeout();
    method public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
    method public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
  }
+9 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -1031,18 +1032,24 @@ public class ApplicationPackageManager extends PackageManager {
    }

    @Override
    public ResolveInfo resolveService(Intent intent, int flags) {
    public ResolveInfo resolveServiceAsUser(Intent intent, @ResolveInfoFlags int flags,
            @UserIdInt int userId) {
        try {
            return mPM.resolveService(
                intent,
                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                flags,
                mContext.getUserId());
                userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public ResolveInfo resolveService(Intent intent, int flags) {
        return resolveServiceAsUser(intent, flags, mContext.getUserId());
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
+6 −0
Original line number Diff line number Diff line
@@ -4182,6 +4182,12 @@ public abstract class PackageManager {
     */
    public abstract ResolveInfo resolveService(Intent intent, @ResolveInfoFlags int flags);

    /**
     * @hide
     */
    public abstract ResolveInfo resolveServiceAsUser(Intent intent, @ResolveInfoFlags int flags,
            @UserIdInt int userId);

    /**
     * Retrieve all services that can match the given intent.
     *
+18 −0
Original line number Diff line number Diff line
@@ -11596,6 +11596,24 @@ public final class Settings {
        public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS =
                "hidden_api_blacklist_exemptions";

        /**
         * Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
         * operation (in ms).
         *
         * @hide
         */
        public static final String SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT =
                "sound_trigger_detection_service_op_timeout";

        /**
         * Maximum number of {@link android.media.soundtrigger.SoundTriggerDetectionService}
         * operations per day.
         *
         * @hide
         */
        public static final String MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY =
                "max_sound_trigger_detection_service_ops_per_day";

        /**
         * Settings to backup. This is here so that it's in the same place as the settings
         * keys and easy to update.
Loading