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

Commit bfc9915f authored by Igor Murashkin's avatar Igor Murashkin
Browse files

Camera: Drop ProCamera connections when a Camera connection happens

* Also adds an ICameraServiceListener with available/not available statuses

Bug: 8291653
Change-Id: I24680f1a2dc109510caf451cf7c7bd180b670d84
parent 3fa4891f
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@ LOCAL_SRC_FILES:= \
	ICamera.cpp \
	ICamera.cpp \
	ICameraClient.cpp \
	ICameraClient.cpp \
	ICameraService.cpp \
	ICameraService.cpp \
	ICameraServiceListener.cpp \
	ICameraRecordingProxy.cpp \
	ICameraRecordingProxy.cpp \
	ICameraRecordingProxyListener.cpp \
	ICameraRecordingProxyListener.cpp \
	IProCameraUser.cpp \
	IProCameraUser.cpp \
+16 −0
Original line number Original line Diff line number Diff line
@@ -231,6 +231,22 @@ status_t CameraBase<TCam, TCamTraits>::getCameraInfo(int cameraId,
    return cs->getCameraInfo(cameraId, cameraInfo);
    return cs->getCameraInfo(cameraId, cameraInfo);
}
}


template <typename TCam, typename TCamTraits>
status_t CameraBase<TCam, TCamTraits>::addServiceListener(
                            const sp<ICameraServiceListener>& listener) {
    const sp<ICameraService>& cs = getCameraService();
    if (cs == 0) return UNKNOWN_ERROR;
    return cs->addListener(listener);
}

template <typename TCam, typename TCamTraits>
status_t CameraBase<TCam, TCamTraits>::removeServiceListener(
                            const sp<ICameraServiceListener>& listener) {
    const sp<ICameraService>& cs = getCameraService();
    if (cs == 0) return UNKNOWN_ERROR;
    return cs->removeListener(listener);
}

template class CameraBase<ProCamera>;
template class CameraBase<ProCamera>;
template class CameraBase<Camera>;
template class CameraBase<Camera>;


+33 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>


#include <camera/ICameraService.h>
#include <camera/ICameraService.h>
#include <camera/ICameraServiceListener.h>
#include <camera/IProCameraUser.h>
#include <camera/IProCameraUser.h>
#include <camera/IProCameraCallbacks.h>
#include <camera/IProCameraCallbacks.h>
#include <camera/ICamera.h>
#include <camera/ICamera.h>
@@ -86,6 +87,24 @@ public:
        remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
        remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
        return interface_cast<IProCameraUser>(reply.readStrongBinder());
        return interface_cast<IProCameraUser>(reply.readStrongBinder());
    }
    }

    virtual status_t addListener(const sp<ICameraServiceListener>& listener)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(listener->asBinder());
        remote()->transact(BnCameraService::ADD_LISTENER, data, &reply);
        return reply.readInt32();
    }

    virtual status_t removeListener(const sp<ICameraServiceListener>& listener)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(listener->asBinder());
        remote()->transact(BnCameraService::REMOVE_LISTENER, data, &reply);
        return reply.readInt32();
    }
};
};


IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
@@ -134,6 +153,20 @@ status_t BnCameraService::onTransact(
            reply->writeStrongBinder(camera->asBinder());
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case ADD_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeInt32(addListener(listener));
            return NO_ERROR;
        } break;
        case REMOVE_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeInt32(removeListener(listener));
            return NO_ERROR;
        } break;
        default:
        default:
            return BBinder::onTransact(code, data, reply, flags);
            return BBinder::onTransact(code, data, reply, flags);
    }
    }
+86 −0
Original line number Original line Diff line number Diff line
/*
**
** Copyright 2013, 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.
*/

#include <stdint.h>
#include <sys/types.h>

#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>

#include <camera/ICameraServiceListener.h>

namespace android {

namespace {
    enum {
        STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
    };
}; // namespace anonymous

class BpCameraServiceListener: public BpInterface<ICameraServiceListener>
{

public:
    BpCameraServiceListener(const sp<IBinder>& impl)
        : BpInterface<ICameraServiceListener>(impl)
    {
    }

    virtual void onStatusChanged(Status status, int32_t cameraId)
    {
        Parcel data, reply;
        data.writeInterfaceToken(
                              ICameraServiceListener::getInterfaceDescriptor());

        data.writeInt32(static_cast<int32_t>(status));
        data.writeInt32(cameraId);

        remote()->transact(STATUS_CHANGED,
                           data,
                           &reply,
                           IBinder::FLAG_ONEWAY);
    }
};

IMPLEMENT_META_INTERFACE(CameraServiceListener,
                         "android.hardware.ICameraServiceListener");

// ----------------------------------------------------------------------

status_t BnCameraServiceListener::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case STATUS_CHANGED: {
            CHECK_INTERFACE(ICameraServiceListener, data, reply);

            Status status = static_cast<Status>(data.readInt32());
            int32_t cameraId = data.readInt32();

            onStatusChanged(status, cameraId);

            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

// ----------------------------------------------------------------------------

}; // namespace android
+138 −12
Original line number Original line Diff line number Diff line
@@ -33,6 +33,8 @@
#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
#include <camera/CameraMetadata.h>
#include <camera/CameraMetadata.h>


#include <camera/ICameraServiceListener.h>

namespace android {
namespace android {
namespace camera2 {
namespace camera2 {
namespace tests {
namespace tests {
@@ -48,9 +50,9 @@ namespace client {
#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16
#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16


// defaults for display "test"
// defaults for display "test"
#define TEST_DISPLAY_FORMAT HAL_PIXEL_FORMAT_Y16
#define TEST_DISPLAY_FORMAT HAL_PIXEL_FORMAT_Y8
#define TEST_DISPLAY_WIDTH 1280
#define TEST_DISPLAY_WIDTH 320
#define TEST_DISPLAY_HEIGHT 960
#define TEST_DISPLAY_HEIGHT 240


#define TEST_CPU_FRAME_COUNT 2
#define TEST_CPU_FRAME_COUNT 2
#define TEST_CPU_HEAP_COUNT 5
#define TEST_CPU_HEAP_COUNT 5
@@ -68,6 +70,52 @@ namespace client {


class ProCameraTest;
class ProCameraTest;


struct ServiceListener : public BnCameraServiceListener {

    ServiceListener() :
        mLatestStatus(STATUS_UNKNOWN),
        mPrevStatus(STATUS_UNKNOWN)
    {
    }

    void onStatusChanged(Status status, int32_t cameraId) {
        dout << "On status changed: 0x" << std::hex
             << status << " cameraId " << cameraId
             << std::endl;

        Mutex::Autolock al(mMutex);

        mLatestStatus = status;
        mCondition.broadcast();
    }

    status_t waitForStatusChange(Status& newStatus) {
        Mutex::Autolock al(mMutex);

        if (mLatestStatus != mPrevStatus) {
            newStatus = mLatestStatus;
            mPrevStatus = mLatestStatus;
            return OK;
        }

        status_t stat = mCondition.waitRelative(mMutex,
                                               TEST_LISTENER_TIMEOUT);

        if (stat == OK) {
            newStatus = mLatestStatus;
            mPrevStatus = mLatestStatus;
        }

        return stat;
    }

    Condition mCondition;
    Mutex mMutex;

    Status mLatestStatus;
    Status mPrevStatus;
};

enum ProEvent {
enum ProEvent {
    UNKNOWN,
    UNKNOWN,
    ACQUIRED,
    ACQUIRED,
@@ -441,7 +489,6 @@ protected:
        }
        }
        request.acquire(requestTmp);
        request.acquire(requestTmp);
    }
    }

};
};


sp<Thread> ProCameraTest::mTestThread;
sp<Thread> ProCameraTest::mTestThread;
@@ -538,18 +585,52 @@ TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
    }
    }


    int depthStreamId = -1;
    int depthStreamId = -1;
    EXPECT_OK(mCamera->createStream(mDisplayW, mDisplayH, mDisplayFmt, surface,

    sp<ServiceListener> listener = new ServiceListener();
    EXPECT_OK(ProCamera::addServiceListener(listener));

    ServiceListener::Status currentStatus = ServiceListener::STATUS_AVAILABLE;

    dout << "Will now stream and resume infinitely..." << std::endl;
    while (true) {

        if (currentStatus == ServiceListener::STATUS_AVAILABLE) {

            EXPECT_OK(mCamera->createStream(mDisplayW, mDisplayH, mDisplayFmt,
                                            surface,
                                            &depthStreamId));
                                            &depthStreamId));
            EXPECT_NE(-1, depthStreamId);
            EXPECT_NE(-1, depthStreamId);


            EXPECT_OK(mCamera->exclusiveTryLock());
            EXPECT_OK(mCamera->exclusiveTryLock());


            uint8_t streams[] = { depthStreamId };
            uint8_t streams[] = { depthStreamId };
    ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(streams, /*count*/1));
            ASSERT_NO_FATAL_FAILURE(createSubmitRequestForStreams(
                                                 streams,
                                                 /*count*/1));
        }


    dout << "will sleep now for " << mDisplaySecs << std::endl;
        ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
    sleep(mDisplaySecs);

        // TODO: maybe check for getch every once in a while?
        while (listener->waitForStatusChange(/*out*/stat) != OK);

        if (currentStatus != stat) {
            if (stat == ServiceListener::STATUS_AVAILABLE) {
                dout << "Reconnecting to camera" << std::endl;
                mCamera = ProCamera::connect(CAMERA_ID);
            } else if (stat == ServiceListener::STATUS_NOT_AVAILABLE) {
                dout << "Disconnecting from camera" << std::endl;
                mCamera->disconnect();
            } else {
                dout << "Unknown status change "
                     << std::hex << stat << std::endl;
            }


            currentStatus = stat;
        }
    }

    EXPECT_OK(ProCamera::removeServiceListener(listener));
    EXPECT_OK(mCamera->deleteStream(depthStreamId));
    EXPECT_OK(mCamera->deleteStream(depthStreamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
    EXPECT_OK(mCamera->exclusiveUnlock());
}
}
@@ -1035,6 +1116,51 @@ TEST_F(ProCameraTest, WaitForSingleStreamBufferAndDropFrames) {






//TODO: refactor into separate file
TEST_F(ProCameraTest, ServiceListenersSubscribe) {

    ASSERT_EQ(4u, sizeof(ServiceListener::Status));

    sp<ServiceListener> listener = new ServiceListener();

    EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
    EXPECT_OK(ProCamera::addServiceListener(listener));

    EXPECT_EQ(ALREADY_EXISTS, ProCamera::addServiceListener(listener));
    EXPECT_OK(ProCamera::removeServiceListener(listener));

    EXPECT_EQ(BAD_VALUE, ProCamera::removeServiceListener(listener));
}

//TODO: refactor into separate file
TEST_F(ProCameraTest, ServiceListenersFunctional) {

    sp<ServiceListener> listener = new ServiceListener();

    EXPECT_OK(ProCamera::addServiceListener(listener));

    sp<Camera> cam = Camera::connect(CAMERA_ID,
                                     /*clientPackageName*/String16(),
                                     -1);
    EXPECT_NE((void*)NULL, cam.get());

    ServiceListener::Status stat = ServiceListener::STATUS_UNKNOWN;
    EXPECT_OK(listener->waitForStatusChange(/*out*/stat));

    EXPECT_EQ(ServiceListener::STATUS_NOT_AVAILABLE, stat);

    if (cam.get()) {
        cam->disconnect();
    }

    EXPECT_OK(listener->waitForStatusChange(/*out*/stat));
    EXPECT_EQ(ServiceListener::STATUS_AVAILABLE, stat);

    EXPECT_OK(ProCamera::removeServiceListener(listener));
}



}
}
}
}
}
}
Loading