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

Commit f1dcd2e7 authored by Danny Baumann's avatar Danny Baumann Committed by Roman Birg
Browse files

Fix up torch tile handling.

- Keep it in sync with other torch invocations (e.g. via gesture)
- Only treat torch as 'unavailable' if another client (camera app) uses
  the camera, but not if torch itself opened it.

Change-Id: Ife9ae30ab48d491af70a5e23d1b2d123da60de3a
parent bfbd6d6f
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -22,9 +22,9 @@ package android.hardware;
 */
 */
oneway interface ITorchCallback {
oneway interface ITorchCallback {
     /**
     /**
      * Called when the flashlight turns off unexpectedly.
      * Called when the flashlight state changes
      */
      */
     void onTorchOff();
     void onTorchStateChanged(boolean on);


     /**
     /**
      * Called when there is an error that turns the flashlight off.
      * Called when there is an error that turns the flashlight off.
+9 −8
Original line number Original line Diff line number Diff line
@@ -33,7 +33,7 @@ public class TorchManager {


    public static final String TAG = TorchManager.class.getSimpleName();
    public static final String TAG = TorchManager.class.getSimpleName();


    private static final int DISPATCH_TORCH_OFF = 1;
    private static final int DISPATCH_TORCH_STATE_CHANGE = 1;
    private static final int DISPATCH_TORCH_ERROR = 2;
    private static final int DISPATCH_TORCH_ERROR = 2;
    private static final int DISPATCH_TORCH_AVAILABILITY_CHANGE = 3;
    private static final int DISPATCH_TORCH_AVAILABILITY_CHANGE = 3;


@@ -57,14 +57,14 @@ public class TorchManager {
        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            switch (msg.what) {
                case DISPATCH_TORCH_OFF:
                case DISPATCH_TORCH_STATE_CHANGE:
                    synchronized (mCallbacks) {
                    synchronized (mCallbacks) {
                        List<TorchCallback> listenersToRemove = new ArrayList<>();
                        List<TorchCallback> listenersToRemove = new ArrayList<>();
                        for (TorchCallback listener : mCallbacks) {
                        for (TorchCallback listener : mCallbacks) {
                            try {
                            try {
                                listener.onTorchOff();
                                listener.onTorchStateChanged(msg.arg1 != 0);
                            } catch (Throwable e) {
                            } catch (Throwable e) {
                                Log.w(TAG, "Unable to update torch off", e);
                                Log.w(TAG, "Unable to update torch state", e);
                                listenersToRemove.add(listener);
                                listenersToRemove.add(listener);
                            }
                            }
                        }
                        }
@@ -148,8 +148,9 @@ public class TorchManager {


    private final ITorchCallback mTorchChangeListener = new ITorchCallback.Stub() {
    private final ITorchCallback mTorchChangeListener = new ITorchCallback.Stub() {
        @Override
        @Override
        public void onTorchOff() throws RemoteException {
        public void onTorchStateChanged(boolean on) throws RemoteException {
            mHandler.sendEmptyMessage(DISPATCH_TORCH_OFF);
            mHandler.sendMessage(Message.obtain(mHandler, DISPATCH_TORCH_STATE_CHANGE,
                    on ? 1 : 0, 0));
        }
        }


        @Override
        @Override
@@ -212,9 +213,9 @@ public class TorchManager {


    public interface TorchCallback {
    public interface TorchCallback {
        /**
        /**
         * Called when the torch turns off unexpectedly.
         * Called when the torch state changes
         */
         */
        public void onTorchOff();
        public void onTorchStateChanged(boolean on);
        /**
        /**
         * Called when there is an error that turns the torch off.
         * Called when there is an error that turns the torch off.
         */
         */
+6 −5
Original line number Original line Diff line number Diff line
@@ -34,11 +34,13 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements


    private final TorchManager mTorchManager;
    private final TorchManager mTorchManager;
    private long mWasLastOn;
    private long mWasLastOn;
    private boolean mTorchAvailable;


    public FlashlightTile(Host host) {
    public FlashlightTile(Host host) {
        super(host);
        super(host);
        mTorchManager = (TorchManager) mContext.getSystemService(Context.TORCH_SERVICE);
        mTorchManager = (TorchManager) mContext.getSystemService(Context.TORCH_SERVICE);
        mTorchManager.addListener(this);
        mTorchManager.addListener(this);
        mTorchAvailable = mTorchManager.isAvailable();
    }
    }


    @Override
    @Override
@@ -90,9 +92,7 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
            }
            }
        }
        }


        // Always show the tile when the flashlight is or was recently on. This is needed because
        state.visible = mWasLastOn != 0 || mTorchAvailable;
        // the camera is not available while it is being used for the flashlight.
        state.visible = mWasLastOn != 0 || mTorchManager.isAvailable();
        state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
        state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
        state.iconId = state.value
        state.iconId = state.value
                ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
                ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
@@ -112,8 +112,8 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
    }
    }


    @Override
    @Override
    public void onTorchOff() {
    public void onTorchStateChanged(boolean on) {
        refreshState(false);
        refreshState(on);
    }
    }


    @Override
    @Override
@@ -123,6 +123,7 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements


    @Override
    @Override
    public void onTorchAvailabilityChanged(boolean available) {
    public void onTorchAvailabilityChanged(boolean available) {
        mTorchAvailable = available;
        refreshState(mTorchManager.isTorchOn());
        refreshState(mTorchManager.isTorchOn());
    }
    }


+32 −20
Original line number Original line Diff line number Diff line
@@ -50,7 +50,7 @@ public class TorchService extends ITorchService.Stub {
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);


    private static final int DISPATCH_ERROR = 0;
    private static final int DISPATCH_ERROR = 0;
    private static final int DISPATCH_OFF = 1;
    private static final int DISPATCH_STATE_CHANGE = 1;
    private static final int DISPATCH_AVAILABILITY_CHANGED = 2;
    private static final int DISPATCH_AVAILABILITY_CHANGED = 2;


    private final Context mContext;
    private final Context mContext;
@@ -74,6 +74,7 @@ public class TorchService extends ITorchService.Stub {


    private CameraManager mCameraManager;
    private CameraManager mCameraManager;
    private CameraDevice mCameraDevice;
    private CameraDevice mCameraDevice;
    private boolean mOpeningCamera;
    private CaptureRequest mFlashlightRequest;
    private CaptureRequest mFlashlightRequest;
    private CameraCaptureSession mSession;
    private CameraCaptureSession mSession;
    private SurfaceTexture mSurfaceTexture;
    private SurfaceTexture mSurfaceTexture;
@@ -222,6 +223,7 @@ public class TorchService extends ITorchService.Stub {
        final String cameraId = getCameraId();
        final String cameraId = getCameraId();
        if (DEBUG) Log.d(TAG, "startDevice(), cameraID: " + cameraId);
        if (DEBUG) Log.d(TAG, "startDevice(), cameraID: " + cameraId);
        mTorchCameraId = Integer.valueOf(cameraId);
        mTorchCameraId = Integer.valueOf(cameraId);
        mOpeningCamera = true;
        mCameraManager.openCamera(cameraId, mTorchCameraListener, mHandler);
        mCameraManager.openCamera(cameraId, mTorchCameraListener, mHandler);
    }
    }


@@ -279,7 +281,9 @@ public class TorchService extends ITorchService.Stub {
            }
            }
            if (enabled) {
            if (enabled) {
                if (mCameraDevice == null) {
                if (mCameraDevice == null) {
                    if (!mOpeningCamera) {
                        startDevice();
                        startDevice();
                    }
                    return;
                    return;
                }
                }
                if (mSession == null) {
                if (mSession == null) {
@@ -294,13 +298,11 @@ public class TorchService extends ITorchService.Stub {
                    CaptureRequest request = builder.build();
                    CaptureRequest request = builder.build();
                    mSession.capture(request, null, mHandler);
                    mSession.capture(request, null, mHandler);
                    mFlashlightRequest = request;
                    mFlashlightRequest = request;
                    dispatchStateChange(true);
                }
                }
            } else {
            } else {
                if (mCameraDevice != null) {
                    mCameraDevice.close();
                teardownTorch();
                teardownTorch();
            }
            }
            }


        } catch (CameraAccessException|IllegalStateException|UnsupportedOperationException e) {
        } catch (CameraAccessException|IllegalStateException|UnsupportedOperationException e) {
            Log.e(TAG, "Error in updateFlashlight", e);
            Log.e(TAG, "Error in updateFlashlight", e);
@@ -317,7 +319,11 @@ public class TorchService extends ITorchService.Stub {
    }
    }


    private void teardownTorch() {
    private void teardownTorch() {
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
            mCameraDevice = null;
        }
        mOpeningCamera = false;
        mSession = null;
        mSession = null;
        mFlashlightRequest = null;
        mFlashlightRequest = null;
        if (mSurface != null) {
        if (mSurface != null) {
@@ -333,7 +339,7 @@ public class TorchService extends ITorchService.Stub {
            mTorchEnabled = false;
            mTorchEnabled = false;
        }
        }
        dispatchError();
        dispatchError();
        dispatchOff();
        dispatchStateChange(false);
        updateFlashlight(true /* forceDisable */);
        updateFlashlight(true /* forceDisable */);
    }
    }


@@ -352,12 +358,12 @@ public class TorchService extends ITorchService.Stub {
                mTorchEnabled = false;
                mTorchEnabled = false;
            }
            }
            updateFlashlight(true /* forceDisable */);
            updateFlashlight(true /* forceDisable */);
            dispatchOff();
            dispatchStateChange(false);
        }
        }
    };
    };


    private void dispatchOff() {
    private void dispatchStateChange(boolean on) {
        dispatchListeners(DISPATCH_OFF, false /* argument (ignored) */);
        dispatchListeners(DISPATCH_STATE_CHANGE, on);
    }
    }


    private void dispatchError() {
    private void dispatchError() {
@@ -376,8 +382,8 @@ public class TorchService extends ITorchService.Stub {
                try {
                try {
                    if (message == DISPATCH_ERROR) {
                    if (message == DISPATCH_ERROR) {
                        l.onTorchError();
                        l.onTorchError();
                    } else if (message == DISPATCH_OFF) {
                    } else if (message == DISPATCH_STATE_CHANGE) {
                        l.onTorchOff();
                        l.onTorchStateChanged(argument);
                    } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
                    } else if (message == DISPATCH_AVAILABILITY_CHANGED) {
                        l.onTorchAvailabilityChanged(argument);
                        l.onTorchAvailabilityChanged(argument);
                    }
                    }
@@ -393,14 +399,19 @@ public class TorchService extends ITorchService.Stub {
            new CameraDevice.StateListener() {
            new CameraDevice.StateListener() {
        @Override
        @Override
        public void onOpened(CameraDevice camera) {
        public void onOpened(CameraDevice camera) {
            if (mOpeningCamera) {
                mCameraDevice = camera;
                mCameraDevice = camera;
                mOpeningCamera = false;
                postUpdateFlashlight();
                postUpdateFlashlight();
            } else {
                teardownTorch();
            }
        }
        }


        @Override
        @Override
        public void onDisconnected(CameraDevice camera) {
        public void onDisconnected(CameraDevice camera) {
            if (mCameraDevice == camera) {
            if (mCameraDevice == camera) {
                dispatchOff();
                dispatchStateChange(false);
                teardownTorch();
                teardownTorch();
            }
            }
        }
        }
@@ -446,18 +457,19 @@ public class TorchService extends ITorchService.Stub {
                @Override
                @Override
                public void onCameraUnavailable(String cameraId) {
                public void onCameraUnavailable(String cameraId) {
                    if (DEBUG) Log.d(TAG, "onCameraUnavailable(" + cameraId + ")");
                    if (DEBUG) Log.d(TAG, "onCameraUnavailable(" + cameraId + ")");
                    if (cameraId.equals(String.valueOf(mTorchCameraId))) {
                    boolean openedOurselves = mOpeningCamera || mCameraDevice != null;
                    if (!openedOurselves && cameraId.equals(String.valueOf(mTorchCameraId))) {
                        setTorchAvailable(false);
                        setTorchAvailable(false);
                    }
                    }
                }
                }


                private void setTorchAvailable(boolean available) {
                private void setTorchAvailable(boolean available) {
                    boolean changed;
                    boolean oldAvailable;
                    synchronized (TorchService.this) {
                    synchronized (TorchService.this) {
                        changed = mTorchAvailable != available;
                        oldAvailable = mTorchAvailable;
                        mTorchAvailable = available;
                        mTorchAvailable = available;
                    }
                    }
                    if (changed) {
                    if (oldAvailable != available) {
                        if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
                        if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")");
                        dispatchAvailabilityChanged(available);
                        dispatchAvailabilityChanged(available);
                    }
                    }