CameraService: Notify camera service proxy of device status

Send the camera proxy service in system server updates to
camera device state: opened/closed/active/idle.

Bug: 23393557
Change-Id: Id7c70f134821efa34af8f6e7b4caa4c2ab128ebc
diff --git a/camera/ICameraServiceProxy.cpp b/camera/ICameraServiceProxy.cpp
index 06a5afb..694e9c3 100644
--- a/camera/ICameraServiceProxy.cpp
+++ b/camera/ICameraServiceProxy.cpp
@@ -29,11 +29,21 @@
     BpCameraServiceProxy(const sp<IBinder>& impl) : BpInterface<ICameraServiceProxy>(impl) {}
 
     virtual void pingForUserUpdate() {
-        Parcel data, reply;
+        Parcel data;
         data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor());
-        remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, &reply,
+        remote()->transact(BnCameraServiceProxy::PING_FOR_USER_UPDATE, data, nullptr,
                 IBinder::FLAG_ONEWAY);
     }
+
+    virtual void notifyCameraState(String16 cameraId, CameraState newCameraState) {
+        Parcel data;
+        data.writeInterfaceToken(ICameraServiceProxy::getInterfaceDescriptor());
+        data.writeString16(cameraId);
+        data.writeInt32(newCameraState);
+        remote()->transact(BnCameraServiceProxy::NOTIFY_CAMERA_STATE, data, nullptr,
+                IBinder::FLAG_ONEWAY);
+    }
+
 };
 
 
@@ -47,9 +57,16 @@
             pingForUserUpdate();
             return NO_ERROR;
         } break;
+        case NOTIFY_CAMERA_STATE: {
+            CHECK_INTERFACE(ICameraServiceProxy, data, reply);
+            String16 cameraId = data.readString16();
+            CameraState newCameraState =
+                static_cast<CameraState>(data.readInt32());
+            notifyCameraState(cameraId, newCameraState);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
 }
 }; // namespace android
-
diff --git a/include/camera/ICameraServiceProxy.h b/include/camera/ICameraServiceProxy.h
index 12a555f..2613c01 100644
--- a/include/camera/ICameraServiceProxy.h
+++ b/include/camera/ICameraServiceProxy.h
@@ -23,15 +23,30 @@
 
 namespace android {
 
+/**
+ * Interface from native camera service to managed-side camera service proxy.
+ *
+ * Keep in sync with frameworks/base/core/java/android/hardware/ICameraServiceProxy.aidl
+ *
+ */
 class ICameraServiceProxy : public IInterface {
 public:
     enum {
         PING_FOR_USER_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
+        NOTIFY_CAMERA_STATE
+    };
+
+    enum CameraState {
+        CAMERA_STATE_OPEN,
+        CAMERA_STATE_ACTIVE,
+        CAMERA_STATE_IDLE,
+        CAMERA_STATE_CLOSED
     };
 
     DECLARE_META_INTERFACE(CameraServiceProxy);
 
     virtual void pingForUserUpdate() = 0;
+    virtual void notifyCameraState(String16 cameraId, CameraState newCameraState) = 0;
 };
 
 class BnCameraServiceProxy: public BnInterface<ICameraServiceProxy>
@@ -48,5 +63,3 @@
 }; // namespace android
 
 #endif // ANDROID_HARDWARE_ICAMERASERVICEPROXY_H
-
-
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 43a8ec4..7128df7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -33,7 +33,6 @@
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/ProcessInfoService.h>
-#include <camera/ICameraServiceProxy.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 #include <gui/Surface.h>
@@ -250,13 +249,19 @@
     CameraService::pingCameraServiceProxy();
 }
 
-void CameraService::pingCameraServiceProxy() {
+sp<ICameraServiceProxy> CameraService::getCameraServiceProxy() {
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16("media.camera.proxy"));
     if (binder == nullptr) {
-        return;
+        return nullptr;
     }
     sp<ICameraServiceProxy> proxyBinder = interface_cast<ICameraServiceProxy>(binder);
+    return proxyBinder;
+}
+
+void CameraService::pingCameraServiceProxy() {
+    sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+    if (proxyBinder == nullptr) return;
     proxyBinder->pingForUserUpdate();
 }
 
@@ -1948,6 +1953,10 @@
     mCameraService->updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
             String8::format("%d", mCameraId));
 
+    // Transition device state to OPEN
+    mCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_OPEN,
+            String8::format("%d", mCameraId));
+
     return OK;
 }
 
@@ -1966,6 +1975,10 @@
         mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
                 String8::format("%d", mCameraId), rejected);
 
+        // Transition device state to CLOSED
+        mCameraService->updateProxyDeviceState(ICameraServiceProxy::CAMERA_STATE_CLOSED,
+                String8::format("%d", mCameraId));
+
         // Notify flashlight that a camera device is closed.
         mCameraService->mFlashlight->deviceClosed(
                 String8::format("%d", mCameraId));
@@ -2466,6 +2479,14 @@
         });
 }
 
+void CameraService::updateProxyDeviceState(ICameraServiceProxy::CameraState newState,
+        const String8& cameraId) {
+    sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
+    if (proxyBinder == nullptr) return;
+    String16 id(cameraId);
+    proxyBinder->notifyCameraState(id, newState);
+}
+
 status_t CameraService::getTorchStatusLocked(
         const String8& cameraId,
         ICameraServiceListener::TorchStatus *status) const {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 7f4d43f..894767a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -24,6 +24,7 @@
 #include <binder/BinderService.h>
 #include <binder/IAppOpsCallback.h>
 #include <camera/ICameraService.h>
+#include <camera/ICameraServiceProxy.h>
 #include <hardware/camera.h>
 
 #include <camera/ICamera.h>
@@ -164,6 +165,14 @@
     void                playSound(sound_kind kind);
     void                releaseSound();
 
+    /**
+     * Update the state of a given camera device (open/close/active/idle) with
+     * the camera proxy service in the system service
+     */
+    static void         updateProxyDeviceState(
+            ICameraServiceProxy::CameraState newState,
+            const String8& cameraId);
+
     /////////////////////////////////////////////////////////////////////
     // CameraDeviceFactory functionality
     int                 getDeviceVersion(int cameraId, int* facing = NULL);
@@ -728,6 +737,7 @@
 
     static String8 toString(std::set<userid_t> intSet);
 
+    static sp<ICameraServiceProxy> getCameraServiceProxy();
     static void pingCameraServiceProxy();
 
 };
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 36e99dd..48b5a26 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1912,6 +1912,8 @@
     ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
             __FUNCTION__, resultExtras.requestId, timestamp);
     mCaptureSequencer->notifyShutter(resultExtras, timestamp);
+
+    Camera2ClientBase::notifyShutter(resultExtras, timestamp);
 }
 
 camera2::SharedParameters& Camera2Client::getParameters() {
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index e552633..38e35cd 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -251,6 +251,9 @@
     // Turn off all messages.
     disableMsgType(CAMERA_MSG_ALL_MSGS);
     mHardware->stopPreview();
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
     mHardware->cancelPicture();
     // Release the hardware resources.
     mHardware->release();
@@ -409,7 +412,11 @@
     }
     mHardware->setPreviewWindow(mPreviewWindow);
     result = mHardware->startPreview();
-
+    if (result == NO_ERROR) {
+        mCameraService->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
+            String8::format("%d", mCameraId));
+    }
     return result;
 }
 
@@ -449,7 +456,9 @@
 
     disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
     mHardware->stopPreview();
-
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
     mPreviewBuffer.clear();
 }
 
@@ -790,6 +799,12 @@
     }
     disableMsgType(CAMERA_MSG_SHUTTER);
 
+    // Shutters only happen in response to takePicture, so mark device as
+    // idle now, until preview is restarted
+    mCameraService->updateProxyDeviceState(
+        ICameraServiceProxy::CAMERA_STATE_IDLE,
+        String8::format("%d", mCameraId));
+
     mLock.unlock();
 }
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index f6a0221..0c531c3 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -836,6 +836,7 @@
     if (remoteCb != 0) {
         remoteCb->onDeviceIdle();
     }
+    Camera2ClientBase::notifyIdle();
 }
 
 void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
@@ -845,6 +846,7 @@
     if (remoteCb != 0) {
         remoteCb->onCaptureStarted(resultExtras, timestamp);
     }
+    Camera2ClientBase::notifyShutter(resultExtras, timestamp);
 }
 
 void CameraDeviceClient::notifyPrepared(int streamId) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 0b73f6c..d1e692c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -192,6 +192,7 @@
     Vector<int> mStreamingRequestList;
 
     int32_t mRequestIdCounter;
+
 };
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ba0b264..5732f80 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -55,7 +55,8 @@
         TClientBase(cameraService, remoteCallback, clientPackageName,
                 cameraId, cameraFacing, clientPid, clientUid, servicePid),
         mSharedCameraCallbacks(remoteCallback),
-        mDeviceVersion(cameraService->getDeviceVersion(cameraId))
+        mDeviceVersion(cameraService->getDeviceVersion(cameraId)),
+        mDeviceActive(false)
 {
     ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,
             String8(clientPackageName).string(), clientPid, clientUid);
@@ -235,6 +236,13 @@
 
 template <typename TClientBase>
 void Camera2ClientBase<TClientBase>::notifyIdle() {
+    if (mDeviceActive) {
+        getCameraService()->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_IDLE,
+            String8::format("%d", TClientBase::mCameraId));
+    }
+    mDeviceActive = false;
+
     ALOGV("Camera device is now idle");
 }
 
@@ -244,6 +252,13 @@
     (void)resultExtras;
     (void)timestamp;
 
+    if (!mDeviceActive) {
+        getCameraService()->updateProxyDeviceState(
+            ICameraServiceProxy::CAMERA_STATE_ACTIVE,
+            String8::format("%d", TClientBase::mCameraId));
+    }
+    mDeviceActive = true;
+
     ALOGV("%s: Shutter notification for request id %" PRId32 " at time %" PRId64,
             __FUNCTION__, resultExtras.requestId, timestamp);
 }
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index f1cacdf..220c5ad 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -136,6 +136,8 @@
     status_t              checkPid(const char *checkLocation) const;
 
     virtual void          detachDevice();
+
+    bool                  mDeviceActive;
 };
 
 }; // namespace android