211 lines
7.0 KiB
Java
211 lines
7.0 KiB
Java
/*
|
|
* Copyright (C) 2023 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 android.hardware.camera2.extension;
|
|
|
|
import android.annotation.FlaggedApi;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.SystemApi;
|
|
import android.app.AppOpsManager;
|
|
import android.app.Service;
|
|
import android.content.Intent;
|
|
import android.hardware.camera2.CameraExtensionCharacteristics.Extension;
|
|
import android.os.IBinder;
|
|
import android.os.RemoteException;
|
|
import android.util.Log;
|
|
|
|
import com.android.internal.annotations.GuardedBy;
|
|
import com.android.internal.camera.flags.Flags;
|
|
|
|
interface CameraUsageTracker {
|
|
void startCameraOperation();
|
|
void finishCameraOperation();
|
|
}
|
|
|
|
/**
|
|
* Base service class that extension service implementations must extend.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
public abstract class CameraExtensionService extends Service {
|
|
private static final String TAG = "CameraExtensionService";
|
|
private CameraUsageTracker mCameraUsageTracker;
|
|
private static Object mLock = new Object();
|
|
|
|
private final class CameraTracker implements CameraUsageTracker {
|
|
|
|
private final AppOpsManager mAppOpsService = getApplicationContext().getSystemService(
|
|
AppOpsManager.class);
|
|
private final String mPackageName = getPackageName();
|
|
private final String mAttributionTag = getAttributionTag();
|
|
private int mUid = getApplicationInfo().uid;
|
|
|
|
@Override
|
|
public void startCameraOperation() {
|
|
if (mAppOpsService != null) {
|
|
mAppOpsService.startOp(AppOpsManager.OPSTR_CAMERA, mUid, mPackageName,
|
|
mAttributionTag, "Camera extensions");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void finishCameraOperation() {
|
|
if (mAppOpsService != null) {
|
|
mAppOpsService.finishOp(AppOpsManager.OPSTR_CAMERA, mUid, mPackageName,
|
|
mAttributionTag);
|
|
}
|
|
}
|
|
}
|
|
@GuardedBy("mLock")
|
|
private static IInitializeSessionCallback mInitializeCb = null;
|
|
|
|
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
|
@Override
|
|
public void binderDied() {
|
|
synchronized (mLock) {
|
|
mInitializeCb = null;
|
|
}
|
|
if (mCameraUsageTracker != null) {
|
|
mCameraUsageTracker.finishCameraOperation();
|
|
}
|
|
}
|
|
};
|
|
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
protected CameraExtensionService() { }
|
|
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
@Override
|
|
@NonNull
|
|
public final IBinder onBind(@Nullable Intent intent) {
|
|
if (mCameraUsageTracker == null) {
|
|
mCameraUsageTracker = new CameraTracker();
|
|
}
|
|
return new CameraExtensionServiceImpl();
|
|
}
|
|
|
|
private class CameraExtensionServiceImpl extends ICameraExtensionsProxyService.Stub {
|
|
@Override
|
|
public boolean registerClient(IBinder token) throws RemoteException {
|
|
return CameraExtensionService.this.onRegisterClient(token);
|
|
}
|
|
|
|
@Override
|
|
public void unregisterClient(IBinder token) throws RemoteException {
|
|
CameraExtensionService.this.onUnregisterClient(token);
|
|
}
|
|
|
|
@Override
|
|
public boolean advancedExtensionsSupported() throws RemoteException {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void initializeSession(IInitializeSessionCallback cb) {
|
|
boolean ret = false;
|
|
synchronized (mLock) {
|
|
if (mInitializeCb == null) {
|
|
mInitializeCb = cb;
|
|
try {
|
|
mInitializeCb.asBinder().linkToDeath(mDeathRecipient, 0);
|
|
} catch (RemoteException e) {
|
|
Log.e(TAG, "Failure to register binder death notifier!");
|
|
}
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (ret) {
|
|
cb.onSuccess();
|
|
} else {
|
|
cb.onFailure();
|
|
}
|
|
} catch (RemoteException e) {
|
|
|
|
Log.e(TAG, "Client doesn't respond!");
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void releaseSession() {
|
|
synchronized (mLock) {
|
|
if (mInitializeCb != null) {
|
|
mInitializeCb.asBinder().unlinkToDeath(mDeathRecipient, 0);
|
|
mInitializeCb = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public IPreviewExtenderImpl initializePreviewExtension(@Extension int extensionType)
|
|
throws RemoteException {
|
|
// Basic Extension API is not supported
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public IImageCaptureExtenderImpl initializeImageExtension(@Extension int extensionType)
|
|
throws RemoteException {
|
|
// Basic Extension API is not supported
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public IAdvancedExtenderImpl initializeAdvancedExtension(@Extension int extensionType)
|
|
throws RemoteException {
|
|
AdvancedExtender extender = CameraExtensionService.this.onInitializeAdvancedExtension(
|
|
extensionType);
|
|
extender.setCameraUsageTracker(mCameraUsageTracker);
|
|
return extender.getAdvancedExtenderBinder();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register an extension client. The client must call this method
|
|
* after successfully binding to the service.
|
|
*
|
|
* @param token Binder token that can be used for adding
|
|
* death notifier in case the client exits
|
|
* unexpectedly.
|
|
* @return true if the registration is successful, false otherwise
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
public abstract boolean onRegisterClient(@NonNull IBinder token);
|
|
|
|
/**
|
|
* Unregister an extension client.
|
|
*
|
|
* @param token Binder token
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
public abstract void onUnregisterClient(@NonNull IBinder token);
|
|
|
|
/**
|
|
* Initialize and return an advanced extension.
|
|
*
|
|
* @param extensionType {@link android.hardware.camera2.CameraExtensionCharacteristics}
|
|
* extension type
|
|
* @return Valid advanced extender of the requested type
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_CONCERT_MODE)
|
|
@NonNull
|
|
public abstract AdvancedExtender onInitializeAdvancedExtension(@Extension int extensionType);
|
|
}
|