Merge "Follow-up fixes to MusicRecognitionManagerService"
This commit is contained in:
committed by
Android (Google) Code Review
commit
9dcb0d78ba
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.musicrecognition;
|
||||
|
||||
import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_AUDIO_UNAVAILABLE;
|
||||
import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_KILLED;
|
||||
import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
|
||||
import static android.media.musicrecognition.MusicRecognitionManager.RecognitionFailureCode;
|
||||
@@ -64,10 +65,6 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
@GuardedBy("mLock")
|
||||
private RemoteMusicRecognitionService mRemoteService;
|
||||
|
||||
private MusicRecognitionServiceCallback mRemoteServiceCallback =
|
||||
new MusicRecognitionServiceCallback();
|
||||
private IMusicRecognitionManagerCallback mCallback;
|
||||
|
||||
MusicRecognitionManagerPerUserService(
|
||||
@NonNull MusicRecognitionManagerService primary,
|
||||
@NonNull Object lock, int userId) {
|
||||
@@ -100,7 +97,8 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
private RemoteMusicRecognitionService ensureRemoteServiceLocked() {
|
||||
private RemoteMusicRecognitionService ensureRemoteServiceLocked(
|
||||
IMusicRecognitionManagerCallback clientCallback) {
|
||||
if (mRemoteService == null) {
|
||||
final String serviceName = getComponentNameLocked();
|
||||
if (serviceName == null) {
|
||||
@@ -113,7 +111,8 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
|
||||
mRemoteService = new RemoteMusicRecognitionService(getContext(),
|
||||
serviceComponent, mUserId, this,
|
||||
mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(),
|
||||
new MusicRecognitionServiceCallback(clientCallback),
|
||||
mMaster.isBindInstantServiceAllowed(),
|
||||
mMaster.verbose);
|
||||
}
|
||||
|
||||
@@ -130,13 +129,14 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
@NonNull IBinder callback) {
|
||||
int maxAudioLengthSeconds = Math.min(recognitionRequest.getMaxAudioLengthSeconds(),
|
||||
MAX_STREAMING_SECONDS);
|
||||
mCallback = IMusicRecognitionManagerCallback.Stub.asInterface(callback);
|
||||
IMusicRecognitionManagerCallback clientCallback =
|
||||
IMusicRecognitionManagerCallback.Stub.asInterface(callback);
|
||||
AudioRecord audioRecord = createAudioRecord(recognitionRequest, maxAudioLengthSeconds);
|
||||
|
||||
mRemoteService = ensureRemoteServiceLocked();
|
||||
mRemoteService = ensureRemoteServiceLocked(clientCallback);
|
||||
if (mRemoteService == null) {
|
||||
try {
|
||||
mCallback.onRecognitionFailed(
|
||||
clientCallback.onRecognitionFailed(
|
||||
RECOGNITION_FAILED_SERVICE_UNAVAILABLE);
|
||||
} catch (RemoteException e) {
|
||||
// Ignored.
|
||||
@@ -147,7 +147,8 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
|
||||
if (clientPipe == null) {
|
||||
try {
|
||||
mCallback.onAudioStreamClosed();
|
||||
clientCallback.onRecognitionFailed(
|
||||
RECOGNITION_FAILED_AUDIO_UNAVAILABLE);
|
||||
} catch (RemoteException ignored) {
|
||||
// Ignored.
|
||||
}
|
||||
@@ -192,11 +193,10 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
} finally {
|
||||
audioRecord.release();
|
||||
try {
|
||||
mCallback.onAudioStreamClosed();
|
||||
clientCallback.onAudioStreamClosed();
|
||||
} catch (RemoteException ignored) {
|
||||
// Ignored.
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
// Send the pipe down to the lookup service while we write to it asynchronously.
|
||||
@@ -207,13 +207,20 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
* Callback invoked by {@link android.service.musicrecognition.MusicRecognitionService} to pass
|
||||
* back the music search result.
|
||||
*/
|
||||
private final class MusicRecognitionServiceCallback extends
|
||||
final class MusicRecognitionServiceCallback extends
|
||||
IMusicRecognitionServiceCallback.Stub {
|
||||
|
||||
private final IMusicRecognitionManagerCallback mClientCallback;
|
||||
|
||||
private MusicRecognitionServiceCallback(IMusicRecognitionManagerCallback clientCallback) {
|
||||
mClientCallback = clientCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecognitionSucceeded(MediaMetadata result, Bundle extras) {
|
||||
try {
|
||||
sanitizeBundle(extras);
|
||||
mCallback.onRecognitionSucceeded(result, extras);
|
||||
mClientCallback.onRecognitionSucceeded(result, extras);
|
||||
} catch (RemoteException ignored) {
|
||||
// Ignored.
|
||||
}
|
||||
@@ -223,18 +230,23 @@ public final class MusicRecognitionManagerPerUserService extends
|
||||
@Override
|
||||
public void onRecognitionFailed(@RecognitionFailureCode int failureCode) {
|
||||
try {
|
||||
mCallback.onRecognitionFailed(failureCode);
|
||||
mClientCallback.onRecognitionFailed(failureCode);
|
||||
} catch (RemoteException ignored) {
|
||||
// Ignored.
|
||||
}
|
||||
destroyService();
|
||||
}
|
||||
|
||||
private IMusicRecognitionManagerCallback getClientCallback() {
|
||||
return mClientCallback;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDied(@NonNull RemoteMusicRecognitionService service) {
|
||||
try {
|
||||
mCallback.onRecognitionFailed(RECOGNITION_FAILED_SERVICE_KILLED);
|
||||
service.getServerCallback().getClientCallback().onRecognitionFailed(
|
||||
RECOGNITION_FAILED_SERVICE_KILLED);
|
||||
} catch (RemoteException e) {
|
||||
// Ignored.
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.musicrecognition.IMusicRecognitionManager;
|
||||
import android.media.musicrecognition.IMusicRecognitionManagerCallback;
|
||||
import android.media.musicrecognition.RecognitionRequest;
|
||||
@@ -32,7 +34,9 @@ import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.infra.AbstractMasterSystemService;
|
||||
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
|
||||
|
||||
@@ -113,9 +117,11 @@ public class MusicRecognitionManagerService extends
|
||||
enforceCaller("beginRecognition");
|
||||
|
||||
synchronized (mLock) {
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
final MusicRecognitionManagerPerUserService service = getServiceForUserLocked(
|
||||
UserHandle.getCallingUserId());
|
||||
if (service != null) {
|
||||
userId);
|
||||
if (service != null && (isDefaultServiceLocked(userId)
|
||||
|| isCalledByServiceAppLocked("beginRecognition"))) {
|
||||
service.beginRecognitionLocked(recognitionRequest, callback);
|
||||
} else {
|
||||
try {
|
||||
@@ -139,5 +145,55 @@ public class MusicRecognitionManagerService extends
|
||||
MusicRecognitionManagerService.this).exec(this, in, out, err, args, callback,
|
||||
resultReceiver);
|
||||
}
|
||||
|
||||
/** True if the currently set handler service is not overridden by the shell. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean isDefaultServiceLocked(int userId) {
|
||||
final String defaultServiceName = mServiceNameResolver.getDefaultServiceName(userId);
|
||||
if (defaultServiceName == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final String currentServiceName = mServiceNameResolver.getServiceName(userId);
|
||||
return defaultServiceName.equals(currentServiceName);
|
||||
}
|
||||
|
||||
/** True if the caller of the api is the same app which hosts the default service. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean isCalledByServiceAppLocked(@NonNull String methodName) {
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final String serviceName = mServiceNameResolver.getServiceName(userId);
|
||||
if (serviceName == null) {
|
||||
Slog.e(TAG, methodName + ": called by UID " + callingUid
|
||||
+ ", but there's no service set for user " + userId);
|
||||
return false;
|
||||
}
|
||||
|
||||
final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
|
||||
if (serviceComponent == null) {
|
||||
Slog.w(TAG, methodName + ": invalid service name: " + serviceName);
|
||||
return false;
|
||||
}
|
||||
|
||||
final String servicePackageName = serviceComponent.getPackageName();
|
||||
|
||||
final PackageManager pm = getContext().getPackageManager();
|
||||
final int serviceUid;
|
||||
try {
|
||||
serviceUid = pm.getPackageUidAsUser(servicePackageName,
|
||||
UserHandle.getCallingUserId());
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.w(TAG, methodName + ": could not verify UID for " + serviceName);
|
||||
return false;
|
||||
}
|
||||
if (callingUid != serviceUid) {
|
||||
Slog.e(TAG, methodName + ": called by UID " + callingUid + ", but service UID is "
|
||||
+ serviceUid);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.musicrecognition.IMusicRecognitionService;
|
||||
import android.media.musicrecognition.IMusicRecognitionServiceCallback;
|
||||
import android.media.musicrecognition.MusicRecognitionService;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
|
||||
import com.android.server.musicrecognition.MusicRecognitionManagerPerUserService.MusicRecognitionServiceCallback;
|
||||
|
||||
/** Remote connection to an instance of {@link MusicRecognitionService}. */
|
||||
public class RemoteMusicRecognitionService extends
|
||||
@@ -39,11 +39,12 @@ public class RemoteMusicRecognitionService extends
|
||||
private static final long TIMEOUT_IDLE_BIND_MILLIS = 40 * DateUtils.SECOND_IN_MILLIS;
|
||||
|
||||
// Allows the remote service to send back a result.
|
||||
private final IMusicRecognitionServiceCallback mServerCallback;
|
||||
private final MusicRecognitionServiceCallback
|
||||
mServerCallback;
|
||||
|
||||
public RemoteMusicRecognitionService(Context context, ComponentName serviceName,
|
||||
int userId, MusicRecognitionManagerPerUserService perUserService,
|
||||
IMusicRecognitionServiceCallback callback,
|
||||
MusicRecognitionServiceCallback callback,
|
||||
boolean bindInstantServiceAllowed, boolean verbose) {
|
||||
super(context, MusicRecognitionService.ACTION_MUSIC_SEARCH_LOOKUP, serviceName, userId,
|
||||
perUserService,
|
||||
@@ -66,6 +67,10 @@ public class RemoteMusicRecognitionService extends
|
||||
return TIMEOUT_IDLE_BIND_MILLIS;
|
||||
}
|
||||
|
||||
MusicRecognitionServiceCallback getServerCallback() {
|
||||
return mServerCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required, but empty since we don't need to notify the callback implementation of the request
|
||||
* results.
|
||||
|
||||
Reference in New Issue
Block a user