| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2012 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
|  | 17 | #define LOG_TAG "CameraClient" | 
|  | 18 | //#define LOG_NDEBUG 0 | 
|  | 19 |  | 
| Mathias Agopian | 05d19b0 | 2017-02-28 16:28:19 -0800 | [diff] [blame] | 20 | #include <cutils/atomic.h> | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 21 | #include <cutils/properties.h> | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 22 | #include <gui/Surface.h> | 
| Chien-Yu Chen | 2d13b1d | 2016-04-28 12:11:20 -0700 | [diff] [blame] | 23 | #include <media/hardware/HardwareAPI.h> | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 24 |  | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 25 | #include "api1/CameraClient.h" | 
|  | 26 | #include "device1/CameraHardwareInterface.h" | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 27 | #include "CameraService.h" | 
|  | 28 |  | 
|  | 29 | namespace android { | 
|  | 30 |  | 
|  | 31 | #define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__); | 
|  | 32 | #define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__); | 
|  | 33 |  | 
|  | 34 | static int getCallingPid() { | 
|  | 35 | return IPCThreadState::self()->getCallingPid(); | 
|  | 36 | } | 
|  | 37 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 38 | CameraClient::CameraClient(const sp<CameraService>& cameraService, | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 39 | const sp<hardware::ICameraClient>& cameraClient, | 
| Eino-Ville Talvala | ceb388d | 2013-02-19 10:40:14 -0800 | [diff] [blame] | 40 | const String16& clientPackageName, | 
|  | 41 | int cameraId, int cameraFacing, | 
|  | 42 | int clientPid, int clientUid, | 
| Igor Murashkin | a858ea0 | 2014-08-19 14:53:08 -0700 | [diff] [blame] | 43 | int servicePid, bool legacyMode): | 
| Eino-Ville Talvala | ceb388d | 2013-02-19 10:40:14 -0800 | [diff] [blame] | 44 | Client(cameraService, cameraClient, clientPackageName, | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 45 | String8::format("%d", cameraId), cameraFacing, clientPid, | 
|  | 46 | clientUid, servicePid) | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 47 | { | 
|  | 48 | int callingPid = getCallingPid(); | 
|  | 49 | LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId); | 
|  | 50 |  | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 51 | mHardware = NULL; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 52 | mMsgEnabled = 0; | 
|  | 53 | mSurface = 0; | 
|  | 54 | mPreviewWindow = 0; | 
|  | 55 | mDestructionStarted = false; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 56 |  | 
|  | 57 | // Callback is disabled by default | 
|  | 58 | mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; | 
|  | 59 | mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT); | 
| Igor Murashkin | a858ea0 | 2014-08-19 14:53:08 -0700 | [diff] [blame] | 60 | mLegacyMode = legacyMode; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 61 | mPlayShutterSound = true; | 
|  | 62 | LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId); | 
|  | 63 | } | 
|  | 64 |  | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 65 | status_t CameraClient::initialize(sp<CameraProviderManager> manager) { | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 66 | int callingPid = getCallingPid(); | 
| Eino-Ville Talvala | ceb388d | 2013-02-19 10:40:14 -0800 | [diff] [blame] | 67 | status_t res; | 
|  | 68 |  | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 69 | LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); | 
|  | 70 |  | 
| Eino-Ville Talvala | ceb388d | 2013-02-19 10:40:14 -0800 | [diff] [blame] | 71 | // Verify ops permissions | 
|  | 72 | res = startCameraOps(); | 
|  | 73 | if (res != OK) { | 
|  | 74 | return res; | 
|  | 75 | } | 
|  | 76 |  | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 77 | char camera_device_name[10]; | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 78 | snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); | 
|  | 79 |  | 
|  | 80 | mHardware = new CameraHardwareInterface(camera_device_name); | 
| Emilian Peev | f53f66e | 2017-04-11 14:29:43 +0100 | [diff] [blame] | 81 | res = mHardware->initialize(manager); | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 82 | if (res != OK) { | 
|  | 83 | ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", | 
|  | 84 | __FUNCTION__, mCameraId, strerror(-res), res); | 
| Igor Murashkin | 44f120f | 2012-10-09 14:45:37 -0700 | [diff] [blame] | 85 | mHardware.clear(); | 
| Zhijun He | b10cdad | 2014-06-16 16:38:35 -0700 | [diff] [blame] | 86 | return res; | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 87 | } | 
|  | 88 |  | 
|  | 89 | mHardware->setCallbacks(notifyCallback, | 
|  | 90 | dataCallback, | 
|  | 91 | dataCallbackTimestamp, | 
| Yin-Chia Yeh | b5df547 | 2017-03-20 19:32:19 -0700 | [diff] [blame] | 92 | handleCallbackTimestampBatch, | 
| Kévin PETIT | 377b2ec | 2014-02-03 12:35:36 +0000 | [diff] [blame] | 93 | (void *)(uintptr_t)mCameraId); | 
| Eino-Ville Talvala | f69c70d | 2012-05-20 15:59:14 -0700 | [diff] [blame] | 94 |  | 
|  | 95 | // Enable zoom, error, focus, and metadata messages by default | 
|  | 96 | enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS | | 
|  | 97 | CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE); | 
|  | 98 |  | 
|  | 99 | LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); | 
|  | 100 | return OK; | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 104 | // tear down the client | 
|  | 105 | CameraClient::~CameraClient() { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 106 | mDestructionStarted = true; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 107 | int callingPid = getCallingPid(); | 
|  | 108 | LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this); | 
|  | 109 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 110 | disconnect(); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 111 | LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this); | 
|  | 112 | } | 
|  | 113 |  | 
|  | 114 | status_t CameraClient::dump(int fd, const Vector<String16>& args) { | 
| Eino-Ville Talvala | c400396 | 2016-01-13 10:07:04 -0800 | [diff] [blame] | 115 | return BasicClient::dump(fd, args); | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | status_t CameraClient::dumpClient(int fd, const Vector<String16>& args) { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 119 | const size_t SIZE = 256; | 
|  | 120 | char buffer[SIZE]; | 
|  | 121 |  | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 122 | size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) with UID %d\n", | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 123 | mCameraId, | 
| Eino-Ville Talvala | e992e75 | 2014-11-07 16:17:48 -0800 | [diff] [blame] | 124 | (getRemoteCallback() != NULL ? | 
| Marco Nelissen | 06b4606 | 2014-11-14 07:58:25 -0800 | [diff] [blame] | 125 | IInterface::asBinder(getRemoteCallback()).get() : NULL), | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 126 | mClientUid); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 127 | len = (len > SIZE - 1) ? SIZE - 1 : len; | 
|  | 128 | write(fd, buffer, len); | 
| Igor Murashkin | fcf5fea | 2014-09-11 14:43:24 -0700 | [diff] [blame] | 129 |  | 
|  | 130 | len = snprintf(buffer, SIZE, "Latest set parameters:\n"); | 
|  | 131 | len = (len > SIZE - 1) ? SIZE - 1 : len; | 
|  | 132 | write(fd, buffer, len); | 
|  | 133 |  | 
|  | 134 | mLatestSetParameters.dump(fd, args); | 
|  | 135 |  | 
|  | 136 | const char *enddump = "\n\n"; | 
|  | 137 | write(fd, enddump, strlen(enddump)); | 
|  | 138 |  | 
| Yin-Chia Yeh | 9cf785b | 2017-12-01 13:37:30 -0800 | [diff] [blame] | 139 | sp<CameraHardwareInterface> hardware = mHardware; | 
|  | 140 | if (hardware != nullptr) { | 
|  | 141 | return hardware->dump(fd, args); | 
|  | 142 | } | 
|  | 143 | ALOGI("%s: camera device closed already, skip dumping", __FUNCTION__); | 
|  | 144 | return OK; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 145 | } | 
|  | 146 |  | 
|  | 147 | // ---------------------------------------------------------------------------- | 
|  | 148 |  | 
|  | 149 | status_t CameraClient::checkPid() const { | 
|  | 150 | int callingPid = getCallingPid(); | 
| Eino-Ville Talvala | c037920 | 2012-10-09 22:16:58 -0700 | [diff] [blame] | 151 | if (callingPid == mClientPid) return NO_ERROR; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 152 |  | 
|  | 153 | ALOGW("attempt to use a locked camera from a different process" | 
|  | 154 | " (old pid %d, new pid %d)", mClientPid, callingPid); | 
|  | 155 | return EBUSY; | 
|  | 156 | } | 
|  | 157 |  | 
|  | 158 | status_t CameraClient::checkPidAndHardware() const { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 159 | if (mHardware == 0) { | 
|  | 160 | ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid()); | 
|  | 161 | return INVALID_OPERATION; | 
|  | 162 | } | 
| Eino-Ville Talvala | 6192b89 | 2016-04-04 12:31:18 -0700 | [diff] [blame] | 163 | status_t result = checkPid(); | 
|  | 164 | if (result != NO_ERROR) return result; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 165 | return NO_ERROR; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | status_t CameraClient::lock() { | 
|  | 169 | int callingPid = getCallingPid(); | 
|  | 170 | LOG1("lock (pid %d)", callingPid); | 
|  | 171 | Mutex::Autolock lock(mLock); | 
|  | 172 |  | 
|  | 173 | // lock camera to this client if the the camera is unlocked | 
|  | 174 | if (mClientPid == 0) { | 
|  | 175 | mClientPid = callingPid; | 
|  | 176 | return NO_ERROR; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | // returns NO_ERROR if the client already owns the camera, EBUSY otherwise | 
|  | 180 | return checkPid(); | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | status_t CameraClient::unlock() { | 
|  | 184 | int callingPid = getCallingPid(); | 
|  | 185 | LOG1("unlock (pid %d)", callingPid); | 
|  | 186 | Mutex::Autolock lock(mLock); | 
|  | 187 |  | 
|  | 188 | // allow anyone to use camera (after they lock the camera) | 
|  | 189 | status_t result = checkPid(); | 
|  | 190 | if (result == NO_ERROR) { | 
|  | 191 | if (mHardware->recordingEnabled()) { | 
|  | 192 | ALOGE("Not allowed to unlock camera during recording."); | 
|  | 193 | return INVALID_OPERATION; | 
|  | 194 | } | 
|  | 195 | mClientPid = 0; | 
| Igor Murashkin | 44cfcf0 | 2013-03-01 16:22:28 -0800 | [diff] [blame] | 196 | LOG1("clear mRemoteCallback (pid %d)", callingPid); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 197 | // we need to remove the reference to ICameraClient so that when the app | 
|  | 198 | // goes away, the reference count goes to 0. | 
| Igor Murashkin | 44cfcf0 | 2013-03-01 16:22:28 -0800 | [diff] [blame] | 199 | mRemoteCallback.clear(); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 200 | } | 
|  | 201 | return result; | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 | // connect a new client to the camera | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 205 | status_t CameraClient::connect(const sp<hardware::ICameraClient>& client) { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 206 | int callingPid = getCallingPid(); | 
|  | 207 | LOG1("connect E (pid %d)", callingPid); | 
|  | 208 | Mutex::Autolock lock(mLock); | 
|  | 209 |  | 
|  | 210 | if (mClientPid != 0 && checkPid() != NO_ERROR) { | 
|  | 211 | ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)", | 
|  | 212 | mClientPid, callingPid); | 
|  | 213 | return EBUSY; | 
|  | 214 | } | 
|  | 215 |  | 
| Igor Murashkin | 44cfcf0 | 2013-03-01 16:22:28 -0800 | [diff] [blame] | 216 | if (mRemoteCallback != 0 && | 
| Marco Nelissen | 06b4606 | 2014-11-14 07:58:25 -0800 | [diff] [blame] | 217 | (IInterface::asBinder(client) == IInterface::asBinder(mRemoteCallback))) { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 218 | LOG1("Connect to the same client"); | 
|  | 219 | return NO_ERROR; | 
|  | 220 | } | 
|  | 221 |  | 
|  | 222 | mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; | 
|  | 223 | mClientPid = callingPid; | 
| Igor Murashkin | 44cfcf0 | 2013-03-01 16:22:28 -0800 | [diff] [blame] | 224 | mRemoteCallback = client; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 225 |  | 
|  | 226 | LOG1("connect X (pid %d)", callingPid); | 
|  | 227 | return NO_ERROR; | 
|  | 228 | } | 
|  | 229 |  | 
|  | 230 | static void disconnectWindow(const sp<ANativeWindow>& window) { | 
|  | 231 | if (window != 0) { | 
|  | 232 | status_t result = native_window_api_disconnect(window.get(), | 
|  | 233 | NATIVE_WINDOW_API_CAMERA); | 
|  | 234 | if (result != NO_ERROR) { | 
|  | 235 | ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result), | 
|  | 236 | result); | 
|  | 237 | } | 
|  | 238 | } | 
|  | 239 | } | 
|  | 240 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 241 | binder::Status CameraClient::disconnect() { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 242 | int callingPid = getCallingPid(); | 
|  | 243 | LOG1("disconnect E (pid %d)", callingPid); | 
|  | 244 | Mutex::Autolock lock(mLock); | 
|  | 245 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 246 | binder::Status res = binder::Status::ok(); | 
| Chien-Yu Chen | 98a668f | 2015-12-18 14:10:33 -0800 | [diff] [blame] | 247 | // Allow both client and the cameraserver to disconnect at all times | 
| Eino-Ville Talvala | c037920 | 2012-10-09 22:16:58 -0700 | [diff] [blame] | 248 | if (callingPid != mClientPid && callingPid != mServicePid) { | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 249 | ALOGW("different client - don't disconnect"); | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 250 | return res; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 251 | } | 
|  | 252 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 253 | // Make sure disconnect() is done once and once only, whether it is called | 
|  | 254 | // from the user directly, or called by the destructor. | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 255 | if (mHardware == 0) return res; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 256 |  | 
|  | 257 | LOG1("hardware teardown"); | 
|  | 258 | // Before destroying mHardware, we must make sure it's in the | 
|  | 259 | // idle state. | 
|  | 260 | // Turn off all messages. | 
|  | 261 | disableMsgType(CAMERA_MSG_ALL_MSGS); | 
|  | 262 | mHardware->stopPreview(); | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 263 | sCameraService->updateProxyDeviceState( | 
| Eino-Ville Talvala | e8c96c7 | 2017-06-27 12:24:07 -0700 | [diff] [blame] | 264 | hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, | 
|  | 265 | mCameraIdStr, mCameraFacing, mClientPackageName); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 266 | mHardware->cancelPicture(); | 
|  | 267 | // Release the hardware resources. | 
|  | 268 | mHardware->release(); | 
|  | 269 |  | 
|  | 270 | // Release the held ANativeWindow resources. | 
|  | 271 | if (mPreviewWindow != 0) { | 
|  | 272 | disconnectWindow(mPreviewWindow); | 
|  | 273 | mPreviewWindow = 0; | 
|  | 274 | mHardware->setPreviewWindow(mPreviewWindow); | 
|  | 275 | } | 
|  | 276 | mHardware.clear(); | 
|  | 277 |  | 
|  | 278 | CameraService::Client::disconnect(); | 
|  | 279 |  | 
|  | 280 | LOG1("disconnect X (pid %d)", callingPid); | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 281 |  | 
|  | 282 | return res; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 283 | } | 
|  | 284 |  | 
|  | 285 | // ---------------------------------------------------------------------------- | 
|  | 286 |  | 
|  | 287 | status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder, | 
|  | 288 | const sp<ANativeWindow>& window) { | 
|  | 289 | Mutex::Autolock lock(mLock); | 
|  | 290 | status_t result = checkPidAndHardware(); | 
|  | 291 | if (result != NO_ERROR) return result; | 
|  | 292 |  | 
|  | 293 | // return if no change in surface. | 
|  | 294 | if (binder == mSurface) { | 
|  | 295 | return NO_ERROR; | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | if (window != 0) { | 
|  | 299 | result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA); | 
|  | 300 | if (result != NO_ERROR) { | 
|  | 301 | ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result), | 
|  | 302 | result); | 
|  | 303 | return result; | 
|  | 304 | } | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | // If preview has been already started, register preview buffers now. | 
|  | 308 | if (mHardware->previewEnabled()) { | 
|  | 309 | if (window != 0) { | 
| Eino-Ville Talvala | f735117 | 2016-02-09 12:13:57 -0800 | [diff] [blame] | 310 | mHardware->setPreviewScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); | 
|  | 311 | mHardware->setPreviewTransform(mOrientation); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 312 | result = mHardware->setPreviewWindow(window); | 
|  | 313 | } | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | if (result == NO_ERROR) { | 
|  | 317 | // Everything has succeeded.  Disconnect the old window and remember the | 
|  | 318 | // new window. | 
|  | 319 | disconnectWindow(mPreviewWindow); | 
|  | 320 | mSurface = binder; | 
|  | 321 | mPreviewWindow = window; | 
|  | 322 | } else { | 
|  | 323 | // Something went wrong after we connected to the new window, so | 
|  | 324 | // disconnect here. | 
|  | 325 | disconnectWindow(window); | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | return result; | 
|  | 329 | } | 
|  | 330 |  | 
| Eino-Ville Talvala | 1ce7c34 | 2013-08-21 13:57:21 -0700 | [diff] [blame] | 331 | // set the buffer consumer that the preview will use | 
|  | 332 | status_t CameraClient::setPreviewTarget( | 
| Andy McFadden | 8ba0102 | 2012-12-18 09:46:54 -0800 | [diff] [blame] | 333 | const sp<IGraphicBufferProducer>& bufferProducer) { | 
| Eino-Ville Talvala | 1ce7c34 | 2013-08-21 13:57:21 -0700 | [diff] [blame] | 334 | LOG1("setPreviewTarget(%p) (pid %d)", bufferProducer.get(), | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 335 | getCallingPid()); | 
|  | 336 |  | 
|  | 337 | sp<IBinder> binder; | 
|  | 338 | sp<ANativeWindow> window; | 
| Andy McFadden | 8ba0102 | 2012-12-18 09:46:54 -0800 | [diff] [blame] | 339 | if (bufferProducer != 0) { | 
| Marco Nelissen | 06b4606 | 2014-11-14 07:58:25 -0800 | [diff] [blame] | 340 | binder = IInterface::asBinder(bufferProducer); | 
| Eino-Ville Talvala | 1ce7c34 | 2013-08-21 13:57:21 -0700 | [diff] [blame] | 341 | // Using controlledByApp flag to ensure that the buffer queue remains in | 
|  | 342 | // async mode for the old camera API, where many applications depend | 
|  | 343 | // on that behavior. | 
|  | 344 | window = new Surface(bufferProducer, /*controlledByApp*/ true); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 345 | } | 
|  | 346 | return setPreviewWindow(binder, window); | 
|  | 347 | } | 
|  | 348 |  | 
|  | 349 | // set the preview callback flag to affect how the received frames from | 
|  | 350 | // preview are handled. | 
|  | 351 | void CameraClient::setPreviewCallbackFlag(int callback_flag) { | 
|  | 352 | LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid()); | 
|  | 353 | Mutex::Autolock lock(mLock); | 
|  | 354 | if (checkPidAndHardware() != NO_ERROR) return; | 
|  | 355 |  | 
|  | 356 | mPreviewCallbackFlag = callback_flag; | 
|  | 357 | if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) { | 
|  | 358 | enableMsgType(CAMERA_MSG_PREVIEW_FRAME); | 
|  | 359 | } else { | 
|  | 360 | disableMsgType(CAMERA_MSG_PREVIEW_FRAME); | 
|  | 361 | } | 
|  | 362 | } | 
|  | 363 |  | 
| Eino-Ville Talvala | 3ee3550 | 2013-04-02 15:45:11 -0700 | [diff] [blame] | 364 | status_t CameraClient::setPreviewCallbackTarget( | 
|  | 365 | const sp<IGraphicBufferProducer>& callbackProducer) { | 
| Eino-Ville Talvala | 7b82efe | 2013-07-25 17:12:35 -0700 | [diff] [blame] | 366 | (void)callbackProducer; | 
| Eino-Ville Talvala | 3ee3550 | 2013-04-02 15:45:11 -0700 | [diff] [blame] | 367 | ALOGE("%s: Unimplemented!", __FUNCTION__); | 
|  | 368 | return INVALID_OPERATION; | 
|  | 369 | } | 
|  | 370 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 371 | // start preview mode | 
|  | 372 | status_t CameraClient::startPreview() { | 
|  | 373 | LOG1("startPreview (pid %d)", getCallingPid()); | 
|  | 374 | return startCameraMode(CAMERA_PREVIEW_MODE); | 
|  | 375 | } | 
|  | 376 |  | 
|  | 377 | // start recording mode | 
|  | 378 | status_t CameraClient::startRecording() { | 
|  | 379 | LOG1("startRecording (pid %d)", getCallingPid()); | 
|  | 380 | return startCameraMode(CAMERA_RECORDING_MODE); | 
|  | 381 | } | 
|  | 382 |  | 
|  | 383 | // start preview or recording | 
|  | 384 | status_t CameraClient::startCameraMode(camera_mode mode) { | 
|  | 385 | LOG1("startCameraMode(%d)", mode); | 
|  | 386 | Mutex::Autolock lock(mLock); | 
|  | 387 | status_t result = checkPidAndHardware(); | 
|  | 388 | if (result != NO_ERROR) return result; | 
|  | 389 |  | 
|  | 390 | switch(mode) { | 
|  | 391 | case CAMERA_PREVIEW_MODE: | 
|  | 392 | if (mSurface == 0 && mPreviewWindow == 0) { | 
|  | 393 | LOG1("mSurface is not set yet."); | 
|  | 394 | // still able to start preview in this case. | 
|  | 395 | } | 
|  | 396 | return startPreviewMode(); | 
|  | 397 | case CAMERA_RECORDING_MODE: | 
|  | 398 | if (mSurface == 0 && mPreviewWindow == 0) { | 
|  | 399 | ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode."); | 
|  | 400 | return INVALID_OPERATION; | 
|  | 401 | } | 
|  | 402 | return startRecordingMode(); | 
|  | 403 | default: | 
|  | 404 | return UNKNOWN_ERROR; | 
|  | 405 | } | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | status_t CameraClient::startPreviewMode() { | 
|  | 409 | LOG1("startPreviewMode"); | 
|  | 410 | status_t result = NO_ERROR; | 
|  | 411 |  | 
|  | 412 | // if preview has been enabled, nothing needs to be done | 
|  | 413 | if (mHardware->previewEnabled()) { | 
|  | 414 | return NO_ERROR; | 
|  | 415 | } | 
|  | 416 |  | 
|  | 417 | if (mPreviewWindow != 0) { | 
| Eino-Ville Talvala | f735117 | 2016-02-09 12:13:57 -0800 | [diff] [blame] | 418 | mHardware->setPreviewScalingMode( | 
|  | 419 | NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); | 
|  | 420 | mHardware->setPreviewTransform(mOrientation); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 421 | } | 
|  | 422 | mHardware->setPreviewWindow(mPreviewWindow); | 
|  | 423 | result = mHardware->startPreview(); | 
| Eino-Ville Talvala | 412fe56 | 2015-08-20 17:08:32 -0700 | [diff] [blame] | 424 | if (result == NO_ERROR) { | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 425 | sCameraService->updateProxyDeviceState( | 
| Eino-Ville Talvala | e8c96c7 | 2017-06-27 12:24:07 -0700 | [diff] [blame] | 426 | hardware::ICameraServiceProxy::CAMERA_STATE_ACTIVE, | 
|  | 427 | mCameraIdStr, mCameraFacing, mClientPackageName); | 
| Eino-Ville Talvala | 412fe56 | 2015-08-20 17:08:32 -0700 | [diff] [blame] | 428 | } | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 429 | return result; | 
|  | 430 | } | 
|  | 431 |  | 
|  | 432 | status_t CameraClient::startRecordingMode() { | 
|  | 433 | LOG1("startRecordingMode"); | 
|  | 434 | status_t result = NO_ERROR; | 
|  | 435 |  | 
|  | 436 | // if recording has been enabled, nothing needs to be done | 
|  | 437 | if (mHardware->recordingEnabled()) { | 
|  | 438 | return NO_ERROR; | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | // if preview has not been started, start preview first | 
|  | 442 | if (!mHardware->previewEnabled()) { | 
|  | 443 | result = startPreviewMode(); | 
|  | 444 | if (result != NO_ERROR) { | 
|  | 445 | return result; | 
|  | 446 | } | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | // start recording mode | 
|  | 450 | enableMsgType(CAMERA_MSG_VIDEO_FRAME); | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 451 | sCameraService->playSound(CameraService::SOUND_RECORDING_START); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 452 | result = mHardware->startRecording(); | 
|  | 453 | if (result != NO_ERROR) { | 
|  | 454 | ALOGE("mHardware->startRecording() failed with status %d", result); | 
|  | 455 | } | 
|  | 456 | return result; | 
|  | 457 | } | 
|  | 458 |  | 
|  | 459 | // stop preview mode | 
|  | 460 | void CameraClient::stopPreview() { | 
|  | 461 | LOG1("stopPreview (pid %d)", getCallingPid()); | 
|  | 462 | Mutex::Autolock lock(mLock); | 
|  | 463 | if (checkPidAndHardware() != NO_ERROR) return; | 
|  | 464 |  | 
|  | 465 |  | 
|  | 466 | disableMsgType(CAMERA_MSG_PREVIEW_FRAME); | 
|  | 467 | mHardware->stopPreview(); | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 468 | sCameraService->updateProxyDeviceState( | 
| Eino-Ville Talvala | e8c96c7 | 2017-06-27 12:24:07 -0700 | [diff] [blame] | 469 | hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, | 
|  | 470 | mCameraIdStr, mCameraFacing, mClientPackageName); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 471 | mPreviewBuffer.clear(); | 
|  | 472 | } | 
|  | 473 |  | 
|  | 474 | // stop recording mode | 
|  | 475 | void CameraClient::stopRecording() { | 
|  | 476 | LOG1("stopRecording (pid %d)", getCallingPid()); | 
| Emilian Peev | 698f0a7 | 2017-04-05 11:20:09 +0100 | [diff] [blame] | 477 | { | 
|  | 478 | Mutex::Autolock lock(mLock); | 
|  | 479 | if (checkPidAndHardware() != NO_ERROR) return; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 480 |  | 
| Emilian Peev | 698f0a7 | 2017-04-05 11:20:09 +0100 | [diff] [blame] | 481 | disableMsgType(CAMERA_MSG_VIDEO_FRAME); | 
|  | 482 | mHardware->stopRecording(); | 
|  | 483 | sCameraService->playSound(CameraService::SOUND_RECORDING_STOP); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 484 |  | 
| Emilian Peev | 698f0a7 | 2017-04-05 11:20:09 +0100 | [diff] [blame] | 485 | mPreviewBuffer.clear(); | 
|  | 486 | } | 
|  | 487 |  | 
|  | 488 | { | 
|  | 489 | Mutex::Autolock l(mAvailableCallbackBuffersLock); | 
|  | 490 | if (!mAvailableCallbackBuffers.empty()) { | 
|  | 491 | mAvailableCallbackBuffers.clear(); | 
|  | 492 | } | 
|  | 493 | } | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 494 | } | 
|  | 495 |  | 
|  | 496 | // release a recording frame | 
|  | 497 | void CameraClient::releaseRecordingFrame(const sp<IMemory>& mem) { | 
|  | 498 | Mutex::Autolock lock(mLock); | 
|  | 499 | if (checkPidAndHardware() != NO_ERROR) return; | 
| Chien-Yu Chen | 42f2707 | 2016-01-11 17:39:17 -0800 | [diff] [blame] | 500 | if (mem == nullptr) { | 
|  | 501 | android_errorWriteWithInfoLog(CameraService::SN_EVENT_LOG_ID, "26164272", | 
|  | 502 | IPCThreadState::self()->getCallingUid(), nullptr, 0); | 
|  | 503 | return; | 
|  | 504 | } | 
|  | 505 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 506 | mHardware->releaseRecordingFrame(mem); | 
|  | 507 | } | 
|  | 508 |  | 
| Chien-Yu Chen | 2d13b1d | 2016-04-28 12:11:20 -0700 | [diff] [blame] | 509 | void CameraClient::releaseRecordingFrameHandle(native_handle_t *handle) { | 
|  | 510 | if (handle == nullptr) return; | 
|  | 511 |  | 
|  | 512 | sp<IMemory> dataPtr; | 
|  | 513 | { | 
|  | 514 | Mutex::Autolock l(mAvailableCallbackBuffersLock); | 
|  | 515 | if (!mAvailableCallbackBuffers.empty()) { | 
|  | 516 | dataPtr = mAvailableCallbackBuffers.back(); | 
|  | 517 | mAvailableCallbackBuffers.pop_back(); | 
|  | 518 | } | 
|  | 519 | } | 
|  | 520 |  | 
|  | 521 | if (dataPtr == nullptr) { | 
|  | 522 | ALOGE("%s: %d: No callback buffer available. Dropping a native handle.", __FUNCTION__, | 
|  | 523 | __LINE__); | 
|  | 524 | native_handle_close(handle); | 
|  | 525 | native_handle_delete(handle); | 
|  | 526 | return; | 
|  | 527 | } else if (dataPtr->size() != sizeof(VideoNativeHandleMetadata)) { | 
|  | 528 | ALOGE("%s: %d: Callback buffer size doesn't match VideoNativeHandleMetadata", __FUNCTION__, | 
|  | 529 | __LINE__); | 
|  | 530 | native_handle_close(handle); | 
|  | 531 | native_handle_delete(handle); | 
|  | 532 | return; | 
|  | 533 | } | 
|  | 534 |  | 
|  | 535 | VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer()); | 
|  | 536 | metadata->eType = kMetadataBufferTypeNativeHandleSource; | 
|  | 537 | metadata->pHandle = handle; | 
|  | 538 |  | 
|  | 539 | mHardware->releaseRecordingFrame(dataPtr); | 
|  | 540 | } | 
|  | 541 |  | 
| Yin-Chia Yeh | b5df547 | 2017-03-20 19:32:19 -0700 | [diff] [blame] | 542 | void CameraClient::releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) { | 
|  | 543 | size_t n = handles.size(); | 
|  | 544 | std::vector<sp<IMemory>> frames; | 
|  | 545 | frames.reserve(n); | 
|  | 546 | bool error = false; | 
|  | 547 | for (auto& handle : handles) { | 
|  | 548 | sp<IMemory> dataPtr; | 
|  | 549 | { | 
|  | 550 | Mutex::Autolock l(mAvailableCallbackBuffersLock); | 
|  | 551 | if (!mAvailableCallbackBuffers.empty()) { | 
|  | 552 | dataPtr = mAvailableCallbackBuffers.back(); | 
|  | 553 | mAvailableCallbackBuffers.pop_back(); | 
|  | 554 | } | 
|  | 555 | } | 
|  | 556 |  | 
|  | 557 | if (dataPtr == nullptr) { | 
|  | 558 | ALOGE("%s: %d: No callback buffer available. Dropping frames.", __FUNCTION__, | 
|  | 559 | __LINE__); | 
|  | 560 | error = true; | 
|  | 561 | break; | 
|  | 562 | } else if (dataPtr->size() != sizeof(VideoNativeHandleMetadata)) { | 
|  | 563 | ALOGE("%s: %d: Callback buffer must be VideoNativeHandleMetadata", __FUNCTION__, | 
|  | 564 | __LINE__); | 
|  | 565 | error = true; | 
|  | 566 | break; | 
|  | 567 | } | 
|  | 568 |  | 
|  | 569 | VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer()); | 
|  | 570 | metadata->eType = kMetadataBufferTypeNativeHandleSource; | 
|  | 571 | metadata->pHandle = handle; | 
|  | 572 | frames.push_back(dataPtr); | 
|  | 573 | } | 
|  | 574 |  | 
|  | 575 | if (error) { | 
|  | 576 | for (auto& handle : handles) { | 
|  | 577 | native_handle_close(handle); | 
|  | 578 | native_handle_delete(handle); | 
|  | 579 | } | 
|  | 580 | } else { | 
|  | 581 | mHardware->releaseRecordingFrameBatch(frames); | 
|  | 582 | } | 
|  | 583 | return; | 
|  | 584 | } | 
|  | 585 |  | 
| Chien-Yu Chen | 8cca075 | 2015-11-13 15:28:48 -0800 | [diff] [blame] | 586 | status_t CameraClient::setVideoBufferMode(int32_t videoBufferMode) { | 
|  | 587 | LOG1("setVideoBufferMode: %d", videoBufferMode); | 
|  | 588 | bool enableMetadataInBuffers = false; | 
|  | 589 |  | 
|  | 590 | if (videoBufferMode == VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA) { | 
|  | 591 | enableMetadataInBuffers = true; | 
|  | 592 | } else if (videoBufferMode != VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV) { | 
|  | 593 | ALOGE("%s: %d: videoBufferMode %d is not supported.", __FUNCTION__, __LINE__, | 
|  | 594 | videoBufferMode); | 
|  | 595 | return BAD_VALUE; | 
|  | 596 | } | 
|  | 597 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 598 | Mutex::Autolock lock(mLock); | 
|  | 599 | if (checkPidAndHardware() != NO_ERROR) { | 
|  | 600 | return UNKNOWN_ERROR; | 
|  | 601 | } | 
| Chien-Yu Chen | 8cca075 | 2015-11-13 15:28:48 -0800 | [diff] [blame] | 602 |  | 
|  | 603 | return mHardware->storeMetaDataInBuffers(enableMetadataInBuffers); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 604 | } | 
|  | 605 |  | 
|  | 606 | bool CameraClient::previewEnabled() { | 
|  | 607 | LOG1("previewEnabled (pid %d)", getCallingPid()); | 
|  | 608 |  | 
|  | 609 | Mutex::Autolock lock(mLock); | 
|  | 610 | if (checkPidAndHardware() != NO_ERROR) return false; | 
|  | 611 | return mHardware->previewEnabled(); | 
|  | 612 | } | 
|  | 613 |  | 
|  | 614 | bool CameraClient::recordingEnabled() { | 
|  | 615 | LOG1("recordingEnabled (pid %d)", getCallingPid()); | 
|  | 616 |  | 
|  | 617 | Mutex::Autolock lock(mLock); | 
|  | 618 | if (checkPidAndHardware() != NO_ERROR) return false; | 
|  | 619 | return mHardware->recordingEnabled(); | 
|  | 620 | } | 
|  | 621 |  | 
|  | 622 | status_t CameraClient::autoFocus() { | 
|  | 623 | LOG1("autoFocus (pid %d)", getCallingPid()); | 
|  | 624 |  | 
|  | 625 | Mutex::Autolock lock(mLock); | 
|  | 626 | status_t result = checkPidAndHardware(); | 
|  | 627 | if (result != NO_ERROR) return result; | 
|  | 628 |  | 
|  | 629 | return mHardware->autoFocus(); | 
|  | 630 | } | 
|  | 631 |  | 
|  | 632 | status_t CameraClient::cancelAutoFocus() { | 
|  | 633 | LOG1("cancelAutoFocus (pid %d)", getCallingPid()); | 
|  | 634 |  | 
|  | 635 | Mutex::Autolock lock(mLock); | 
|  | 636 | status_t result = checkPidAndHardware(); | 
|  | 637 | if (result != NO_ERROR) return result; | 
|  | 638 |  | 
|  | 639 | return mHardware->cancelAutoFocus(); | 
|  | 640 | } | 
|  | 641 |  | 
|  | 642 | // take a picture - image is returned in callback | 
|  | 643 | status_t CameraClient::takePicture(int msgType) { | 
|  | 644 | LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType); | 
|  | 645 |  | 
|  | 646 | Mutex::Autolock lock(mLock); | 
|  | 647 | status_t result = checkPidAndHardware(); | 
|  | 648 | if (result != NO_ERROR) return result; | 
|  | 649 |  | 
|  | 650 | if ((msgType & CAMERA_MSG_RAW_IMAGE) && | 
|  | 651 | (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) { | 
|  | 652 | ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY" | 
|  | 653 | " cannot be both enabled"); | 
|  | 654 | return BAD_VALUE; | 
|  | 655 | } | 
|  | 656 |  | 
|  | 657 | // We only accept picture related message types | 
|  | 658 | // and ignore other types of messages for takePicture(). | 
|  | 659 | int picMsgType = msgType | 
|  | 660 | & (CAMERA_MSG_SHUTTER | | 
|  | 661 | CAMERA_MSG_POSTVIEW_FRAME | | 
|  | 662 | CAMERA_MSG_RAW_IMAGE | | 
|  | 663 | CAMERA_MSG_RAW_IMAGE_NOTIFY | | 
|  | 664 | CAMERA_MSG_COMPRESSED_IMAGE); | 
|  | 665 |  | 
|  | 666 | enableMsgType(picMsgType); | 
|  | 667 |  | 
|  | 668 | return mHardware->takePicture(); | 
|  | 669 | } | 
|  | 670 |  | 
|  | 671 | // set preview/capture parameters - key/value pairs | 
|  | 672 | status_t CameraClient::setParameters(const String8& params) { | 
|  | 673 | LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string()); | 
|  | 674 |  | 
|  | 675 | Mutex::Autolock lock(mLock); | 
|  | 676 | status_t result = checkPidAndHardware(); | 
|  | 677 | if (result != NO_ERROR) return result; | 
|  | 678 |  | 
| Igor Murashkin | fcf5fea | 2014-09-11 14:43:24 -0700 | [diff] [blame] | 679 | mLatestSetParameters = CameraParameters(params); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 680 | CameraParameters p(params); | 
|  | 681 | return mHardware->setParameters(p); | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | // get preview/capture parameters - key/value pairs | 
|  | 685 | String8 CameraClient::getParameters() const { | 
|  | 686 | Mutex::Autolock lock(mLock); | 
| Igor Murashkin | ebe865b | 2014-08-07 17:07:28 -0700 | [diff] [blame] | 687 | // The camera service can unconditionally get the parameters at all times | 
|  | 688 | if (getCallingPid() != mServicePid && checkPidAndHardware() != NO_ERROR) return String8(); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 689 |  | 
|  | 690 | String8 params(mHardware->getParameters().flatten()); | 
|  | 691 | LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string()); | 
|  | 692 | return params; | 
|  | 693 | } | 
|  | 694 |  | 
|  | 695 | // enable shutter sound | 
|  | 696 | status_t CameraClient::enableShutterSound(bool enable) { | 
|  | 697 | LOG1("enableShutterSound (pid %d)", getCallingPid()); | 
|  | 698 |  | 
|  | 699 | status_t result = checkPidAndHardware(); | 
|  | 700 | if (result != NO_ERROR) return result; | 
|  | 701 |  | 
|  | 702 | if (enable) { | 
|  | 703 | mPlayShutterSound = true; | 
|  | 704 | return OK; | 
|  | 705 | } | 
|  | 706 |  | 
| Igor Murashkin | a858ea0 | 2014-08-19 14:53:08 -0700 | [diff] [blame] | 707 | // the camera2 api legacy mode can unconditionally disable the shutter sound | 
|  | 708 | if (mLegacyMode) { | 
|  | 709 | ALOGV("%s: Disable shutter sound in legacy mode", __FUNCTION__); | 
|  | 710 | mPlayShutterSound = false; | 
|  | 711 | return OK; | 
|  | 712 | } | 
|  | 713 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 714 | // Disabling shutter sound may not be allowed. In that case only | 
|  | 715 | // allow the mediaserver process to disable the sound. | 
|  | 716 | char value[PROPERTY_VALUE_MAX]; | 
|  | 717 | property_get("ro.camera.sound.forced", value, "0"); | 
|  | 718 | if (strcmp(value, "0") != 0) { | 
|  | 719 | // Disabling shutter sound is not allowed. Deny if the current | 
|  | 720 | // process is not mediaserver. | 
|  | 721 | if (getCallingPid() != getpid()) { | 
|  | 722 | ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid()); | 
|  | 723 | return PERMISSION_DENIED; | 
|  | 724 | } | 
|  | 725 | } | 
|  | 726 |  | 
|  | 727 | mPlayShutterSound = false; | 
|  | 728 | return OK; | 
|  | 729 | } | 
|  | 730 |  | 
|  | 731 | status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { | 
|  | 732 | LOG1("sendCommand (pid %d)", getCallingPid()); | 
|  | 733 | int orientation; | 
|  | 734 | Mutex::Autolock lock(mLock); | 
|  | 735 | status_t result = checkPidAndHardware(); | 
|  | 736 | if (result != NO_ERROR) return result; | 
|  | 737 |  | 
|  | 738 | if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { | 
|  | 739 | // Mirror the preview if the camera is front-facing. | 
|  | 740 | orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT); | 
|  | 741 | if (orientation == -1) return BAD_VALUE; | 
|  | 742 |  | 
|  | 743 | if (mOrientation != orientation) { | 
|  | 744 | mOrientation = orientation; | 
|  | 745 | if (mPreviewWindow != 0) { | 
| Eino-Ville Talvala | f735117 | 2016-02-09 12:13:57 -0800 | [diff] [blame] | 746 | mHardware->setPreviewTransform(mOrientation); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 747 | } | 
|  | 748 | } | 
|  | 749 | return OK; | 
|  | 750 | } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) { | 
|  | 751 | switch (arg1) { | 
|  | 752 | case 0: | 
| Eino-Ville Talvala | c5268e8 | 2012-09-11 11:01:18 -0700 | [diff] [blame] | 753 | return enableShutterSound(false); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 754 | case 1: | 
| Eino-Ville Talvala | c5268e8 | 2012-09-11 11:01:18 -0700 | [diff] [blame] | 755 | return enableShutterSound(true); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 756 | default: | 
|  | 757 | return BAD_VALUE; | 
|  | 758 | } | 
|  | 759 | return OK; | 
|  | 760 | } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) { | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 761 | sCameraService->playSound(CameraService::SOUND_RECORDING_START); | 
| James Dong | 983cf23 | 2012-08-01 16:39:55 -0700 | [diff] [blame] | 762 | } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) { | 
|  | 763 | // Silently ignore this command | 
|  | 764 | return INVALID_OPERATION; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 765 | } else if (cmd == CAMERA_CMD_PING) { | 
|  | 766 | // If mHardware is 0, checkPidAndHardware will return error. | 
|  | 767 | return OK; | 
|  | 768 | } | 
|  | 769 |  | 
|  | 770 | return mHardware->sendCommand(cmd, arg1, arg2); | 
|  | 771 | } | 
|  | 772 |  | 
|  | 773 | // ---------------------------------------------------------------------------- | 
|  | 774 |  | 
|  | 775 | void CameraClient::enableMsgType(int32_t msgType) { | 
|  | 776 | android_atomic_or(msgType, &mMsgEnabled); | 
|  | 777 | mHardware->enableMsgType(msgType); | 
|  | 778 | } | 
|  | 779 |  | 
|  | 780 | void CameraClient::disableMsgType(int32_t msgType) { | 
|  | 781 | android_atomic_and(~msgType, &mMsgEnabled); | 
|  | 782 | mHardware->disableMsgType(msgType); | 
|  | 783 | } | 
|  | 784 |  | 
|  | 785 | #define CHECK_MESSAGE_INTERVAL 10 // 10ms | 
|  | 786 | bool CameraClient::lockIfMessageWanted(int32_t msgType) { | 
|  | 787 | int sleepCount = 0; | 
|  | 788 | while (mMsgEnabled & msgType) { | 
|  | 789 | if (mLock.tryLock() == NO_ERROR) { | 
|  | 790 | if (sleepCount > 0) { | 
|  | 791 | LOG1("lockIfMessageWanted(%d): waited for %d ms", | 
|  | 792 | msgType, sleepCount * CHECK_MESSAGE_INTERVAL); | 
|  | 793 | } | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 794 |  | 
|  | 795 | // If messages are no longer enabled after acquiring lock, release and drop message | 
|  | 796 | if ((mMsgEnabled & msgType) == 0) { | 
|  | 797 | mLock.unlock(); | 
|  | 798 | break; | 
|  | 799 | } | 
|  | 800 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 801 | return true; | 
|  | 802 | } | 
|  | 803 | if (sleepCount++ == 0) { | 
|  | 804 | LOG1("lockIfMessageWanted(%d): enter sleep", msgType); | 
|  | 805 | } | 
|  | 806 | usleep(CHECK_MESSAGE_INTERVAL * 1000); | 
|  | 807 | } | 
|  | 808 | ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType); | 
|  | 809 | return false; | 
|  | 810 | } | 
|  | 811 |  | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 812 | sp<CameraClient> CameraClient::getClientFromCookie(void* user) { | 
|  | 813 | String8 cameraId = String8::format("%d", (int)(intptr_t) user); | 
|  | 814 | auto clientDescriptor = sCameraService->mActiveClientManager.get(cameraId); | 
|  | 815 | if (clientDescriptor != nullptr) { | 
|  | 816 | return sp<CameraClient>{ | 
|  | 817 | static_cast<CameraClient*>(clientDescriptor->getValue().get())}; | 
|  | 818 | } | 
|  | 819 | return sp<CameraClient>{nullptr}; | 
|  | 820 | } | 
|  | 821 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 822 | // Callback messages can be dispatched to internal handlers or pass to our | 
|  | 823 | // client's callback functions, depending on the message type. | 
|  | 824 | // | 
|  | 825 | // notifyCallback: | 
|  | 826 | //      CAMERA_MSG_SHUTTER              handleShutter | 
|  | 827 | //      (others)                        c->notifyCallback | 
|  | 828 | // dataCallback: | 
|  | 829 | //      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData | 
|  | 830 | //      CAMERA_MSG_POSTVIEW_FRAME       handlePostview | 
|  | 831 | //      CAMERA_MSG_RAW_IMAGE            handleRawPicture | 
|  | 832 | //      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture | 
|  | 833 | //      (others)                        c->dataCallback | 
|  | 834 | // dataCallbackTimestamp | 
|  | 835 | //      (others)                        c->dataCallbackTimestamp | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 836 |  | 
|  | 837 | void CameraClient::notifyCallback(int32_t msgType, int32_t ext1, | 
|  | 838 | int32_t ext2, void* user) { | 
|  | 839 | LOG2("notifyCallback(%d)", msgType); | 
|  | 840 |  | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 841 | sp<CameraClient> client = getClientFromCookie(user); | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 842 | if (client.get() == nullptr) return; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 843 |  | 
|  | 844 | if (!client->lockIfMessageWanted(msgType)) return; | 
|  | 845 |  | 
|  | 846 | switch (msgType) { | 
|  | 847 | case CAMERA_MSG_SHUTTER: | 
|  | 848 | // ext1 is the dimension of the yuv picture. | 
|  | 849 | client->handleShutter(); | 
|  | 850 | break; | 
|  | 851 | default: | 
|  | 852 | client->handleGenericNotify(msgType, ext1, ext2); | 
|  | 853 | break; | 
|  | 854 | } | 
|  | 855 | } | 
|  | 856 |  | 
|  | 857 | void CameraClient::dataCallback(int32_t msgType, | 
|  | 858 | const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) { | 
|  | 859 | LOG2("dataCallback(%d)", msgType); | 
|  | 860 |  | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 861 | sp<CameraClient> client = getClientFromCookie(user); | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 862 | if (client.get() == nullptr) return; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 863 |  | 
|  | 864 | if (!client->lockIfMessageWanted(msgType)) return; | 
|  | 865 | if (dataPtr == 0 && metadata == NULL) { | 
|  | 866 | ALOGE("Null data returned in data callback"); | 
|  | 867 | client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); | 
|  | 868 | return; | 
|  | 869 | } | 
|  | 870 |  | 
|  | 871 | switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) { | 
|  | 872 | case CAMERA_MSG_PREVIEW_FRAME: | 
|  | 873 | client->handlePreviewData(msgType, dataPtr, metadata); | 
|  | 874 | break; | 
|  | 875 | case CAMERA_MSG_POSTVIEW_FRAME: | 
|  | 876 | client->handlePostview(dataPtr); | 
|  | 877 | break; | 
|  | 878 | case CAMERA_MSG_RAW_IMAGE: | 
|  | 879 | client->handleRawPicture(dataPtr); | 
|  | 880 | break; | 
|  | 881 | case CAMERA_MSG_COMPRESSED_IMAGE: | 
|  | 882 | client->handleCompressedPicture(dataPtr); | 
|  | 883 | break; | 
|  | 884 | default: | 
|  | 885 | client->handleGenericData(msgType, dataPtr, metadata); | 
|  | 886 | break; | 
|  | 887 | } | 
|  | 888 | } | 
|  | 889 |  | 
|  | 890 | void CameraClient::dataCallbackTimestamp(nsecs_t timestamp, | 
|  | 891 | int32_t msgType, const sp<IMemory>& dataPtr, void* user) { | 
|  | 892 | LOG2("dataCallbackTimestamp(%d)", msgType); | 
|  | 893 |  | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 894 | sp<CameraClient> client = getClientFromCookie(user); | 
| Ruben Brunk | cc77671 | 2015-02-17 20:18:47 -0800 | [diff] [blame] | 895 | if (client.get() == nullptr) return; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 896 |  | 
|  | 897 | if (!client->lockIfMessageWanted(msgType)) return; | 
|  | 898 |  | 
|  | 899 | if (dataPtr == 0) { | 
|  | 900 | ALOGE("Null data returned in data with timestamp callback"); | 
|  | 901 | client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); | 
|  | 902 | return; | 
|  | 903 | } | 
|  | 904 |  | 
|  | 905 | client->handleGenericDataTimestamp(timestamp, msgType, dataPtr); | 
|  | 906 | } | 
|  | 907 |  | 
| Yin-Chia Yeh | b5df547 | 2017-03-20 19:32:19 -0700 | [diff] [blame] | 908 | void CameraClient::handleCallbackTimestampBatch( | 
|  | 909 | int32_t msgType, const std::vector<HandleTimestampMessage>& msgs, void* user) { | 
|  | 910 | LOG2("dataCallbackTimestampBatch"); | 
|  | 911 | sp<CameraClient> client = getClientFromCookie(user); | 
|  | 912 | if (client.get() == nullptr) return; | 
|  | 913 | if (!client->lockIfMessageWanted(msgType)) return; | 
|  | 914 |  | 
|  | 915 | sp<hardware::ICameraClient> c = client->mRemoteCallback; | 
|  | 916 | client->mLock.unlock(); | 
|  | 917 | if (c != 0 && msgs.size() > 0) { | 
|  | 918 | size_t n = msgs.size(); | 
|  | 919 | std::vector<nsecs_t> timestamps; | 
|  | 920 | std::vector<native_handle_t*> handles; | 
|  | 921 | timestamps.reserve(n); | 
|  | 922 | handles.reserve(n); | 
|  | 923 | for (auto& msg : msgs) { | 
|  | 924 | native_handle_t* handle = nullptr; | 
|  | 925 | if (msg.dataPtr->size() != sizeof(VideoNativeHandleMetadata)) { | 
|  | 926 | ALOGE("%s: dataPtr does not contain VideoNativeHandleMetadata!", __FUNCTION__); | 
|  | 927 | return; | 
|  | 928 | } | 
|  | 929 | VideoNativeHandleMetadata *metadata = | 
|  | 930 | (VideoNativeHandleMetadata*)(msg.dataPtr->pointer()); | 
|  | 931 | if (metadata->eType == kMetadataBufferTypeNativeHandleSource) { | 
|  | 932 | handle = metadata->pHandle; | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | if (handle == nullptr) { | 
|  | 936 | ALOGE("%s: VideoNativeHandleMetadata type mismatch or null handle passed!", | 
|  | 937 | __FUNCTION__); | 
|  | 938 | return; | 
|  | 939 | } | 
|  | 940 | { | 
|  | 941 | Mutex::Autolock l(client->mAvailableCallbackBuffersLock); | 
|  | 942 | client->mAvailableCallbackBuffers.push_back(msg.dataPtr); | 
|  | 943 | } | 
|  | 944 | timestamps.push_back(msg.timestamp); | 
|  | 945 | handles.push_back(handle); | 
|  | 946 | } | 
|  | 947 | c->recordingFrameHandleCallbackTimestampBatch(timestamps, handles); | 
|  | 948 | } | 
|  | 949 | } | 
|  | 950 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 951 | // snapshot taken callback | 
|  | 952 | void CameraClient::handleShutter(void) { | 
|  | 953 | if (mPlayShutterSound) { | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 954 | sCameraService->playSound(CameraService::SOUND_SHUTTER); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 955 | } | 
|  | 956 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 957 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 958 | if (c != 0) { | 
|  | 959 | mLock.unlock(); | 
|  | 960 | c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); | 
|  | 961 | if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return; | 
|  | 962 | } | 
|  | 963 | disableMsgType(CAMERA_MSG_SHUTTER); | 
|  | 964 |  | 
| Eino-Ville Talvala | 412fe56 | 2015-08-20 17:08:32 -0700 | [diff] [blame] | 965 | // Shutters only happen in response to takePicture, so mark device as | 
|  | 966 | // idle now, until preview is restarted | 
| Eino-Ville Talvala | 2f09bac | 2016-12-13 11:29:54 -0800 | [diff] [blame] | 967 | sCameraService->updateProxyDeviceState( | 
| Eino-Ville Talvala | e8c96c7 | 2017-06-27 12:24:07 -0700 | [diff] [blame] | 968 | hardware::ICameraServiceProxy::CAMERA_STATE_IDLE, | 
|  | 969 | mCameraIdStr, mCameraFacing, mClientPackageName); | 
| Eino-Ville Talvala | 412fe56 | 2015-08-20 17:08:32 -0700 | [diff] [blame] | 970 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 971 | mLock.unlock(); | 
|  | 972 | } | 
|  | 973 |  | 
|  | 974 | // preview callback - frame buffer update | 
|  | 975 | void CameraClient::handlePreviewData(int32_t msgType, | 
|  | 976 | const sp<IMemory>& mem, | 
|  | 977 | camera_frame_metadata_t *metadata) { | 
|  | 978 | ssize_t offset; | 
|  | 979 | size_t size; | 
|  | 980 | sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); | 
|  | 981 |  | 
|  | 982 | // local copy of the callback flags | 
|  | 983 | int flags = mPreviewCallbackFlag; | 
|  | 984 |  | 
|  | 985 | // is callback enabled? | 
|  | 986 | if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) { | 
|  | 987 | // If the enable bit is off, the copy-out and one-shot bits are ignored | 
|  | 988 | LOG2("frame callback is disabled"); | 
|  | 989 | mLock.unlock(); | 
|  | 990 | return; | 
|  | 991 | } | 
|  | 992 |  | 
|  | 993 | // hold a strong pointer to the client | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 994 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 995 |  | 
|  | 996 | // clear callback flags if no client or one-shot mode | 
|  | 997 | if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) { | 
|  | 998 | LOG2("Disable preview callback"); | 
|  | 999 | mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | | 
|  | 1000 | CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK | | 
|  | 1001 | CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK); | 
|  | 1002 | disableMsgType(CAMERA_MSG_PREVIEW_FRAME); | 
|  | 1003 | } | 
|  | 1004 |  | 
|  | 1005 | if (c != 0) { | 
|  | 1006 | // Is the received frame copied out or not? | 
|  | 1007 | if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { | 
|  | 1008 | LOG2("frame is copied"); | 
|  | 1009 | copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata); | 
|  | 1010 | } else { | 
|  | 1011 | LOG2("frame is forwarded"); | 
|  | 1012 | mLock.unlock(); | 
|  | 1013 | c->dataCallback(msgType, mem, metadata); | 
|  | 1014 | } | 
|  | 1015 | } else { | 
|  | 1016 | mLock.unlock(); | 
|  | 1017 | } | 
|  | 1018 | } | 
|  | 1019 |  | 
|  | 1020 | // picture callback - postview image ready | 
|  | 1021 | void CameraClient::handlePostview(const sp<IMemory>& mem) { | 
|  | 1022 | disableMsgType(CAMERA_MSG_POSTVIEW_FRAME); | 
|  | 1023 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1024 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1025 | mLock.unlock(); | 
|  | 1026 | if (c != 0) { | 
|  | 1027 | c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL); | 
|  | 1028 | } | 
|  | 1029 | } | 
|  | 1030 |  | 
|  | 1031 | // picture callback - raw image ready | 
|  | 1032 | void CameraClient::handleRawPicture(const sp<IMemory>& mem) { | 
|  | 1033 | disableMsgType(CAMERA_MSG_RAW_IMAGE); | 
|  | 1034 |  | 
|  | 1035 | ssize_t offset; | 
|  | 1036 | size_t size; | 
|  | 1037 | sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); | 
|  | 1038 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1039 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1040 | mLock.unlock(); | 
|  | 1041 | if (c != 0) { | 
|  | 1042 | c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL); | 
|  | 1043 | } | 
|  | 1044 | } | 
|  | 1045 |  | 
|  | 1046 | // picture callback - compressed picture ready | 
|  | 1047 | void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { | 
|  | 1048 | disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); | 
|  | 1049 |  | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1050 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1051 | mLock.unlock(); | 
|  | 1052 | if (c != 0) { | 
|  | 1053 | c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); | 
|  | 1054 | } | 
|  | 1055 | } | 
|  | 1056 |  | 
|  | 1057 |  | 
|  | 1058 | void CameraClient::handleGenericNotify(int32_t msgType, | 
|  | 1059 | int32_t ext1, int32_t ext2) { | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1060 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1061 | mLock.unlock(); | 
|  | 1062 | if (c != 0) { | 
|  | 1063 | c->notifyCallback(msgType, ext1, ext2); | 
|  | 1064 | } | 
|  | 1065 | } | 
|  | 1066 |  | 
|  | 1067 | void CameraClient::handleGenericData(int32_t msgType, | 
|  | 1068 | const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1069 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1070 | mLock.unlock(); | 
|  | 1071 | if (c != 0) { | 
|  | 1072 | c->dataCallback(msgType, dataPtr, metadata); | 
|  | 1073 | } | 
|  | 1074 | } | 
|  | 1075 |  | 
|  | 1076 | void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp, | 
|  | 1077 | int32_t msgType, const sp<IMemory>& dataPtr) { | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1078 | sp<hardware::ICameraClient> c = mRemoteCallback; | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1079 | mLock.unlock(); | 
| Chien-Yu Chen | 2d13b1d | 2016-04-28 12:11:20 -0700 | [diff] [blame] | 1080 | if (c != 0 && dataPtr != nullptr) { | 
|  | 1081 | native_handle_t* handle = nullptr; | 
|  | 1082 |  | 
|  | 1083 | // Check if dataPtr contains a VideoNativeHandleMetadata. | 
|  | 1084 | if (dataPtr->size() == sizeof(VideoNativeHandleMetadata)) { | 
|  | 1085 | VideoNativeHandleMetadata *metadata = | 
|  | 1086 | (VideoNativeHandleMetadata*)(dataPtr->pointer()); | 
|  | 1087 | if (metadata->eType == kMetadataBufferTypeNativeHandleSource) { | 
|  | 1088 | handle = metadata->pHandle; | 
|  | 1089 | } | 
|  | 1090 | } | 
|  | 1091 |  | 
|  | 1092 | // If dataPtr contains a native handle, send it via recordingFrameHandleCallbackTimestamp. | 
|  | 1093 | if (handle != nullptr) { | 
|  | 1094 | { | 
|  | 1095 | Mutex::Autolock l(mAvailableCallbackBuffersLock); | 
|  | 1096 | mAvailableCallbackBuffers.push_back(dataPtr); | 
|  | 1097 | } | 
|  | 1098 | c->recordingFrameHandleCallbackTimestamp(timestamp, handle); | 
|  | 1099 | } else { | 
|  | 1100 | c->dataCallbackTimestamp(timestamp, msgType, dataPtr); | 
|  | 1101 | } | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1102 | } | 
|  | 1103 | } | 
|  | 1104 |  | 
|  | 1105 | void CameraClient::copyFrameAndPostCopiedFrame( | 
| Eino-Ville Talvala | d56db1d | 2015-12-17 16:50:35 -0800 | [diff] [blame] | 1106 | int32_t msgType, const sp<hardware::ICameraClient>& client, | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1107 | const sp<IMemoryHeap>& heap, size_t offset, size_t size, | 
|  | 1108 | camera_frame_metadata_t *metadata) { | 
|  | 1109 | LOG2("copyFrameAndPostCopiedFrame"); | 
|  | 1110 | // It is necessary to copy out of pmem before sending this to | 
|  | 1111 | // the callback. For efficiency, reuse the same MemoryHeapBase | 
|  | 1112 | // provided it's big enough. Don't allocate the memory or | 
|  | 1113 | // perform the copy if there's no callback. | 
|  | 1114 | // hold the preview lock while we grab a reference to the preview buffer | 
|  | 1115 | sp<MemoryHeapBase> previewBuffer; | 
|  | 1116 |  | 
|  | 1117 | if (mPreviewBuffer == 0) { | 
|  | 1118 | mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); | 
|  | 1119 | } else if (size > mPreviewBuffer->virtualSize()) { | 
|  | 1120 | mPreviewBuffer.clear(); | 
|  | 1121 | mPreviewBuffer = new MemoryHeapBase(size, 0, NULL); | 
|  | 1122 | } | 
|  | 1123 | if (mPreviewBuffer == 0) { | 
|  | 1124 | ALOGE("failed to allocate space for preview buffer"); | 
|  | 1125 | mLock.unlock(); | 
|  | 1126 | return; | 
|  | 1127 | } | 
|  | 1128 | previewBuffer = mPreviewBuffer; | 
|  | 1129 |  | 
| Ruben Brunk | 65e01f7 | 2014-08-29 17:25:13 -0700 | [diff] [blame] | 1130 | void* previewBufferBase = previewBuffer->base(); | 
|  | 1131 | void* heapBase = heap->base(); | 
|  | 1132 |  | 
|  | 1133 | if (heapBase == MAP_FAILED) { | 
|  | 1134 | ALOGE("%s: Failed to mmap heap for preview frame.", __FUNCTION__); | 
|  | 1135 | mLock.unlock(); | 
|  | 1136 | return; | 
|  | 1137 | } else if (previewBufferBase == MAP_FAILED) { | 
|  | 1138 | ALOGE("%s: Failed to mmap preview buffer for preview frame.", __FUNCTION__); | 
|  | 1139 | mLock.unlock(); | 
|  | 1140 | return; | 
|  | 1141 | } | 
|  | 1142 |  | 
|  | 1143 | memcpy(previewBufferBase, (uint8_t *) heapBase + offset, size); | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1144 |  | 
|  | 1145 | sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size); | 
|  | 1146 | if (frame == 0) { | 
|  | 1147 | ALOGE("failed to allocate space for frame callback"); | 
|  | 1148 | mLock.unlock(); | 
|  | 1149 | return; | 
|  | 1150 | } | 
|  | 1151 |  | 
|  | 1152 | mLock.unlock(); | 
|  | 1153 | client->dataCallback(msgType, frame, metadata); | 
|  | 1154 | } | 
|  | 1155 |  | 
|  | 1156 | int CameraClient::getOrientation(int degrees, bool mirror) { | 
|  | 1157 | if (!mirror) { | 
|  | 1158 | if (degrees == 0) return 0; | 
|  | 1159 | else if (degrees == 90) return HAL_TRANSFORM_ROT_90; | 
|  | 1160 | else if (degrees == 180) return HAL_TRANSFORM_ROT_180; | 
|  | 1161 | else if (degrees == 270) return HAL_TRANSFORM_ROT_270; | 
|  | 1162 | } else {  // Do mirror (horizontal flip) | 
|  | 1163 | if (degrees == 0) {           // FLIP_H and ROT_0 | 
|  | 1164 | return HAL_TRANSFORM_FLIP_H; | 
|  | 1165 | } else if (degrees == 90) {   // FLIP_H and ROT_90 | 
|  | 1166 | return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90; | 
|  | 1167 | } else if (degrees == 180) {  // FLIP_H and ROT_180 | 
|  | 1168 | return HAL_TRANSFORM_FLIP_V; | 
|  | 1169 | } else if (degrees == 270) {  // FLIP_H and ROT_270 | 
|  | 1170 | return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90; | 
|  | 1171 | } | 
|  | 1172 | } | 
|  | 1173 | ALOGE("Invalid setDisplayOrientation degrees=%d", degrees); | 
|  | 1174 | return -1; | 
|  | 1175 | } | 
|  | 1176 |  | 
| Chien-Yu Chen | 8cca075 | 2015-11-13 15:28:48 -0800 | [diff] [blame] | 1177 | status_t CameraClient::setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer) { | 
| Chien-Yu Chen | 98a668f | 2015-12-18 14:10:33 -0800 | [diff] [blame] | 1178 | (void)bufferProducer; | 
| Chien-Yu Chen | 8cca075 | 2015-11-13 15:28:48 -0800 | [diff] [blame] | 1179 | ALOGE("%s: %d: CameraClient doesn't support setting a video target.", __FUNCTION__, __LINE__); | 
|  | 1180 | return INVALID_OPERATION; | 
|  | 1181 | } | 
|  | 1182 |  | 
| Eino-Ville Talvala | 5e08d60 | 2012-05-16 14:59:25 -0700 | [diff] [blame] | 1183 | }; // namespace android |