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

Commit 9c1f93a2 authored by Roman Birg's avatar Roman Birg Committed by Steve Kondik
Browse files

frameworks: implement system-wide Torch service



Allows Torch and any camera to coexist peacefully. When torch is active
and a camera is opened, the torch will be first shut down, and the
camera will be allowed to continue opening, instead of displaying
"Cannot connect to camera."

Also a squash of the following commits:

    add framework torch service

    Change-Id: I0c7a055b33fdebe697f23d207b20408e06eb74a8
    Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
    Fully fix interaction between torch and camera usage.

    For doing this, two things are necessary:
    - The torch shutdown needs to be synchronous, so that the torch app has
      a chance to release the camera before the camera app tries to use it.
    - The torch service needs to track camera usage, so that it can notify
      the torch app if a camera is busy.

    Change-Id: I521091d255ff4c251d97a0e8d65c9d2a80b9dae4

    Fix camera usage tracking.

    When a Camera object is finalized, it notifies the torch service that
    it's no longer using the camera. This call used to not check whether the
    caller actually is still using the camera and called release() before,
    so depending on timing of the finalizer, it could happen that e.g. the
    camera app released the camera user record of the torch app, leading to
    the torch usage not being detected on next usage of the camera app.

    Fix that by checking whether the caller of onCameraClosed() actually
    owned the camera prior to releasing the record.
    Also fix synchronization between accesses.

    Change-Id: Ic01cbc3c89ab8d855e4613bfa1b2f548de919b73

    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>

    frameworks: move TorchService to new services location

    Change-Id: I392f37dfefe41686388811069999eb031f7eb92c
    Signed-off-by: default avatarRoman Birg <roman@cyngn.com>

Change-Id: I37a265ec98391936a6c19e8bcdf8da1efb57d45d
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent 59ab9535
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -160,6 +160,8 @@ LOCAL_SRC_FILES += \
	core/java/android/hardware/IConsumerIrService.aidl \
	core/java/android/hardware/IProCameraUser.aidl \
	core/java/android/hardware/IProCameraCallbacks.aidl \
	core/java/android/hardware/ITorchService.aidl \
	core/java/android/hardware/ITorchCallback.aidl \
	core/java/android/hardware/camera2/ICameraDeviceUser.aidl \
	core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
	core/java/android/hardware/ISerialManager.aidl \
+10 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.app.usage.UsageStatsManager;
import android.appwidget.AppWidgetManager;
import android.content.res.IThemeService;
import android.content.res.ThemeManager;
import android.hardware.ITorchService;
import android.hardware.TorchManager;
import android.os.Build;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
@@ -785,6 +787,14 @@ class ContextImpl extends Context {
                return new ThemeManager(ctx.getOuterContext(),
                        service);
            }});

        registerService(TORCH_SERVICE, new ServiceFetcher() {
            public Object createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(TORCH_SERVICE);
                ITorchService service = ITorchService.Stub.asInterface(b);
                final Context outerContext = ctx.getOuterContext();
                return new TorchManager(outerContext, service);
            }});
    }

    static ContextImpl getImpl(Context context) {
+10 −0
Original line number Diff line number Diff line
@@ -2937,6 +2937,16 @@ public abstract class Context {
     */
    public static final String MEDIA_PROJECTION_SERVICE = "media_projection";

    /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link com.android.server.TorchService} for accessing torch service.
     *
     * @see #getSystemService
     * @see com.android.server.TorchService
     * @hide
     */
    public static final String TORCH_SERVICE = "torch";

    /**
     * Determine whether the given permission is allowed for a particular
     * process and user ID running in the system.
+24 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.media.IAudioService;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -160,6 +161,7 @@ public class Camera {
    /* ### QC ADD-ONS: END */

    private long mNativeContext; // accessed by native methods
    private int mCameraId;
    private EventHandler mEventHandler;
    private ShutterCallback mShutterCallback;
    private PictureCallback mRawImageCallback;
@@ -189,6 +191,7 @@ public class Camera {
    private CameraDataCallback mCameraDataCallback;
    private CameraMetaDataCallback mCameraMetaDataCallback;
    /* ### QC ADD-ONS: END */
    private Binder mTorchToken;

    /**
     * Broadcast Action:  A new picture is taken by the camera, and the entry of
@@ -463,6 +466,7 @@ public class Camera {
    }

    private int cameraInitVersion(int cameraId, int halVersion) {
        mCameraId = cameraId;
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
@@ -474,6 +478,7 @@ public class Camera {
        mCameraDataCallback = null;
        mCameraMetaDataCallback = null;
        /* ### QC ADD-ONS: END */
        mTorchToken = new Binder();

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
@@ -485,7 +490,11 @@ public class Camera {
        }

        String packageName = ActivityThread.currentPackageName();
        if (packageName == null && android.os.Process.SYSTEM_UID == Binder.getCallingUid()) {
            packageName = "android";
        }

        notifyTorch(true);
        return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName);
    }

@@ -548,6 +557,20 @@ public class Camera {
    Camera() {
    }

    private void notifyTorch(boolean inUse) {
        IBinder b = ServiceManager.getService(Context.TORCH_SERVICE);
        ITorchService torchService = ITorchService.Stub.asInterface(b);
        try {
            if (inUse) {
                torchService.onCameraOpened(mTorchToken, mCameraId);
            } else {
                torchService.onCameraClosed(mTorchToken, mCameraId);
            }
        } catch (RemoteException e) {
            // Ignore
        }
    }

    @Override
    protected void finalize() {
        release();
@@ -567,6 +590,7 @@ public class Camera {
    public final void release() {
        native_release();
        mFaceDetectionRunning = false;
        notifyTorch(false);
    }

    /**
+39 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2015, The CyanogenMod 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;


/**
 * {@hide}
 */
oneway interface ITorchCallback {
     /**
      * Called when the flashlight turns off unexpectedly.
      */
     void onTorchOff();

     /**
      * Called when there is an error that turns the flashlight off.
      */
     void onTorchError();

     /**
      * Called when there is a change in availability of the flashlight functionality
      * @param available true if the flashlight is currently available.
      */
     void onTorchAvailabilityChanged(boolean available);
 }
Loading