Add shell commands MusicRecognitionService

The shell command allows a temporary override of the recognition service so I can substitute a stub in cts tests. Also add permission for the shell to be able to invoke the recognition api for the sake of cts tests.

Bug: 164439465
Test: new test in topic
Change-Id: I4a8de616a70f0d6504b2eaf486d5641cb7872607
This commit is contained in:
Nick Moukhine
2020-11-23 14:33:08 +01:00
parent e9cf1f9847
commit e61ddcfc0a
5 changed files with 126 additions and 2 deletions

View File

@@ -1771,6 +1771,7 @@ package android.content {
field public static final String EUICC_CARD_SERVICE = "euicc_card";
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
field public static final String NETD_SERVICE = "netd";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
field public static final String OEM_LOCK_SERVICE = "oem_lock";

View File

@@ -4536,6 +4536,7 @@ public abstract class Context {
* @hide
* @see #getSystemService(String)
*/
@SystemApi
public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
/**

View File

@@ -113,7 +113,8 @@ public final class MusicRecognitionManagerPerUserService extends
mRemoteService = new RemoteMusicRecognitionService(getContext(),
serviceComponent, mUserId, this,
mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(),
mMaster.verbose);
}
return mRemoteService;
@@ -167,7 +168,8 @@ public final class MusicRecognitionManagerPerUserService extends
recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
audioRecord.startRecording();
while (bytesRead >= 0 && totalBytesRead
< audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE) {
< audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE
&& mRemoteService != null) {
bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
if (bytesRead > 0) {
totalBytesRead += bytesRead;
@@ -215,6 +217,7 @@ public final class MusicRecognitionManagerPerUserService extends
} catch (RemoteException ignored) {
// Ignored.
}
destroyService();
}
@Override
@@ -224,6 +227,7 @@ public final class MusicRecognitionManagerPerUserService extends
} catch (RemoteException ignored) {
// Ignored.
}
destroyService();
}
}
@@ -235,6 +239,17 @@ public final class MusicRecognitionManagerPerUserService extends
// Ignored.
}
Slog.w(TAG, "remote service died: " + service);
destroyService();
}
@GuardedBy("mLock")
private void destroyService() {
synchronized (mLock) {
if (mRemoteService != null) {
mRemoteService.destroy();
mRemoteService = null;
}
}
}
/** Establishes an audio stream from the DSP audio source. */

View File

@@ -16,6 +16,7 @@
package com.android.server.musicrecognition;
import static android.Manifest.permission.MANAGE_MUSIC_RECOGNITION;
import static android.content.PermissionChecker.PERMISSION_GRANTED;
import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
@@ -28,11 +29,14 @@ import android.media.musicrecognition.RecognitionRequest;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import java.io.FileDescriptor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -45,6 +49,7 @@ public class MusicRecognitionManagerService extends
MusicRecognitionManagerPerUserService> {
private static final String TAG = MusicRecognitionManagerService.class.getSimpleName();
private static final int MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS = 60_000;
private MusicRecognitionManagerStub mMusicRecognitionManagerStub;
final ExecutorService mExecutorService = Executors.newCachedThreadPool();
@@ -90,6 +95,16 @@ public class MusicRecognitionManagerService extends
throw new SecurityException(msg);
}
@Override
protected void enforceCallingPermissionForManagement() {
getContext().enforceCallingPermission(MANAGE_MUSIC_RECOGNITION, TAG);
}
@Override
protected int getMaximumTemporaryServiceDurationMs() {
return MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS;
}
final class MusicRecognitionManagerStub extends IMusicRecognitionManager.Stub {
@Override
public void beginRecognition(
@@ -112,5 +127,17 @@ public class MusicRecognitionManagerService extends
}
}
}
@Override
public void onShellCommand(@Nullable FileDescriptor in,
@Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args,
@Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
new MusicRecognitionManagerServiceShellCommand(
MusicRecognitionManagerService.this).exec(this, in, out, err, args, callback,
resultReceiver);
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.musicrecognition;
import android.os.ShellCommand;
import java.io.PrintWriter;
/** Handles adb shell commands send to MusicRecognitionManagerService. */
class MusicRecognitionManagerServiceShellCommand extends ShellCommand {
private final MusicRecognitionManagerService mService;
MusicRecognitionManagerServiceShellCommand(MusicRecognitionManagerService service) {
mService = service;
}
@Override
public int onCommand(String cmd) {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
final PrintWriter pw = getOutPrintWriter();
if ("set".equals(cmd)) {
return requestSet(pw);
}
return handleDefaultCommands(cmd);
}
private int requestSet(PrintWriter pw) {
final String what = getNextArgRequired();
if ("temporary-service".equals(what)) {
return setTemporaryService(pw);
}
pw.println("Invalid set: " + what);
return -1;
}
private int setTemporaryService(PrintWriter pw) {
final int userId = Integer.parseInt(getNextArgRequired());
final String serviceName = getNextArg();
if (serviceName == null) {
mService.resetTemporaryService(userId);
return 0;
}
final int duration = Integer.parseInt(getNextArgRequired());
mService.setTemporaryService(userId, serviceName, duration);
pw.println("MusicRecognitionService temporarily set to " + serviceName + " for "
+ duration + "ms");
return 0;
}
@Override
public void onHelp() {
try (PrintWriter pw = getOutPrintWriter();) {
pw.println("MusicRecognition Service (music_recognition) commands:");
pw.println(" help");
pw.println(" Prints this help text.");
pw.println("");
pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]");
pw.println(" Temporarily (for DURATION ms) changes the service implementation.");
pw.println(" To reset, call with just the USER_ID argument.");
pw.println("");
}
}
}