| /* |
| ** |
| ** Copyright (C) 2008, 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. |
| */ |
| |
| #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H |
| #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H |
| |
| #include <utils/Vector.h> |
| #include <binder/AppOpsManager.h> |
| #include <binder/BinderService.h> |
| #include <binder/IAppOpsCallback.h> |
| #include <camera/ICameraService.h> |
| #include <hardware/camera.h> |
| |
| #include <camera/ICamera.h> |
| #include <camera/ICameraClient.h> |
| #include <camera/IProCameraUser.h> |
| #include <camera/IProCameraCallbacks.h> |
| |
| #include <camera/ICameraServiceListener.h> |
| |
| /* This needs to be increased if we can have more cameras */ |
| #define MAX_CAMERAS 2 |
| |
| namespace android { |
| |
| extern volatile int32_t gLogLevel; |
| |
| class MemoryHeapBase; |
| class MediaPlayer; |
| |
| class CameraService : |
| public BinderService<CameraService>, |
| public BnCameraService, |
| public IBinder::DeathRecipient, |
| public camera_module_callbacks_t |
| { |
| friend class BinderService<CameraService>; |
| public: |
| class Client; |
| class BasicClient; |
| |
| // Implementation of BinderService<T> |
| static char const* getServiceName() { return "media.camera"; } |
| |
| CameraService(); |
| virtual ~CameraService(); |
| |
| ///////////////////////////////////////////////////////////////////// |
| // HAL Callbacks |
| virtual void onDeviceStatusChanged(int cameraId, |
| int newStatus); |
| |
| ///////////////////////////////////////////////////////////////////// |
| // ICameraService |
| virtual int32_t getNumberOfCameras(); |
| virtual status_t getCameraInfo(int cameraId, |
| struct CameraInfo* cameraInfo); |
| |
| virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId, |
| const String16& clientPackageName, int clientUid); |
| virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb, |
| int cameraId, const String16& clientPackageName, int clientUid); |
| |
| virtual status_t addListener(const sp<ICameraServiceListener>& listener); |
| virtual status_t removeListener( |
| const sp<ICameraServiceListener>& listener); |
| |
| // Extra permissions checks |
| virtual status_t onTransact(uint32_t code, const Parcel& data, |
| Parcel* reply, uint32_t flags); |
| |
| virtual status_t dump(int fd, const Vector<String16>& args); |
| |
| ///////////////////////////////////////////////////////////////////// |
| // Client functionality |
| virtual void removeClientByRemote(const wp<IBinder>& remoteBinder); |
| |
| enum sound_kind { |
| SOUND_SHUTTER = 0, |
| SOUND_RECORDING = 1, |
| NUM_SOUNDS |
| }; |
| |
| void loadSound(); |
| void playSound(sound_kind kind); |
| void releaseSound(); |
| |
| |
| ///////////////////////////////////////////////////////////////////// |
| // CameraClient functionality |
| |
| // returns plain pointer of client. Note that mClientLock should be acquired to |
| // prevent the client from destruction. The result can be NULL. |
| virtual Client* getClientByIdUnsafe(int cameraId); |
| virtual Mutex* getClientLockById(int cameraId); |
| |
| class BasicClient : public virtual RefBase { |
| public: |
| virtual status_t initialize(camera_module_t *module) = 0; |
| |
| virtual void disconnect() = 0; |
| |
| // Return the remote callback binder object (e.g. IProCameraCallbacks) |
| wp<IBinder> getRemote() { |
| return mRemoteBinder; |
| } |
| |
| protected: |
| BasicClient(const sp<CameraService>& cameraService, |
| const sp<IBinder>& remoteCallback, |
| const String16& clientPackageName, |
| int cameraId, |
| int cameraFacing, |
| int clientPid, |
| uid_t clientUid, |
| int servicePid); |
| |
| virtual ~BasicClient(); |
| |
| // the instance is in the middle of destruction. When this is set, |
| // the instance should not be accessed from callback. |
| // CameraService's mClientLock should be acquired to access this. |
| // - subclasses should set this to true in their destructors. |
| bool mDestructionStarted; |
| |
| // these are initialized in the constructor. |
| sp<CameraService> mCameraService; // immutable after constructor |
| int mCameraId; // immutable after constructor |
| int mCameraFacing; // immutable after constructor |
| const String16 mClientPackageName; |
| pid_t mClientPid; |
| uid_t mClientUid; // immutable after constructor |
| pid_t mServicePid; // immutable after constructor |
| |
| // - The app-side Binder interface to receive callbacks from us |
| wp<IBinder> mRemoteBinder; // immutable after constructor |
| |
| // permissions management |
| status_t startCameraOps(); |
| status_t finishCameraOps(); |
| |
| // Notify client about a fatal error |
| virtual void notifyError() = 0; |
| private: |
| AppOpsManager mAppOpsManager; |
| |
| class OpsCallback : public BnAppOpsCallback { |
| public: |
| OpsCallback(wp<BasicClient> client); |
| virtual void opChanged(int32_t op, const String16& packageName); |
| |
| private: |
| wp<BasicClient> mClient; |
| |
| }; // class OpsCallback |
| |
| sp<OpsCallback> mOpsCallback; |
| // Track whether startCameraOps was called successfully, to avoid |
| // finishing what we didn't start. |
| bool mOpsActive; |
| |
| // IAppOpsCallback interface, indirected through opListener |
| virtual void opChanged(int32_t op, const String16& packageName); |
| }; // class BasicClient |
| |
| class Client : public BnCamera, public BasicClient |
| { |
| public: |
| typedef ICameraClient TCamCallbacks; |
| |
| // ICamera interface (see ICamera for details) |
| virtual void disconnect(); |
| virtual status_t connect(const sp<ICameraClient>& client) = 0; |
| virtual status_t lock() = 0; |
| virtual status_t unlock() = 0; |
| virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0; |
| virtual status_t setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer)=0; |
| virtual void setPreviewCallbackFlag(int flag) = 0; |
| virtual status_t startPreview() = 0; |
| virtual void stopPreview() = 0; |
| virtual bool previewEnabled() = 0; |
| virtual status_t storeMetaDataInBuffers(bool enabled) = 0; |
| virtual status_t startRecording() = 0; |
| virtual void stopRecording() = 0; |
| virtual bool recordingEnabled() = 0; |
| virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0; |
| virtual status_t autoFocus() = 0; |
| virtual status_t cancelAutoFocus() = 0; |
| virtual status_t takePicture(int msgType) = 0; |
| virtual status_t setParameters(const String8& params) = 0; |
| virtual String8 getParameters() const = 0; |
| virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0; |
| |
| // Interface used by CameraService |
| Client(const sp<CameraService>& cameraService, |
| const sp<ICameraClient>& cameraClient, |
| const String16& clientPackageName, |
| int cameraId, |
| int cameraFacing, |
| int clientPid, |
| uid_t clientUid, |
| int servicePid); |
| ~Client(); |
| |
| // return our camera client |
| const sp<ICameraClient>& getRemoteCallback() { |
| return mRemoteCallback; |
| } |
| |
| protected: |
| static Mutex* getClientLockFromCookie(void* user); |
| // convert client from cookie. Client lock should be acquired before getting Client. |
| static Client* getClientFromCookie(void* user); |
| |
| virtual void notifyError(); |
| |
| // Initialized in constructor |
| |
| // - The app-side Binder interface to receive callbacks from us |
| sp<ICameraClient> mRemoteCallback; |
| |
| }; // class Client |
| |
| class ProClient : public BnProCameraUser, public BasicClient { |
| public: |
| typedef IProCameraCallbacks TCamCallbacks; |
| |
| ProClient(const sp<CameraService>& cameraService, |
| const sp<IProCameraCallbacks>& remoteCallback, |
| const String16& clientPackageName, |
| int cameraId, |
| int cameraFacing, |
| int clientPid, |
| uid_t clientUid, |
| int servicePid); |
| |
| virtual ~ProClient(); |
| |
| const sp<IProCameraCallbacks>& getRemoteCallback() { |
| return mRemoteCallback; |
| } |
| |
| /*** |
| IProCamera implementation |
| ***/ |
| virtual status_t connect(const sp<IProCameraCallbacks>& callbacks) |
| = 0; |
| virtual status_t exclusiveTryLock() = 0; |
| virtual status_t exclusiveLock() = 0; |
| virtual status_t exclusiveUnlock() = 0; |
| |
| virtual bool hasExclusiveLock() = 0; |
| |
| // Note that the callee gets a copy of the metadata. |
| virtual int submitRequest(camera_metadata_t* metadata, |
| bool streaming = false) = 0; |
| virtual status_t cancelRequest(int requestId) = 0; |
| |
| // Callbacks from camera service |
| virtual void onExclusiveLockStolen() = 0; |
| |
| protected: |
| virtual void notifyError(); |
| |
| sp<IProCameraCallbacks> mRemoteCallback; |
| }; // class ProClient |
| |
| private: |
| |
| // Delay-load the Camera HAL module |
| virtual void onFirstRef(); |
| |
| // Step 1. Check if we can connect, before we acquire the service lock. |
| bool validateConnect(int cameraId, |
| /*inout*/ |
| int& clientUid) const; |
| |
| // Step 2. Check if we can connect, after we acquire the service lock. |
| bool canConnectUnsafe(int cameraId, |
| const String16& clientPackageName, |
| const sp<IBinder>& remoteCallback, |
| /*out*/ |
| sp<Client> &client); |
| |
| // When connection is successful, initialize client and track its death |
| bool connectFinishUnsafe(const sp<BasicClient>& client, |
| const sp<IBinder>& clientBinder); |
| |
| virtual sp<BasicClient> getClientByRemote(const wp<IBinder>& cameraClient); |
| |
| Mutex mServiceLock; |
| wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock |
| Mutex mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks |
| int mNumberOfCameras; |
| |
| typedef wp<ProClient> weak_pro_client_ptr; |
| Vector<weak_pro_client_ptr> mProClientList[MAX_CAMERAS]; |
| |
| // needs to be called with mServiceLock held |
| sp<Client> findClientUnsafe(const wp<IBinder>& cameraClient, int& outIndex); |
| sp<ProClient> findProClientUnsafe( |
| const wp<IBinder>& cameraCallbacksRemote); |
| |
| // atomics to record whether the hardware is allocated to some client. |
| volatile int32_t mBusy[MAX_CAMERAS]; |
| void setCameraBusy(int cameraId); |
| void setCameraFree(int cameraId); |
| |
| // sounds |
| MediaPlayer* newMediaPlayer(const char *file); |
| |
| Mutex mSoundLock; |
| sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS]; |
| int mSoundRef; // reference count (release all MediaPlayer when 0) |
| |
| camera_module_t *mModule; |
| |
| Vector<sp<ICameraServiceListener> > |
| mListenerList; |
| |
| // guard only mStatusList and the broadcasting of ICameraServiceListener |
| mutable Mutex mStatusMutex; |
| ICameraServiceListener::Status |
| mStatusList[MAX_CAMERAS]; |
| |
| // Read the current status (locks mStatusMutex) |
| ICameraServiceListener::Status |
| getStatus(int cameraId) const; |
| |
| // Broadcast the new status if it changed (locks the service mutex) |
| void updateStatus( |
| ICameraServiceListener::Status status, |
| int32_t cameraId); |
| // Call this one when the service mutex is already held (idempotent) |
| void updateStatusUnsafe( |
| ICameraServiceListener::Status status, |
| int32_t cameraId); |
| |
| // IBinder::DeathRecipient implementation |
| virtual void binderDied(const wp<IBinder> &who); |
| |
| // Helpers |
| int getDeviceVersion(int cameraId, int* facing); |
| |
| bool isValidCameraId(int cameraId); |
| }; |
| |
| } // namespace android |
| |
| #endif |