Merge change 5142 into donut
* changes:
Fix NPE in GradientDrawable constructor
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 7852c13..e945056 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -32,6 +32,7 @@
#include <media/AudioSystem.h>
#include "CameraService.h"
+#include <cutils/atomic.h>
#include <cutils/properties.h>
namespace android {
@@ -81,6 +82,7 @@
BnCameraService()
{
LOGI("CameraService started: pid=%d", getpid());
+ mUsers = 0;
}
CameraService::~CameraService()
@@ -113,7 +115,7 @@
"(old pid %d, old client %p)",
callingPid, cameraClient->asBinder().get(),
currentClient->mClientPid, currentCameraClient->asBinder().get());
- if (kill(currentClient->mClientPid, 0) == ESRCH) {
+ if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
LOGD("The old client is dead!");
}
return client;
@@ -123,6 +125,10 @@
LOGD("New client (pid %d) connecting, old reference was dangling...",
callingPid);
mClient.clear();
+ if (mUsers > 0) {
+ LOGD("Still have client, rejected");
+ return client;
+ }
}
}
@@ -174,6 +180,20 @@
LOGD("removeClient (pid %d) done", callingPid);
}
+// The reason we need this count is a new CameraService::connect() request may
+// come in while the previous Client's destructor has not been run or is still
+// running. If the last strong reference of the previous Client is gone but
+// destructor has not been run, we should not allow the new Client to be created
+// because we need to wait for the previous Client to tear down the hardware
+// first.
+void CameraService::incUsers() {
+ android_atomic_inc(&mUsers);
+}
+
+void CameraService::decUsers() {
+ android_atomic_dec(&mUsers);
+}
+
static sp<MediaPlayer> newMediaPlayer(const char *file)
{
sp<MediaPlayer> mp = new MediaPlayer();
@@ -209,6 +229,7 @@
// Callback is disabled by default
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+ cameraService->incUsers();
LOGD("Client::Client X (pid %d)", callingPid);
}
@@ -350,7 +371,7 @@
void CameraService::Client::disconnect()
{
- int callingPid = getCallingPid();
+ int callingPid = getCallingPid();
LOGD("Client::disconnect() E (pid %d client %p)",
callingPid, getCameraClient()->asBinder().get());
@@ -365,18 +386,24 @@
return;
}
+ // Make sure disconnect() is done once and once only, whether it is called
+ // from the user directly, or called by the destructor.
+ if (mHardware == 0) return;
+
mCameraService->removeClient(mCameraClient);
- if (mHardware != 0) {
- LOGD("hardware teardown");
- // Before destroying mHardware, we must make sure it's in the
- // idle state.
- mHardware->stopPreview();
- // Cancel all picture callbacks.
- mHardware->cancelPicture(true, true, true);
- // Release the hardware resources.
- mHardware->release();
- }
+
+ LOGD("hardware teardown");
+ // Before destroying mHardware, we must make sure it's in the
+ // idle state.
+ mHardware->stopPreview();
+ // Cancel all picture callbacks.
+ mHardware->cancelPicture(true, true, true);
+ // Release the hardware resources.
+ mHardware->release();
mHardware.clear();
+
+ mCameraService->decUsers();
+
LOGD("Client::disconnect() X (pid %d)", callingPid);
}
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index a421fd3..729e539 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -194,6 +194,11 @@
CameraService();
virtual ~CameraService();
+ // We use a count for number of clients (shoule only be 0 or 1).
+ volatile int32_t mUsers;
+ virtual void incUsers();
+ virtual void decUsers();
+
mutable Mutex mLock;
wp<Client> mClient;
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index 048bdd5..564a1db 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -86,6 +86,14 @@
class Mutex;
class String8;
+// ref-counted object for callbacks
+class CameraListener: virtual public RefBase
+{
+public:
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+};
+
typedef void (*shutter_callback)(void *cookie);
typedef void (*frame_callback)(const sp<IMemory>& mem, void *cookie);
typedef void (*autofocus_callback)(bool focused, void *cookie);
@@ -144,13 +152,8 @@
// get preview/capture parameters - key/value pairs
String8 getParameters() const;
- void setShutterCallback(shutter_callback cb, void *cookie);
- void setRawCallback(frame_callback cb, void *cookie);
- void setJpegCallback(frame_callback cb, void *cookie);
- void setRecordingCallback(frame_callback cb, void *cookie);
- void setPreviewCallback(frame_callback cb, void *cookie, int preview_callback_flag = FRAME_CALLBACK_FLAG_NOOP);
- void setErrorCallback(error_callback cb, void *cookie);
- void setAutoFocusCallback(autofocus_callback cb, void *cookie);
+ void setListener(const sp<CameraListener>& listener);
+ void setPreviewCallbackFlags(int preview_callback_flag);
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
@@ -179,20 +182,7 @@
sp<ICamera> mCamera;
status_t mStatus;
- shutter_callback mShutterCallback;
- void *mShutterCallbackCookie;
- frame_callback mRawCallback;
- void *mRawCallbackCookie;
- frame_callback mJpegCallback;
- void *mJpegCallbackCookie;
- frame_callback mPreviewCallback;
- void *mPreviewCallbackCookie;
- frame_callback mRecordingCallback;
- void *mRecordingCallbackCookie;
- error_callback mErrorCallback;
- void *mErrorCallbackCookie;
- autofocus_callback mAutoFocusCallback;
- void *mAutoFocusCallbackCookie;
+ sp<CameraListener> mListener;
friend class DeathNotifier;
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
index a21359f..759a0cc 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -43,6 +43,7 @@
struct FileState {
int modTime_sec;
int modTime_nsec;
+ int mode;
int size;
int crc32;
int nameLen;
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 6613700..bb22dab 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -85,20 +85,6 @@
void Camera::init()
{
mStatus = UNKNOWN_ERROR;
- mShutterCallback = 0;
- mShutterCallbackCookie = 0;
- mRawCallback = 0;
- mRawCallbackCookie = 0;
- mJpegCallback = 0;
- mJpegCallbackCookie = 0;
- mPreviewCallback = 0;
- mPreviewCallbackCookie = 0;
- mRecordingCallback = 0;
- mRecordingCallbackCookie = 0;
- mErrorCallback = 0;
- mErrorCallbackCookie = 0;
- mAutoFocusCallback = 0;
- mAutoFocusCallbackCookie = 0;
}
Camera::~Camera()
@@ -127,7 +113,6 @@
{
LOGV("disconnect");
if (mCamera != 0) {
- mErrorCallback = 0;
mCamera->disconnect();
mCamera = 0;
}
@@ -285,125 +270,49 @@
return params;
}
-void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie)
+void Camera::setListener(const sp<CameraListener>& listener)
{
- LOGV("setAutoFocusCallback");
- mAutoFocusCallback = cb;
- mAutoFocusCallbackCookie = cookie;
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
}
-void Camera::setShutterCallback(shutter_callback cb, void *cookie)
+void Camera::setPreviewCallbackFlags(int flag)
{
- LOGV("setShutterCallback");
- mShutterCallback = cb;
- mShutterCallbackCookie = cookie;
-}
-
-void Camera::setRawCallback(frame_callback cb, void *cookie)
-{
- LOGV("setRawCallback");
- mRawCallback = cb;
- mRawCallbackCookie = cookie;
-}
-
-void Camera::setJpegCallback(frame_callback cb, void *cookie)
-{
- LOGV("setJpegCallback");
- mJpegCallback = cb;
- mJpegCallbackCookie = cookie;
-}
-
-void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag)
-{
- LOGV("setPreviewCallback");
- mPreviewCallback = cb;
- mPreviewCallbackCookie = cookie;
+ LOGV("setPreviewCallbackFlags");
sp <ICamera> c = mCamera;
if (c == 0) return;
mCamera->setPreviewCallbackFlag(flag);
}
-void Camera::setRecordingCallback(frame_callback cb, void *cookie)
-{
- LOGV("setRecordingCallback");
- mRecordingCallback = cb;
- mRecordingCallbackCookie = cookie;
-}
-
-void Camera::setErrorCallback(error_callback cb, void *cookie)
-{
- LOGV("setErrorCallback");
- mErrorCallback = cb;
- mErrorCallbackCookie = cookie;
-}
-
// callback from camera service
void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
{
- switch(msgType) {
- case CAMERA_MSG_ERROR:
- LOGV("errorCallback");
- if (mErrorCallback) {
- mErrorCallback((status_t)ext1, mErrorCallbackCookie);
- }
- break;
- case CAMERA_MSG_FOCUS:
- LOGV("autoFocusCallback");
- if (mAutoFocusCallback) {
- mAutoFocusCallback((bool)ext1, mAutoFocusCallbackCookie);
- }
- break;
- case CAMERA_MSG_SHUTTER:
- LOGV("shutterCallback");
- if (mShutterCallback) {
- mShutterCallback(mShutterCallbackCookie);
- }
- break;
- default:
- LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2);
- break;
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->notify(msgType, ext1, ext2);
}
}
// callback from camera service when frame or image is ready
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
{
- switch(msgType) {
- case CAMERA_MSG_PREVIEW_FRAME:
- LOGV("previewCallback");
- if (mPreviewCallback) {
- mPreviewCallback(dataPtr, mPreviewCallbackCookie);
- }
- break;
- case CAMERA_MSG_VIDEO_FRAME:
- LOGV("recordingCallback");
- if (mRecordingCallback) {
- mRecordingCallback(dataPtr, mRecordingCallbackCookie);
- }
- break;
- case CAMERA_MSG_RAW_IMAGE:
- LOGV("rawCallback");
- if (mRawCallback) {
- mRawCallback(dataPtr, mRawCallbackCookie);
- }
- break;
- case CAMERA_MSG_COMPRESSED_IMAGE:
- LOGV("jpegCallback");
- if (mJpegCallback) {
- mJpegCallback(dataPtr, mJpegCallbackCookie);
- }
- break;
- default:
- LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
- break;
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->postData(msgType, dataPtr);
}
}
void Camera::binderDied(const wp<IBinder>& who) {
LOGW("ICamera died");
- if (mErrorCallback) {
- mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie);
- }
+ notifyCallback(CAMERA_MSG_ERROR, DEAD_OBJECT, 0);
}
void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index d65a457..67d07fe 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -302,6 +302,7 @@
r.s.modTime_sec = st.st_mtime;
r.s.modTime_nsec = 0; // workaround sim breakage
//r.s.modTime_nsec = st.st_mtime_nsec;
+ r.s.mode = st.st_mode;
r.s.size = st.st_size;
// we compute the crc32 later down below, when we already have the file open.
@@ -349,12 +350,12 @@
g.s.crc32 = compute_crc32(fd);
LOGP("%s", q.string());
- LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x",
- f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
- LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x",
- g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
+ LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+ f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
+ LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+ g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
- || f.size != g.s.size || f.crc32 != g.s.crc32) {
+ || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
write_update_file(dataStream, fd, p, g.file.string());
}
@@ -450,6 +451,7 @@
r.s.modTime_sec = st.st_mtime;
r.s.modTime_nsec = 0; // workaround sim breakage
//r.s.modTime_nsec = st.st_mtime_nsec;
+ r.s.mode = st.st_mode;
r.s.size = st.st_size;
r.s.crc32 = crc;
@@ -623,6 +625,7 @@
states[0].modTime_sec = 0xfedcba98;
states[0].modTime_nsec = 0xdeadbeef;
+ states[0].mode = 0777; // decimal 511, hex 0x000001ff
states[0].size = 0xababbcbc;
states[0].crc32 = 0x12345678;
states[0].nameLen = -12;
@@ -632,6 +635,7 @@
states[1].modTime_sec = 0x93400031;
states[1].modTime_nsec = 0xdeadbeef;
+ states[1].mode = 0666; // decimal 438, hex 0x000001b6
states[1].size = 0x88557766;
states[1].crc32 = 0x22334422;
states[1].nameLen = -1;
@@ -641,6 +645,7 @@
states[2].modTime_sec = 0x33221144;
states[2].modTime_nsec = 0xdeadbeef;
+ states[2].mode = 0744; // decimal 484, hex 0x000001e4
states[2].size = 0x11223344;
states[2].crc32 = 0x01122334;
states[2].nameLen = 0;
@@ -650,6 +655,7 @@
states[3].modTime_sec = 0x33221144;
states[3].modTime_nsec = 0xdeadbeef;
+ states[3].mode = 0755; // decimal 493, hex 0x000001ed
states[3].size = 0x11223344;
states[3].crc32 = 0x01122334;
states[3].nameLen = 0;
@@ -669,35 +675,38 @@
static const unsigned char correct_data[] = {
// header
0x53, 0x6e, 0x61, 0x70, 0x04, 0x00, 0x00, 0x00,
- 0x46, 0x69, 0x6c, 0x65, 0xac, 0x00, 0x00, 0x00,
+ 0x46, 0x69, 0x6c, 0x65, 0xbc, 0x00, 0x00, 0x00,
// bytes_of_padding
0x98, 0xba, 0xdc, 0xfe, 0xef, 0xbe, 0xad, 0xde,
- 0xbc, 0xbc, 0xab, 0xab, 0x78, 0x56, 0x34, 0x12,
- 0x10, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
- 0x64, 0x69, 0x6e, 0x67,
+ 0xff, 0x01, 0x00, 0x00, 0xbc, 0xbc, 0xab, 0xab,
+ 0x78, 0x56, 0x34, 0x12, 0x10, 0x00, 0x00, 0x00,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
// bytes_of_padding3
0x31, 0x00, 0x40, 0x93, 0xef, 0xbe, 0xad, 0xde,
- 0x66, 0x77, 0x55, 0x88, 0x22, 0x44, 0x33, 0x22,
- 0x11, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
- 0x64, 0x69, 0x6e, 0x67, 0x33, 0xab, 0xab, 0xab,
+ 0xb6, 0x01, 0x00, 0x00, 0x66, 0x77, 0x55, 0x88,
+ 0x22, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x00,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x33, 0xab, 0xab, 0xab,
// bytes of padding2
0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
- 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
- 0x12, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
- 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x32, 0xab, 0xab,
+ 0xe4, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
+ 0x34, 0x23, 0x12, 0x01, 0x12, 0x00, 0x00, 0x00,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x5f, 0x32, 0xab, 0xab,
// bytes of padding3
0x44, 0x11, 0x22, 0x33, 0xef, 0xbe, 0xad, 0xde,
- 0x44, 0x33, 0x22, 0x11, 0x34, 0x23, 0x12, 0x01,
- 0x13, 0x00, 0x00, 0x00, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x61, 0x64,
- 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x5f, 0x31, 0xab
+ 0xed, 0x01, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11,
+ 0x34, 0x23, 0x12, 0x01, 0x13, 0x00, 0x00, 0x00,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x66,
+ 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x5f, 0x5f, 0x31, 0xab
};
err = compare_file(filename, correct_data, sizeof(correct_data));
@@ -731,14 +740,14 @@
const FileState state = readSnapshot.valueAt(i);
if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
- || states[i].modTime_nsec != state.modTime_nsec
+ || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
|| states[i].size != state.size || states[i].crc32 != states[i].crc32) {
- fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
- " actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
- states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
- name.length(), filenames[i].string(),
- state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
- name.string());
+ fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
+ " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
+ states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
+ states[i].crc32, name.length(), filenames[i].string(),
+ state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
+ state.nameLen, name.string());
matched = false;
}
}
@@ -839,6 +848,7 @@
size_t actualSize;
bool done;
int type;
+ ssize_t nRead;
// printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
@@ -873,8 +883,9 @@
goto finished;
}
- err = reader.ReadEntityData(buf, bufSize);
- if (err != NO_ERROR) {
+ nRead = reader.ReadEntityData(buf, bufSize);
+ if (nRead < 0) {
+ err = reader.Status();
fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
goto finished;
}