blob: 76de1c928f389fc81286b79ae69a64a650fed070 [file] [log] [blame]
/*
* 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 androidx.camera.extensions.impl.serviceforward;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.extensions.impl.InitializerImpl;
import androidx.camera.extensions.impl.service.IAdvancedExtenderImpl;
import androidx.camera.extensions.impl.service.IImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.service.IPreviewExtenderImpl;
import androidx.camera.extensions.impl.service.IExtensionsService;
import androidx.camera.extensions.impl.service.IOnExtensionsDeinitializedCallback;
import androidx.camera.extensions.impl.service.IOnExtensionsInitializedCallback;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
public class ServiceManager {
private static final String TAG = "ServiceManager";
private static final int SERVICE_DELAY_MS = 1000;
private static final String SERVICE_PACKAGE_NAME = "com.android.oemextensions";
private static final String SERVICE_SERVICE_NAME =
"com.android.oemextensions.ExtensionsService";
private static ServiceManager sServiceManager;
private static final Object mLock = new Object();
public static void init(@Nullable Context context, @NonNull String version,
@Nullable InitializerImpl.OnExtensionsInitializedCallback callback,
@Nullable Executor executor) {
synchronized (mLock) {
if (sServiceManager == null) {
sServiceManager = new ServiceManager(context, version);
}
sServiceManager.bindServiceSync(context);
}
try {
Executor executorForCallback =
(executor != null)? executor: (cmd) -> cmd.run();
sServiceManager.mExtensionService.initialize(version,
new IOnExtensionsInitializedCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
executorForCallback.execute( () -> {
if (callback != null) {
callback.onSuccess();
}
Log.d(TAG, "initialize success!");
});
}
@Override
public void onFailure(int error) throws RemoteException {
executorForCallback.execute( () -> {
if (callback != null) {
callback.onFailure(error);
}
Log.d(TAG, "initialize failed! error=" + error);
});
}
});
} catch (RemoteException e){
throw new IllegalStateException("Failed to connect to extensions service", e);
}
}
@NonNull
public static ServiceManager getInstance() {
return sServiceManager;
}
public ServiceManager(@NonNull Context context, @NonNull String version) {
mContext = context;
mVersion = version;
}
private final Context mContext;
private final String mVersion;
private ServiceConnection mServiceConnection;
private IExtensionsService mExtensionService;
void bindServiceSync(Context context) {
if (mServiceConnection == null) {
CountDownLatch countDownLatch = new CountDownLatch(1);
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder binder) {
mExtensionService = IExtensionsService.Stub.asInterface(binder);
Log.d(TAG, "service connected");
countDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "service disconnected");
mExtensionService = null;
mServiceConnection = null;
}
};
Intent intent = new Intent();
intent.setClassName(SERVICE_PACKAGE_NAME, SERVICE_SERVICE_NAME);
Log.d(TAG, "bindService start. intent = " + intent);
context.bindService(intent, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT |
Context.BIND_ABOVE_CLIENT, AsyncTask.THREAD_POOL_EXECUTOR,
mServiceConnection);
try {
boolean success = countDownLatch.await(SERVICE_DELAY_MS, TimeUnit.MILLISECONDS);
if (!success) {
Log.e(TAG, "Timed out while initializing proxy service!");
}
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while initializing proxy service!");
}
}
}
public void deinit(@NonNull InitializerImpl.OnExtensionsDeinitializedCallback callback,
@NonNull Executor executor) {
try {
mExtensionService.deInitialize(new IOnExtensionsDeinitializedCallback.Stub() {
@Override
public void onSuccess() throws RemoteException {
executor.execute( () -> {
callback.onSuccess();
});
}
@Override
public void onFailure(int error) throws RemoteException {
executor.execute( () -> {
callback.onFailure(error);
});
}
});
} catch (RemoteException e) {
throw new IllegalStateException("Failed to connect to extensions service", e);
}
}
@NonNull
public IAdvancedExtenderImpl createAdvancedExtenderImpl(int extensionType) {
try {
synchronized (mLock) {
if (mExtensionService == null) {
init(mContext, mVersion, null, null);
}
}
return mExtensionService.initializeAdvancedExtension(extensionType);
} catch (RemoteException e) {
Log.e(TAG, "initializeAdvancedExtension failed", e);
throw new IllegalStateException("initializeAdvancedExtension failed", e);
}
}
@NonNull
public IImageCaptureExtenderImpl createImageCaptureExtenderImpl(int extensionType) {
try {
synchronized (mLock) {
if (mExtensionService == null) {
bindServiceSync(mContext);
}
}
return mExtensionService.initializeImageCaptureExtension(extensionType);
} catch (RemoteException e) {
Log.e(TAG, "initializeImageCaptureExtender failed", e);
throw new IllegalStateException("initializeImageCaptureExtender failed", e);
}
}
@NonNull
public IPreviewExtenderImpl createPreviewExtenderImpl(int extensionType) {
try {
synchronized (mLock) {
if (mExtensionService == null) {
bindServiceSync(mContext);
}
}
return mExtensionService.initializePreviewExtension(extensionType);
} catch (RemoteException e) {
Log.e(TAG, "initializePreviewExtension failed", e);
throw new IllegalStateException("initializePreviewExtension failed", e);
}
}
}