1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.musicrecognition; 18 19 import android.annotation.NonNull; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.media.AudioFormat; 23 import android.media.musicrecognition.IMusicRecognitionAttributionTagCallback; 24 import android.media.musicrecognition.IMusicRecognitionService; 25 import android.media.musicrecognition.MusicRecognitionService; 26 import android.os.IBinder; 27 import android.os.ParcelFileDescriptor; 28 import android.os.RemoteException; 29 import android.text.format.DateUtils; 30 31 import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService; 32 import com.android.server.musicrecognition.MusicRecognitionManagerPerUserService.MusicRecognitionServiceCallback; 33 34 import java.util.concurrent.CompletableFuture; 35 36 37 /** Remote connection to an instance of {@link MusicRecognitionService}. */ 38 public class RemoteMusicRecognitionService extends 39 AbstractMultiplePendingRequestsRemoteService<RemoteMusicRecognitionService, 40 IMusicRecognitionService> { 41 42 // Maximum time allotted for the remote service to return a result. Up to 24s of audio plus 43 // time to fingerprint and make rpcs. 44 private static final long TIMEOUT_IDLE_BIND_MILLIS = 40 * DateUtils.SECOND_IN_MILLIS; 45 46 // Allows the remote service to send back a result. 47 private final MusicRecognitionServiceCallback 48 mServerCallback; 49 RemoteMusicRecognitionService(Context context, ComponentName serviceName, int userId, MusicRecognitionManagerPerUserService perUserService, MusicRecognitionServiceCallback callback, boolean bindInstantServiceAllowed, boolean verbose)50 public RemoteMusicRecognitionService(Context context, ComponentName serviceName, 51 int userId, MusicRecognitionManagerPerUserService perUserService, 52 MusicRecognitionServiceCallback callback, 53 boolean bindInstantServiceAllowed, boolean verbose) { 54 super(context, MusicRecognitionService.ACTION_MUSIC_SEARCH_LOOKUP, serviceName, userId, 55 perUserService, 56 context.getMainThreadHandler(), 57 // Prevents the service from having its permissions stripped while in background. 58 Context.BIND_INCLUDE_CAPABILITIES | (bindInstantServiceAllowed 59 ? Context.BIND_ALLOW_INSTANT : 0), verbose, 60 /* initialCapacity= */ 1); 61 mServerCallback = callback; 62 } 63 64 @NonNull 65 @Override getServiceInterface(@onNull IBinder service)66 protected IMusicRecognitionService getServiceInterface(@NonNull IBinder service) { 67 return IMusicRecognitionService.Stub.asInterface(service); 68 } 69 70 @Override getTimeoutIdleBindMillis()71 protected long getTimeoutIdleBindMillis() { 72 return TIMEOUT_IDLE_BIND_MILLIS; 73 } 74 getServerCallback()75 MusicRecognitionServiceCallback getServerCallback() { 76 return mServerCallback; 77 } 78 79 /** 80 * Required, but empty since we don't need to notify the callback implementation of the request 81 * results. 82 */ 83 interface Callbacks extends VultureCallback<RemoteMusicRecognitionService> {} 84 85 /** 86 * Sends the given descriptor to the app's {@link MusicRecognitionService} to read the 87 * audio. 88 */ onAudioStreamStarted(@onNull ParcelFileDescriptor fd, @NonNull AudioFormat audioFormat)89 public void onAudioStreamStarted(@NonNull ParcelFileDescriptor fd, 90 @NonNull AudioFormat audioFormat) { 91 scheduleAsyncRequest( 92 binder -> binder.onAudioStreamStarted(fd, audioFormat, mServerCallback)); 93 } 94 95 96 /** 97 * Returns the name of the <attribution> tag defined in the remote service's manifest. 98 */ getAttributionTag()99 public CompletableFuture<String> getAttributionTag() { 100 CompletableFuture<String> attributionTagFuture = new CompletableFuture<String>(); 101 scheduleAsyncRequest( 102 binder -> binder.getAttributionTag( 103 new IMusicRecognitionAttributionTagCallback.Stub() { 104 @Override 105 public void onAttributionTag(String tag) throws RemoteException { 106 attributionTagFuture.complete(tag); 107 } 108 })); 109 return attributionTagFuture; 110 } 111 } 112