Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2ee5c50 authored by Roman Birg's avatar Roman Birg Committed by Brint E. Kriebel
Browse files

frameworks: extend TorchService to be able to handle sysfs torch config



Some devices are still using a sysfs node to control the torch. Let's
support those configurations and properly shut the torch down.

Change-Id: I5fa1cccdcffad26dbfef4b2ee0eafe1218a5308b
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
(cherry picked from commit 204e9e44)
parent 62de78c2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -24,4 +24,5 @@ interface ITorchService {
    void onCameraOpened(IBinder token, int cameraId);
    void onCameraClosed(IBinder token, int cameraId);
    boolean onStartingTorch(int cameraId);
    void onStopTorch();
}
+49 −8
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.ITorchService;
import android.os.Binder;
import android.os.Handler;
@@ -26,8 +27,9 @@ public class TorchService extends ITorchService.Stub {
    private final Context mContext;
    private int mTorchAppUid = 0;
    private int mTorchAppCameraId = -1;
    private SparseArray<CameraUserRecord> mCamerasInUse;
    private Object mStopTorchLock = new Object();
    private final SparseArray<CameraUserRecord> mCamerasInUse;
    private final Object mStopTorchLock = new Object();
    private boolean mTorchUsingSysfs;

    private static class CameraUserRecord {
        IBinder token;
@@ -68,12 +70,14 @@ public class TorchService extends ITorchService.Stub {
            } else {
                // As a synchronous broadcast is an expensive operation, only
                // attempt to kill torch if it actually grabbed the camera before
                if (cameraId == mTorchAppCameraId && mCamerasInUse.get(cameraId) != null) {
                if (cameraId == mTorchAppCameraId) {
                    if (mTorchUsingSysfs || mCamerasInUse.get(cameraId) != null) {
                        if (DEBUG) Log.d(TAG, "Need to kill torch");
                        needTorchShutdown = true;
                    }
                }
            }
        }

        // Shutdown torch outside of lock - torch shutdown will call into onCameraClosed()
        if (needTorchShutdown) {
@@ -114,11 +118,45 @@ public class TorchService extends ITorchService.Stub {
        if (DEBUG) Log.d(TAG, "onStartingTorch(cameraId=" + cameraId + ")");
        synchronized (mCamerasInUse) {
            mTorchAppUid = Binder.getCallingUid();
            if (cameraId >= 0) {
                if (cameraId == mTorchAppCameraId) {
                    return true;
                }
                return mCamerasInUse.get(cameraId) == null;
            }

            // cameraId < 0 means torch is using sysfs
            cameraId = getBackFacingCameraId();
            if (mCamerasInUse.get(cameraId) != null) {
                return false;
            }
            mTorchUsingSysfs = true;
            mTorchAppCameraId = cameraId;
            return true;
        }
    }

    @Override
    public void onStopTorch() {
        if (DEBUG) Log.d(TAG, "onStopTorch()");
        synchronized (mCamerasInUse) {
            if (mTorchUsingSysfs) {
                mTorchAppCameraId = -1;
            }
            mTorchUsingSysfs = false;
        }
    }

    private int getBackFacingCameraId() {
        int numberOfCameras = Camera.getNumberOfCameras();
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                return i;
            }
        }
        return 0;
    }

    private void removeCameraUserLocked(IBinder token, int cameraId) {
@@ -130,6 +168,7 @@ public class TorchService extends ITorchService.Stub {
    }

    private void shutdownTorch() {
        if (DEBUG) Log.d(TAG, "shutdownTorch()");
        // Ordered broadcasts are asynchronous (they only guarantee the order between
        // receivers), so make them synchronous manually by executing the broadcast in a
        // background thread and blocking the calling thread until the broadcast is done
@@ -139,6 +178,7 @@ public class TorchService extends ITorchService.Stub {

        Intent i = new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT");
        i.putExtra("stop", true);
        i.addFlags(Intent.FLAG_FROM_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);

        synchronized (mStopTorchLock) {
            if (DEBUG) Log.v(TAG, "Sending torch shutdown broadcast");
@@ -179,5 +219,6 @@ public class TorchService extends ITorchService.Stub {
        }
        pw.println("  mTorchAppUid=" + mTorchAppUid);
        pw.println("  mTorchAppCameraId=" + mTorchAppCameraId);
        pw.println("  mTorchUsingSysfs=" + mTorchUsingSysfs);
    }
}