Merge "Add OP_PLAY_AUDIO to control shutter sound." into pi-dev

This commit is contained in:
android-build-team Robot
2018-05-01 23:56:12 +00:00
committed by Android (Google) Code Review

View File

@@ -18,19 +18,23 @@ package android.hardware;
import static android.system.OsConstants.*;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.media.AudioAttributes;
import android.media.IAudioService;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.renderscript.Allocation;
@@ -43,6 +47,10 @@ import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -174,6 +182,15 @@ public class Camera {
private boolean mFaceDetectionRunning = false;
private final Object mAutoFocusCallbackLock = new Object();
private final Object mShutterSoundLock = new Object();
// for AppOps
private @Nullable IAppOpsService mAppOps;
private IAppOpsCallback mAppOpsCallback;
@GuardedBy("mShutterSoundLock")
private boolean mHasAppOpsPlayAudio = true;
@GuardedBy("mShutterSoundLock")
private boolean mShutterSoundEnabledFromApp = true;
private static final int NO_ERROR = 0;
/**
@@ -526,6 +543,7 @@ public class Camera {
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
initAppOps();
}
@@ -547,6 +565,33 @@ public class Camera {
* An empty Camera for testing purpose.
*/
Camera() {
initAppOps();
}
private void initAppOps() {
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
// initialize mHasAppOpsPlayAudio
updateAppOpsPlayAudio();
// register a callback to monitor whether the OP_PLAY_AUDIO is still allowed
mAppOpsCallback = new IAppOpsCallbackWrapper(this);
try {
mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO,
ActivityThread.currentPackageName(), mAppOpsCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error registering appOps callback", e);
mHasAppOpsPlayAudio = false;
}
}
private void releaseAppOps() {
try {
if (mAppOps != null) {
mAppOps.stopWatchingMode(mAppOpsCallback);
}
} catch (Exception e) {
// nothing to do here, the object is supposed to be released anyway
}
}
@Override
@@ -568,6 +613,7 @@ public class Camera {
public final void release() {
native_release();
mFaceDetectionRunning = false;
releaseAppOps();
}
/**
@@ -1623,7 +1669,17 @@ public class Camera {
Log.e(TAG, "Audio service is unavailable for queries");
}
}
return _enableShutterSound(enabled);
synchronized (mShutterSoundLock) {
if (enabled && mHasAppOpsPlayAudio) {
Log.i(TAG, "Shutter sound is not allowed by AppOpsManager");
return false;
}
boolean ret = _enableShutterSound(enabled);
if (ret) {
mShutterSoundEnabledFromApp = enabled;
}
return ret;
}
}
/**
@@ -1648,6 +1704,49 @@ public class Camera {
private native final boolean _enableShutterSound(boolean enabled);
private static class IAppOpsCallbackWrapper extends IAppOpsCallback.Stub {
private final WeakReference<Camera> mWeakCamera;
IAppOpsCallbackWrapper(Camera camera) {
mWeakCamera = new WeakReference<Camera>(camera);
}
@Override
public void opChanged(int op, int uid, String packageName) {
if (op == AppOpsManager.OP_PLAY_AUDIO) {
final Camera camera = mWeakCamera.get();
if (camera != null) {
camera.updateAppOpsPlayAudio();
}
}
}
}
private void updateAppOpsPlayAudio() {
synchronized (mShutterSoundLock) {
boolean oldHasAppOpsPlayAudio = mHasAppOpsPlayAudio;
try {
int mode = AppOpsManager.MODE_IGNORED;
if (mAppOps != null) {
mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
Process.myUid(), ActivityThread.currentPackageName());
}
mHasAppOpsPlayAudio = mode == AppOpsManager.MODE_ALLOWED;
} catch (RemoteException e) {
Log.e(TAG, "AppOpsService check audio operation failed");
mHasAppOpsPlayAudio = false;
}
if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio) {
if (!mHasAppOpsPlayAudio) {
_enableShutterSound(false);
} else {
_enableShutterSound(mShutterSoundEnabledFromApp);
}
}
}
}
/**
* Callback interface for zoom changes during a smooth zoom operation.
*