Merge change 4556 into donut
* changes:
Added info about mcc and mnc, plus other changes per http://b/1918247; rewrote "How Android find best match" section per rgreenwalt's comments and added flowchart.
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index a3ab641..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 {
@@ -42,6 +43,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
+#include <signal.h>
}
// When you enable this, as well as DEBUG_REFS=1 and
@@ -63,6 +65,10 @@
static int debug_frame_cnt;
#endif
+static int getCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
// ----------------------------------------------------------------------------
void CameraService::instantiate() {
@@ -76,6 +82,7 @@
BnCameraService()
{
LOGI("CameraService started: pid=%d", getpid());
+ mUsers = 0;
}
CameraService::~CameraService()
@@ -87,7 +94,9 @@
sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
{
- LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
+ int callingPid = getCallingPid();
+ LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
+ cameraClient->asBinder().get());
Mutex::Autolock lock(mLock);
sp<Client> client;
@@ -96,36 +105,50 @@
if (currentClient != 0) {
sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
- // this is the same client reconnecting...
- LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get());
+ // This is the same client reconnecting...
+ LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...",
+ callingPid, cameraClient->asBinder().get());
return currentClient;
} else {
- // it's another client... reject it
- LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get());
+ // It's another client... reject it
+ LOGD("CameraService::connect X (pid %d, new client %p) rejected. "
+ "(old pid %d, old client %p)",
+ callingPid, cameraClient->asBinder().get(),
+ currentClient->mClientPid, currentCameraClient->asBinder().get());
+ if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
+ LOGD("The old client is dead!");
+ }
return client;
}
} else {
// can't promote, the previous client has died...
- LOGD("new client connecting, old reference was dangling...");
+ LOGD("New client (pid %d) connecting, old reference was dangling...",
+ callingPid);
mClient.clear();
+ if (mUsers > 0) {
+ LOGD("Still have client, rejected");
+ return client;
+ }
}
}
// create a new Client object
- client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
+ client = new Client(this, cameraClient, callingPid);
mClient = client;
#if DEBUG_CLIENT_REFERENCES
// Enable tracking for this object, and track increments and decrements of
// the refcount.
client->trackMe(true, true);
#endif
- LOGD("Connect X");
+ LOGD("CameraService::connect X");
return client;
}
void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
{
- // declar this outside the lock to make absolutely sure the
+ int callingPid = getCallingPid();
+
+ // Declare this outside the lock to make absolutely sure the
// destructor won't be called with the lock held.
sp<Client> client;
@@ -133,26 +156,42 @@
if (mClient == 0) {
// This happens when we have already disconnected.
- LOGV("mClient is null.");
+ LOGD("removeClient (pid %d): already disconnected", callingPid);
return;
}
- // Promote mClient. It should never fail because we're called from
- // a binder call, so someone has to have a strong reference.
+ // Promote mClient. It can fail if we are called from this path:
+ // Client::~Client() -> disconnect() -> removeClient().
client = mClient.promote();
if (client == 0) {
- LOGW("can't get a strong reference on mClient!");
+ LOGD("removeClient (pid %d): no more strong reference", callingPid);
mClient.clear();
return;
}
if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
// ugh! that's not our client!!
- LOGW("removeClient() called, but mClient doesn't match!");
+ LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
} else {
// okay, good, forget about mClient
mClient.clear();
}
+
+ 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)
@@ -177,7 +216,8 @@
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient, pid_t clientPid)
{
- LOGD("Client E constructor");
+ int callingPid = getCallingPid();
+ LOGD("Client::Client E (pid %d)", callingPid);
mCameraService = cameraService;
mCameraClient = cameraClient;
mClientPid = clientPid;
@@ -189,22 +229,28 @@
// Callback is disabled by default
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
- LOGD("Client X constructor");
+ cameraService->incUsers();
+ LOGD("Client::Client X (pid %d)", callingPid);
}
status_t CameraService::Client::checkPid()
{
- if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
- LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get());
+ int callingPid = getCallingPid();
+ if (mClientPid == callingPid) return NO_ERROR;
+ LOGW("Attempt to use locked camera (client %p) from different process "
+ " (old pid %d, new pid %d)",
+ getCameraClient()->asBinder().get(), mClientPid, callingPid);
return -EBUSY;
}
status_t CameraService::Client::lock()
{
+ int callingPid = getCallingPid();
+ LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
Mutex::Autolock _l(mLock);
// lock camera to this client if the the camera is unlocked
if (mClientPid == 0) {
- mClientPid = IPCThreadState::self()->getCallingPid();
+ mClientPid = callingPid;
return NO_ERROR;
}
// returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
@@ -213,13 +259,14 @@
status_t CameraService::Client::unlock()
{
+ int callingPid = getCallingPid();
+ LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
Mutex::Autolock _l(mLock);
// allow anyone to use camera
- LOGV("unlock (%p)", getCameraClient()->asBinder().get());
status_t result = checkPid();
if (result == NO_ERROR) {
mClientPid = 0;
-
+ LOGD("clear mCameraClient (pid %d)", callingPid);
// we need to remove the reference so that when app goes
// away, the reference count goes to 0.
mCameraClient.clear();
@@ -229,15 +276,17 @@
status_t CameraService::Client::connect(const sp<ICameraClient>& client)
{
+ int callingPid = getCallingPid();
+
// connect a new process to the camera
- LOGV("connect (%p)", client->asBinder().get());
+ LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
// I hate this hack, but things get really ugly when the media recorder
// service is handing back the camera to the app. The ICameraClient
// destructor will be called during the same IPC, making it look like
// the remote client is trying to disconnect. This hack temporarily
// sets the mClientPid to an invalid pid to prevent the hardware from
- // being torn down.
+ // being torn down.
{
// hold a reference to the old client or we will deadlock if the client is
@@ -246,24 +295,29 @@
{
Mutex::Autolock _l(mLock);
if (mClientPid != 0 && checkPid() != NO_ERROR) {
- LOGW("Tried to connect to locked camera");
+ LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
+ mClientPid, callingPid);
return -EBUSY;
}
oldClient = mCameraClient;
// did the client actually change?
- if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
+ if (client->asBinder() == mCameraClient->asBinder()) {
+ LOGD("Connect to the same client");
+ return NO_ERROR;
+ }
mCameraClient = client;
mClientPid = -1;
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
- LOGV("connect new process (%d) to existing camera client", mClientPid);
+ LOGD("Connect to the new client (pid %d, client %p)",
+ callingPid, mCameraClient->asBinder().get());
}
}
// the old client destructor is called when oldClient goes out of scope
// now we set the new PID to lock the interface again
- mClientPid = IPCThreadState::self()->getCallingPid();
+ mClientPid = callingPid;
return NO_ERROR;
}
@@ -280,8 +334,11 @@
CameraService::Client::~Client()
{
+ int callingPid = getCallingPid();
+
// tear down client
- LOGD("Client (%p) E destructor", getCameraClient()->asBinder().get());
+ LOGD("Client::~Client E (pid %d, client %p)",
+ callingPid, getCameraClient()->asBinder().get());
if (mSurface != 0 && !mUseOverlay) {
#if HAVE_ANDROID_OS
pthread_t thr;
@@ -307,45 +364,53 @@
}
// make sure we tear down the hardware
- mClientPid = IPCThreadState::self()->getCallingPid();
+ mClientPid = callingPid;
disconnect();
- LOGD("Client X destructor");
+ LOGD("Client::~Client X (pid %d)", mClientPid);
}
void CameraService::Client::disconnect()
{
- LOGD("Client (%p) E disconnect from (%d)",
- getCameraClient()->asBinder().get(),
- IPCThreadState::self()->getCallingPid());
+ int callingPid = getCallingPid();
+
+ LOGD("Client::disconnect() E (pid %d client %p)",
+ callingPid, getCameraClient()->asBinder().get());
+
Mutex::Autolock lock(mLock);
if (mClientPid <= 0) {
- LOGV("camera is unlocked, don't tear down hardware");
+ LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
return;
}
if (checkPid() != NO_ERROR) {
- LOGV("Different client - don't disconnect");
+ LOGD("Different client - don't disconnect");
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) {
- LOGV("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();
- LOGD("Client X disconnect");
+
+ mCameraService->decUsers();
+
+ LOGD("Client::disconnect() X (pid %d)", callingPid);
}
// pass the buffered ISurface to the camera service
status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
{
- LOGD("setPreviewDisplay(%p)", surface.get());
+ LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
Mutex::Autolock lock(mLock);
status_t result = checkPid();
if (result != NO_ERROR) return result;
@@ -365,7 +430,7 @@
// preview are handled.
void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
{
- LOGV("setPreviewCallbackFlag");
+ LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
Mutex::Autolock lock(mLock);
if (checkPid() != NO_ERROR) return;
mPreviewCallbackFlag = callback_flag;
@@ -374,7 +439,9 @@
// start preview mode, must call setPreviewDisplay first
status_t CameraService::Client::startCameraMode(camera_mode mode)
{
- LOGD("startCameraMode(%d)", mode);
+ int callingPid = getCallingPid();
+
+ LOGD("startCameraMode(%d) (pid %d)", mode, callingPid);
/* we cannot call into mHardware with mLock held because
* mHardware has callbacks onto us which acquire this lock
@@ -405,7 +472,7 @@
status_t CameraService::Client::startRecordingMode()
{
- LOGV("startRecordingMode");
+ LOGD("startRecordingMode (pid %d)", getCallingPid());
status_t ret = UNKNOWN_ERROR;
@@ -433,7 +500,7 @@
status_t CameraService::Client::startPreviewMode()
{
- LOGV("startPreviewMode");
+ LOGD("startPreviewMode (pid %d)", getCallingPid());
// if preview has been enabled, nothing needs to be done
if (mHardware->previewEnabled()) {
@@ -500,11 +567,15 @@
status_t CameraService::Client::startPreview()
{
+ LOGD("startPreview (pid %d)", getCallingPid());
+
return startCameraMode(CAMERA_PREVIEW_MODE);
}
status_t CameraService::Client::startRecording()
{
+ LOGD("startRecording (pid %d)", getCallingPid());
+
if (mMediaPlayerBeep.get() != NULL) {
mMediaPlayerBeep->seekTo(0);
mMediaPlayerBeep->start();
@@ -515,7 +586,7 @@
// stop preview mode
void CameraService::Client::stopPreview()
{
- LOGD("stopPreview()");
+ LOGD("stopPreview (pid %d)", getCallingPid());
Mutex::Autolock lock(mLock);
if (checkPid() != NO_ERROR) return;
@@ -537,7 +608,7 @@
// stop recording mode
void CameraService::Client::stopRecording()
{
- LOGV("stopRecording()");
+ LOGD("stopRecording (pid %d)", getCallingPid());
Mutex::Autolock lock(mLock);
if (checkPid() != NO_ERROR) return;
@@ -552,15 +623,13 @@
mMediaPlayerBeep->start();
}
mHardware->stopRecording();
- LOGV("stopRecording(), hardware stopped OK");
+ LOGD("stopRecording(), hardware stopped OK");
mPreviewBuffer.clear();
}
// release a recording frame
void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
{
- LOGV("releaseRecordingFrame()");
-
Mutex::Autolock lock(mLock);
if (checkPid() != NO_ERROR) return;
@@ -704,7 +773,7 @@
// take a picture - image is returned in callback
status_t CameraService::Client::autoFocus()
{
- LOGV("autoFocus");
+ LOGD("autoFocus (pid %d)", getCallingPid());
Mutex::Autolock lock(mLock);
status_t result = checkPid();
@@ -722,7 +791,7 @@
// take a picture - image is returned in callback
status_t CameraService::Client::takePicture()
{
- LOGD("takePicture");
+ LOGD("takePicture (pid %d)", getCallingPid());
Mutex::Autolock lock(mLock);
status_t result = checkPid();
@@ -920,6 +989,7 @@
void CameraService::Client::postShutter()
{
+ LOGD("postShutter");
mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
}
@@ -1029,7 +1099,7 @@
if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
snprintf(buffer, SIZE, "Permission Denial: "
"can't dump CameraService from pid=%d, uid=%d\n",
- IPCThreadState::self()->getCallingPid(),
+ getCallingPid(),
IPCThreadState::self()->getCallingUid());
result.append(buffer);
write(fd, result.string(), result.size());
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/cmds/keystore/commands.c b/cmds/keystore/commands.c
index e53cece..17dd060 100644
--- a/cmds/keystore/commands.c
+++ b/cmds/keystore/commands.c
@@ -1,5 +1,5 @@
/*
-** Copyright 2008, The Android Open Source Project
+** Copyright 2009, 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.
@@ -30,7 +30,8 @@
return d;
}
-static int list_files(const char *dir, char reply[REPLY_MAX]) {
+static int list_files(const char *dir, char reply[REPLY_MAX])
+{
struct dirent *de;
DIR *d;
@@ -39,7 +40,9 @@
}
reply[0]=0;
while ((de = readdir(d))) {
- if (de->d_type != DT_REG) continue;
+ if (de->d_type != DT_DIR) continue;
+ if ((strcmp(DOT, de->d_name) == 0) ||
+ (strcmp(DOTDOT, de->d_name) == 0)) continue;
if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX);
if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) {
LOGE("reply is too long(too many files under '%s'\n", dir);
@@ -50,31 +53,25 @@
return 0;
}
-static int copy_keyfile(const char *keystore, const char *srcfile) {
- int srcfd, dstfd;
- int length;
- char buf[2048];
- char dstfile[KEYNAME_LENGTH];
- const char *filename = strrchr(srcfile, '/');
+static int copy_keyfile(const char *src, int src_type, const char *dstfile) {
+ int srcfd = -1, dstfd;
+ char buf[REPLY_MAX];
- strlcpy(dstfile, keystore, KEYNAME_LENGTH);
- strlcat(dstfile, "/", KEYNAME_LENGTH);
- if (strlcat(dstfile, filename ? filename + 1 : srcfile,
- KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
- LOGE("keyname is too long '%s'\n", srcfile);
- return -1;
- }
-
- if ((srcfd = open(srcfile, O_RDONLY)) == -1) {
- LOGE("Cannot open the original file '%s'\n", srcfile);
+ if ((src_type == IS_FILE) && (srcfd = open(src, O_RDONLY)) == -1) {
+ LOGE("Cannot open the original file '%s'\n", src);
return -1;
}
if ((dstfd = open(dstfile, O_CREAT|O_RDWR)) == -1) {
LOGE("Cannot open the destination file '%s'\n", dstfile);
return -1;
}
- while((length = read(srcfd, buf, 2048)) > 0) {
- write(dstfd, buf, length);
+ if (src_type == IS_FILE) {
+ int length;
+ while((length = read(srcfd, buf, REPLY_MAX)) > 0) {
+ write(dstfd, buf, length);
+ }
+ } else {
+ write(dstfd, src, strlen(src));
}
close(srcfd);
close(dstfd);
@@ -82,60 +79,149 @@
return 0;
}
-static int install_key(const char *dir, const char *keyfile)
+static int install_key(const char *path, const char *certname, const char *src,
+ int src_is_file, char *dstfile)
{
struct dirent *de;
+ char fullpath[KEYNAME_LENGTH];
DIR *d;
- if ((d = open_keystore(dir)) == NULL) {
+ if (snprintf(fullpath, sizeof(fullpath), "%s/%s/", path, certname)
+ >= KEYNAME_LENGTH) {
+ LOGE("cert name '%s' is too long.\n", certname);
return -1;
}
- return copy_keyfile(dir, keyfile);
+
+ if ((d = open_keystore(fullpath)) == NULL) {
+ LOGE("Can not open the keystore '%s'\n", fullpath);
+ return -1;
+ }
+ closedir(d);
+ if (strlcat(fullpath, dstfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
+ LOGE("cert name '%s' is too long.\n", certname);
+ return -1;
+ }
+ return copy_keyfile(src, src_is_file, fullpath);
}
-static int remove_key(const char *dir, const char *keyfile)
+static int get_key(const char *path, const char *keyname, const char *file,
+ char reply[REPLY_MAX])
{
- char dstfile[KEYNAME_LENGTH];
+ struct dirent *de;
+ char filename[KEYNAME_LENGTH];
+ int fd;
- strlcpy(dstfile, dir, KEYNAME_LENGTH);
- strlcat(dstfile, "/", KEYNAME_LENGTH);
- if (strlcat(dstfile, keyfile, KEYNAME_LENGTH) >= KEYNAME_LENGTH) {
- LOGE("keyname is too long '%s'\n", keyfile);
+ if (snprintf(filename, sizeof(filename), "%s/%s/%s", path, keyname, file)
+ >= KEYNAME_LENGTH) {
+ LOGE("cert name '%s' is too long.\n", keyname);
return -1;
}
- if (unlink(dstfile)) {
- LOGE("cannot delete '%s': %s\n", dstfile, strerror(errno));
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ return -1;
+ }
+ close(fd);
+ strlcpy(reply, filename, REPLY_MAX);
+ return 0;
+}
+
+static int remove_key(const char *dir, const char *key)
+{
+ char dstfile[KEYNAME_LENGTH];
+ char *keyfile[4] = { USER_KEY, USER_P12_CERT, USER_CERTIFICATE,
+ CA_CERTIFICATE };
+ int i, count = 0;
+
+ for ( i = 0 ; i < 4 ; i++) {
+ if (snprintf(dstfile, KEYNAME_LENGTH, "%s/%s/%s", dir, key, keyfile[i])
+ >= KEYNAME_LENGTH) {
+ LOGE("keyname is too long '%s'\n", key);
+ return -1;
+ }
+ if (unlink(dstfile) == 0) count++;
+ }
+
+ if (count == 0) {
+ LOGE("can not clean up '%s' keys or not exist\n", key);
+ return -1;
+ }
+
+ snprintf(dstfile, KEYNAME_LENGTH, "%s/%s", dir, key);
+ if (rmdir(dstfile)) {
+ LOGE("can not clean up '%s' directory\n", key);
return -1;
}
return 0;
}
-int list_certs(char reply[REPLY_MAX])
+int list_user_certs(char reply[REPLY_MAX])
{
return list_files(CERTS_DIR, reply);
}
-int list_userkeys(char reply[REPLY_MAX])
+int list_ca_certs(char reply[REPLY_MAX])
{
- return list_files(USERKEYS_DIR, reply);
+ return list_files(CACERTS_DIR, reply);
}
-int install_cert(const char *certfile)
+int install_user_cert(const char *keyname, const char *cert, const char *key)
{
- return install_key(CERTS_DIR, certfile);
+ if (install_key(CERTS_DIR, keyname, cert, IS_FILE, USER_CERTIFICATE) == 0) {
+ return install_key(CERTS_DIR, keyname, key, IS_FILE, USER_KEY);
+ }
+ return -1;
}
-int install_userkey(const char *keyfile)
+int install_ca_cert(const char *keyname, const char *certfile)
{
- return install_key(USERKEYS_DIR, keyfile);
+ return install_key(CACERTS_DIR, keyname, certfile, IS_FILE, CA_CERTIFICATE);
}
-int remove_cert(const char *certfile)
+int install_p12_cert(const char *keyname, const char *certfile)
{
- return remove_key(CERTS_DIR, certfile);
+ return install_key(CERTS_DIR, keyname, certfile, IS_FILE, USER_P12_CERT);
}
-int remove_userkey(const char *keyfile)
+int add_ca_cert(const char *keyname, const char *certificate)
{
- return remove_key(USERKEYS_DIR, keyfile);
+ return install_key(CACERTS_DIR, keyname, certificate, IS_CONTENT,
+ CA_CERTIFICATE);
+}
+
+int add_user_cert(const char *keyname, const char *certificate)
+{
+ return install_key(CERTS_DIR, keyname, certificate, IS_CONTENT,
+ USER_CERTIFICATE);
+}
+
+int add_user_key(const char *keyname, const char *key)
+{
+ return install_key(CERTS_DIR, keyname, key, IS_CONTENT, USER_KEY);
+}
+
+int get_ca_cert(const char *keyname, char reply[REPLY_MAX])
+{
+ return get_key(CACERTS_DIR, keyname, CA_CERTIFICATE, reply);
+}
+
+int get_user_cert(const char *keyname, char reply[REPLY_MAX])
+{
+ return get_key(CERTS_DIR, keyname, USER_CERTIFICATE, reply);
+}
+
+int get_user_key(const char *keyname, char reply[REPLY_MAX])
+{
+ if(get_key(CERTS_DIR, keyname, USER_KEY, reply))
+ return get_key(CERTS_DIR, keyname, USER_P12_CERT, reply);
+ return 0;
+}
+
+int remove_user_cert(const char *key)
+{
+ return remove_key(CERTS_DIR, key);
+}
+
+int remove_ca_cert(const char *key)
+{
+ return remove_key(CACERTS_DIR, key);
}
diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c
index 5193b3d..df8d832 100644
--- a/cmds/keystore/keystore.c
+++ b/cmds/keystore/keystore.c
@@ -16,37 +16,89 @@
#include "keystore.h"
-
-static int do_list_certs(char **arg, char reply[REPLY_MAX])
+static inline int has_whitespace(char *name)
{
- return list_certs(reply);
+ if((strrchr(name, ' ') != NULL)) {
+ LOGE("'%s' contains whitespace character\n", name);
+ return 1;
+ }
+ return 0;
}
-static int do_list_userkeys(char **arg, char reply[REPLY_MAX])
+static int do_list_user_certs(char **arg, char reply[REPLY_MAX])
{
- return list_userkeys(reply);
+ return list_user_certs(reply);
}
-static int do_install_cert(char **arg, char reply[REPLY_MAX])
+static int do_list_ca_certs(char **arg, char reply[REPLY_MAX])
{
- return install_cert(arg[0]); /* move the certificate to keystore */
+ return list_ca_certs(reply);
}
-static int do_remove_cert(char **arg, char reply[REPLY_MAX])
+static int do_install_user_cert(char **arg, char reply[REPLY_MAX])
{
- return remove_cert(arg[0]); /* certificate */
+ if (has_whitespace(arg[0])) return -1;
+ /* copy the certificate and key to keystore */
+ return install_user_cert(arg[0], arg[1], arg[2]);
}
-static int do_install_userkey(char **arg, char reply[REPLY_MAX])
+static int do_install_p12_cert(char **arg, char reply[REPLY_MAX])
{
- return install_userkey(arg[0]); /* move the certificate to keystore */
+ if (has_whitespace(arg[0])) return -1;
+ return install_p12_cert(arg[0], arg[1]);
}
-static int do_remove_userkey(char **arg, char reply[REPLY_MAX])
+static int do_install_ca_cert(char **arg, char reply[REPLY_MAX])
{
- return remove_userkey(arg[0]); /* userkey */
+ if (has_whitespace(arg[0])) return -1;
+ /* copy the certificate and key to keystore */
+ return install_ca_cert(arg[0], arg[1]);
}
+static int do_add_ca_cert(char **arg, char reply[REPLY_MAX])
+{
+ if (has_whitespace(arg[0])) return -1;
+ return add_ca_cert(arg[0], arg[1]);
+}
+
+static int do_add_user_cert(char **arg, char reply[REPLY_MAX])
+{
+ if (has_whitespace(arg[0])) return -1;
+ return add_user_cert(arg[0], arg[1]);
+}
+
+static int do_add_user_key(char **arg, char reply[REPLY_MAX])
+{
+ if (has_whitespace(arg[0])) return -1;
+ return add_user_key(arg[0], arg[1]);
+}
+
+static int do_get_ca_cert(char **arg, char reply[REPLY_MAX])
+{
+ return get_ca_cert(arg[0], reply);
+}
+
+static int do_get_user_cert(char **arg, char reply[REPLY_MAX])
+{
+ return get_user_cert(arg[0], reply);
+}
+
+static int do_get_user_key(char **arg, char reply[REPLY_MAX])
+{
+ return get_user_key(arg[0], reply);
+}
+
+static int do_remove_user_cert(char **arg, char reply[REPLY_MAX])
+{
+ return remove_user_cert(arg[0]);
+}
+
+static int do_remove_ca_cert(char **arg, char reply[REPLY_MAX])
+{
+ return remove_ca_cert(arg[0]);
+}
+
+
struct cmdinfo {
const char *name;
unsigned numargs;
@@ -55,12 +107,19 @@
struct cmdinfo cmds[] = {
- { "listcerts", 0, do_list_certs },
- { "listuserkeys", 0, do_list_userkeys },
- { "installcert", 1, do_install_cert },
- { "removecert", 1, do_remove_cert },
- { "installuserkey", 1, do_install_userkey },
- { "removeuserkey", 1, do_remove_userkey },
+ { "listcacerts", 0, do_list_ca_certs },
+ { "listusercerts", 0, do_list_user_certs },
+ { "installusercert", 3, do_install_user_cert },
+ { "installcacert", 2, do_install_ca_cert },
+ { "installp12cert", 2, do_install_p12_cert },
+ { "addusercert", 2, do_add_user_cert },
+ { "adduserkey", 2, do_add_user_key },
+ { "addcacert", 2, do_add_ca_cert },
+ { "getusercert", 1, do_get_user_cert },
+ { "getuserkey", 1, do_get_user_key },
+ { "getcacert", 1, do_get_ca_cert },
+ { "removecacert", 1, do_remove_ca_cert },
+ { "removeusercert", 1, do_remove_user_cert },
};
static int readx(int s, void *_buf, int count)
@@ -121,7 +180,7 @@
/* n is number of args (not counting arg[0]) */
arg[0] = cmd;
while (*cmd) {
- if (isspace(*cmd)) {
+ if (*cmd == CMD_DELIMITER) {
*cmd++ = 0;
n++;
arg[n] = cmd;
@@ -167,6 +226,7 @@
int fd, i;
short ret;
unsigned short count;
+ char delimiter[2] = { CMD_DELIMITER, 0 };
char buf[BUFFER_MAX]="";
fd = socket_local_client(SOCKET_PATH,
@@ -177,7 +237,7 @@
exit(1);
}
for(i = 0; i < argc; i++) {
- if (i > 0) strlcat(buf, " ", BUFFER_MAX);
+ if (i > 0) strlcat(buf, delimiter, BUFFER_MAX);
if(strlcat(buf, argv[i], BUFFER_MAX) >= BUFFER_MAX) {
fprintf(stderr, "Arguments are too long\n");
exit(1);
diff --git a/cmds/keystore/keystore.h b/cmds/keystore/keystore.h
index 35acf0b..b9cb185 100644
--- a/cmds/keystore/keystore.h
+++ b/cmds/keystore/keystore.h
@@ -40,18 +40,35 @@
/* path of the keystore */
#define KEYSTORE_DIR_PREFIX "/data/misc/keystore"
-#define CERTS_DIR KEYSTORE_DIR_PREFIX "/certs"
-#define USERKEYS_DIR KEYSTORE_DIR_PREFIX "/userkeys"
+#define CERTS_DIR KEYSTORE_DIR_PREFIX "/keys"
+#define CACERTS_DIR KEYSTORE_DIR_PREFIX "/cacerts"
+#define CA_CERTIFICATE "ca.crt"
+#define USER_CERTIFICATE "user.crt"
+#define USER_P12_CERT "user.p12"
+#define USER_KEY "user.key"
+#define DOT "."
+#define DOTDOT ".."
-#define BUFFER_MAX 1024 /* input buffer for commands */
+#define BUFFER_MAX 4096 /* input buffer for commands */
#define TOKEN_MAX 8 /* max number of arguments in buffer */
-#define REPLY_MAX 1024 /* largest reply allowed */
+#define REPLY_MAX 4096 /* largest reply allowed */
+#define CMD_DELIMITER '\t'
#define KEYNAME_LENGTH 128
+#define IS_CONTENT 0
+#define IS_FILE 1
+
/* commands.c */
-int list_certs(char reply[REPLY_MAX]);
-int list_userkeys(char reply[REPLY_MAX]);
-int install_cert(const char *certfile);
-int install_userkey(const char *keyfile);
-int remove_cert(const char *certfile);
-int remove_userkey(const char *keyfile);
+int list_ca_certs(char reply[REPLY_MAX]);
+int list_user_certs(char reply[REPLY_MAX]);
+int install_user_cert(const char *certname, const char *cert, const char *key);
+int install_ca_cert(const char *certname, const char *cert);
+int install_p12_cert(const char *certname, const char *cert);
+int add_ca_cert(const char *certname, const char *content);
+int add_user_cert(const char *certname, const char *content);
+int add_user_key(const char *keyname, const char *content);
+int get_ca_cert(const char *keyname, char reply[REPLY_MAX]);
+int get_user_cert(const char *keyname, char reply[REPLY_MAX]);
+int get_user_key(const char *keyname, char reply[REPLY_MAX]);
+int remove_user_cert(const char *certname);
+int remove_ca_cert(const char *certname);
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 0c7ad46..a85f275 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -456,7 +456,7 @@
void validate();
matrixf_t& top() { return stack[depth]; }
const matrixf_t& top() const { return stack[depth]; }
- const uint32_t top_ops() const { return ops[depth]; }
+ uint32_t top_ops() const { return ops[depth]; }
inline bool isRigidBody() const {
return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE));
}
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index d2aa30e..8486532 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -99,14 +99,18 @@
// @param size length of the language value
// @return TTS_SUCCESS, or TTS_FAILURE
virtual tts_result loadLanguage(const char *value, const size_t size);
-
- // Signal the engine to use the specified language. This will force the
- // language to be loaded if it wasn't loaded previously with loadLanguage().
- // See loadLanguage for the specification of the language.
- // @param value pointer to the language value
- // @param size length of the language value
+
+ // Load the resources associated with the specified language, country and Locale variant.
+ // The loaded language will only be used once a call to setLanguageFromLocale() with the same
+ // language value is issued. Language and country values are coded according to the ISO three
+ // letter codes for languages and countries, as can be retrieved from a java.util.Locale
+ // instance. The variant value is encoded as the variant string retrieved from a
+ // java.util.Locale instance built with that variant data.
+ // @param lang pointer to the ISO three letter code for the language
+ // @param country pointer to the ISO three letter code for the country
+ // @param variant pointer to the variant code
// @return TTS_SUCCESS, or TTS_FAILURE
- virtual tts_result setLanguage(const char *value, const size_t size);
+ virtual tts_result setLanguage(const char *lang, const char *country, const char *variant);
// Retrieve the currently set language, or an empty "value" if no language
// has been set.
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index 048bdd5..bbc21c4 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -86,10 +86,13 @@
class Mutex;
class String8;
-typedef void (*shutter_callback)(void *cookie);
-typedef void (*frame_callback)(const sp<IMemory>& mem, void *cookie);
-typedef void (*autofocus_callback)(bool focused, void *cookie);
-typedef void (*error_callback)(status_t err, void *cookie);
+// 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;
+};
class Camera : public BnCameraClient, public IBinder::DeathRecipient
{
@@ -144,13 +147,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);
@@ -160,6 +158,8 @@
private:
Camera();
+ Camera(const Camera&);
+ Camera& operator=(const Camera);
virtual void binderDied(const wp<IBinder>& who);
class DeathNotifier: public IBinder::DeathRecipient
@@ -179,20 +179,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 f60f4ea..b1f5045 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -19,33 +19,41 @@
#include <utils/Errors.h>
#include <utils/String8.h>
+#include <utils/KeyedVector.h>
namespace android {
enum {
- BACKUP_HEADER_APP_V1 = 0x31707041, // App1 (little endian)
BACKUP_HEADER_ENTITY_V1 = 0x61746144, // Data (little endian)
- BACKUP_FOOTER_APP_V1 = 0x746f6f46, // Foot (little endian)
};
-// the sizes of all of these match.
-typedef struct {
- int type; // == BACKUP_HEADER_APP_V1
- int packageLen; // length of the name of the package that follows, not including the null.
- int cookie;
-} app_header_v1;
-
typedef struct {
int type; // BACKUP_HEADER_ENTITY_V1
int keyLen; // length of the key name, not including the null terminator
int dataSize; // size of the data, not including the padding, -1 means delete
} entity_header_v1;
-typedef struct {
- int type; // BACKUP_FOOTER_APP_V1
- int entityCount; // the number of entities that were written
- int cookie;
-} app_footer_v1;
+struct SnapshotHeader {
+ int magic0;
+ int fileCount;
+ int magic1;
+ int totalSize;
+};
+
+struct FileState {
+ int modTime_sec;
+ int modTime_nsec;
+ int mode;
+ int size;
+ int crc32;
+ int nameLen;
+};
+
+struct FileRec {
+ String8 file;
+ bool deleted;
+ FileState s;
+};
/**
@@ -61,12 +69,10 @@
// does not close fd
~BackupDataWriter();
- status_t WriteAppHeader(const String8& packageName, int cookie);
-
status_t WriteEntityHeader(const String8& key, size_t dataSize);
status_t WriteEntityData(const void* data, size_t size);
- status_t WriteAppFooter(int cookie);
+ void SetKeyPrefix(const String8& keyPrefix);
private:
explicit BackupDataWriter();
@@ -76,6 +82,7 @@
status_t m_status;
ssize_t m_pos;
int m_entityCount;
+ String8 m_keyPrefix;
};
/**
@@ -92,34 +99,47 @@
~BackupDataReader();
status_t Status();
- status_t ReadNextHeader(int* type = NULL);
+ status_t ReadNextHeader(bool* done, int* type);
- status_t ReadAppHeader(String8* packageName, int* cookie);
bool HasEntities();
status_t ReadEntityHeader(String8* key, size_t* dataSize);
status_t SkipEntityData(); // must be called with the pointer at the begining of the data.
- status_t ReadEntityData(void* data, size_t size);
- status_t ReadAppFooter(int* cookie);
+ ssize_t ReadEntityData(void* data, size_t size);
private:
explicit BackupDataReader();
status_t skip_padding();
int m_fd;
+ bool m_done;
status_t m_status;
ssize_t m_pos;
+ ssize_t m_dataEndPos;
int m_entityCount;
union {
int type;
- app_header_v1 app;
entity_header_v1 entity;
- app_footer_v1 footer;
} m_header;
+ String8 m_key;
};
int back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD,
char const* const* files, char const* const *keys, int fileCount);
+class RestoreHelperBase
+{
+public:
+ RestoreHelperBase();
+ ~RestoreHelperBase();
+
+ status_t WriteFile(const String8& filename, BackupDataReader* in);
+ status_t WriteSnapshot(int fd);
+
+private:
+ void* m_buf;
+ bool m_loggedUnknownMetadata;
+ KeyedVector<String8,FileRec> m_files;
+};
#define TEST_BACKUP_HELPERS 1
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 9b8c302..f1029b7 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -71,7 +71,7 @@
* The relative sizes of the stretchy segments indicates the relative
* amount of stretchiness of the regions bordered by the segments. For
* example, regions 3, 7 and 11 above will take up more horizontal space
- * than regions 1, 5 and 9 since the horizonal segment associated with
+ * than regions 1, 5 and 9 since the horizontal segment associated with
* the first set of regions is larger than the other set of regions. The
* ratios of the amount of horizontal (or vertical) space taken by any
* two stretchable slices is exactly the ratio of their corresponding
@@ -87,7 +87,7 @@
* the leftmost slices always start at x=0 and the rightmost slices
* always end at the end of the image. So, for example, the regions 0,
* 4 and 8 (which are fixed along the X axis) start at x value 0 and
- * go to xDiv[0] amd slices 2, 6 and 10 start at xDiv[1] and end at
+ * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
* xDiv[2].
*
* The array pointed to by the colors field lists contains hints for
@@ -626,25 +626,25 @@
event_code_t next();
// These are available for all nodes:
- const int32_t getCommentID() const;
+ int32_t getCommentID() const;
const uint16_t* getComment(size_t* outLen) const;
- const uint32_t getLineNumber() const;
+ uint32_t getLineNumber() const;
// This is available for TEXT:
- const int32_t getTextID() const;
+ int32_t getTextID() const;
const uint16_t* getText(size_t* outLen) const;
ssize_t getTextValue(Res_value* outValue) const;
// These are available for START_NAMESPACE and END_NAMESPACE:
- const int32_t getNamespacePrefixID() const;
+ int32_t getNamespacePrefixID() const;
const uint16_t* getNamespacePrefix(size_t* outLen) const;
- const int32_t getNamespaceUriID() const;
+ int32_t getNamespaceUriID() const;
const uint16_t* getNamespaceUri(size_t* outLen) const;
// These are available for START_TAG and END_TAG:
- const int32_t getElementNamespaceID() const;
+ int32_t getElementNamespaceID() const;
const uint16_t* getElementNamespace(size_t* outLen) const;
- const int32_t getElementNameID() const;
+ int32_t getElementNameID() const;
const uint16_t* getElementName(size_t* outLen) const;
// Remaining methods are for retrieving information about attributes
@@ -653,14 +653,14 @@
size_t getAttributeCount() const;
// Returns -1 if no namespace, -2 if idx out of range.
- const int32_t getAttributeNamespaceID(size_t idx) const;
+ int32_t getAttributeNamespaceID(size_t idx) const;
const uint16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
- const int32_t getAttributeNameID(size_t idx) const;
+ int32_t getAttributeNameID(size_t idx) const;
const uint16_t* getAttributeName(size_t idx, size_t* outLen) const;
- const uint32_t getAttributeNameResID(size_t idx) const;
+ uint32_t getAttributeNameResID(size_t idx) const;
- const int32_t getAttributeValueStringID(size_t idx) const;
+ int32_t getAttributeValueStringID(size_t idx) const;
const uint16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
int32_t getAttributeDataType(size_t idx) const;
@@ -1781,7 +1781,7 @@
void getLocales(Vector<String8>* locales) const;
#ifndef HAVE_ANDROID_OS
- void print() const;
+ void print(bool inclValues) const;
#endif
private:
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f14d7e9..eec645e 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -189,9 +189,14 @@
char property[PROPERTY_VALUE_MAX];
- if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
- LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
- strcpy(property, "160");
+ /* Read density from build-specific ro.sf.lcd_density property
+ * except if it is overriden by qemu.sf.lcd_density.
+ */
+ if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
+ if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
+ LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
+ strcpy(property, "160");
+ }
}
mDensity = atoi(property) * (1.0f/160.0f);
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/BackupData.cpp b/libs/utils/BackupData.cpp
index 8c9f875..0868cff 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -86,46 +86,6 @@
}
status_t
-BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie)
-{
- if (m_status != NO_ERROR) {
- return m_status;
- }
-
- ssize_t amt;
-
- amt = write_padding_for(m_pos);
- if (amt != 0) {
- return amt;
- }
-
- app_header_v1 header;
- ssize_t nameLen;
-
- nameLen = packageName.length();
-
- header.type = tolel(BACKUP_HEADER_APP_V1);
- header.packageLen = tolel(nameLen);
- header.cookie = cookie;
-
- amt = write(m_fd, &header, sizeof(app_header_v1));
- if (amt != sizeof(app_header_v1)) {
- m_status = errno;
- return m_status;
- }
- m_pos += amt;
-
- amt = write(m_fd, packageName.string(), nameLen+1);
- if (amt != nameLen+1) {
- m_status = errno;
- return m_status;
- }
- m_pos += amt;
-
- return NO_ERROR;
-}
-
-status_t
BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
{
if (m_status != NO_ERROR) {
@@ -139,10 +99,20 @@
return amt;
}
+ String8 k;
+ if (m_keyPrefix.length() > 0) {
+ k = m_keyPrefix;
+ k += ":";
+ k += key;
+ } else {
+ k = key;
+ }
+ LOGD("m_keyPrefix=%s key=%s k=%s", m_keyPrefix.string(), key.string(), k.string());
+
entity_header_v1 header;
ssize_t keyLen;
- keyLen = key.length();
+ keyLen = k.length();
header.type = tolel(BACKUP_HEADER_ENTITY_V1);
header.keyLen = tolel(keyLen);
@@ -155,7 +125,7 @@
}
m_pos += amt;
- amt = write(m_fd, key.string(), keyLen+1);
+ amt = write(m_fd, k.string(), keyLen+1);
if (amt != keyLen+1) {
m_status = errno;
return m_status;
@@ -188,40 +158,16 @@
return NO_ERROR;
}
-status_t
-BackupDataWriter::WriteAppFooter(int cookie)
+void
+BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
{
- if (m_status != NO_ERROR) {
- return m_status;
- }
-
- ssize_t amt;
-
- amt = write_padding_for(m_pos);
- if (amt != 0) {
- return amt;
- }
-
- app_footer_v1 footer;
- ssize_t nameLen;
-
- footer.type = tolel(BACKUP_FOOTER_APP_V1);
- footer.entityCount = tolel(m_entityCount);
- footer.cookie = cookie;
-
- amt = write(m_fd, &footer, sizeof(app_footer_v1));
- if (amt != sizeof(app_footer_v1)) {
- m_status = errno;
- return m_status;
- }
- m_pos += amt;
-
- return NO_ERROR;
+ m_keyPrefix = keyPrefix;
}
BackupDataReader::BackupDataReader(int fd)
:m_fd(fd),
+ m_done(false),
m_status(NO_ERROR),
m_pos(0),
m_entityCount(0)
@@ -260,32 +206,31 @@
} while(0)
status_t
-BackupDataReader::ReadNextHeader(int* type)
+BackupDataReader::ReadNextHeader(bool* done, int* type)
{
+ *done = m_done;
if (m_status != NO_ERROR) {
return m_status;
}
int amt;
- SKIP_PADDING();
+ // No error checking here, in case we're at the end of the stream. Just let read() fail.
+ skip_padding();
amt = read(m_fd, &m_header, sizeof(m_header));
+ *done = m_done = (amt == 0);
CHECK_SIZE(amt, sizeof(m_header));
+ m_pos += sizeof(m_header);
+ if (type) {
+ *type = m_header.type;
+ }
// validate and fix up the fields.
m_header.type = fromlel(m_header.type);
switch (m_header.type)
{
- case BACKUP_HEADER_APP_V1:
- m_header.app.packageLen = fromlel(m_header.app.packageLen);
- if (m_header.app.packageLen < 0) {
- LOGD("App header at %d has packageLen<0: 0x%08x\n", (int)m_pos,
- (int)m_header.app.packageLen);
- m_status = EINVAL;
- }
- m_header.app.cookie = m_header.app.cookie;
- break;
case BACKUP_HEADER_ENTITY_V1:
+ {
m_header.entity.keyLen = fromlel(m_header.entity.keyLen);
if (m_header.entity.keyLen <= 0) {
LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos,
@@ -294,52 +239,31 @@
}
m_header.entity.dataSize = fromlel(m_header.entity.dataSize);
m_entityCount++;
- break;
- case BACKUP_FOOTER_APP_V1:
- m_header.footer.entityCount = fromlel(m_header.footer.entityCount);
- if (m_header.footer.entityCount < 0) {
- LOGD("Entity header at %d has entityCount<0: 0x%08x\n", (int)m_pos,
- (int)m_header.footer.entityCount);
- m_status = EINVAL;
+
+ // read the rest of the header (filename)
+ size_t size = m_header.entity.keyLen;
+ char* buf = m_key.lockBuffer(size);
+ if (buf == NULL) {
+ m_status = ENOMEM;
+ return m_status;
}
- m_header.footer.cookie = m_header.footer.cookie;
+ int amt = read(m_fd, buf, size+1);
+ CHECK_SIZE(amt, (int)size+1);
+ m_key.unlockBuffer(size);
+ m_pos += size+1;
+ SKIP_PADDING();
+ m_dataEndPos = m_pos + m_header.entity.dataSize;
+
break;
+ }
default:
LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
m_status = EINVAL;
}
- m_pos += sizeof(m_header);
- if (type) {
- *type = m_header.type;
- }
return m_status;
}
-status_t
-BackupDataReader::ReadAppHeader(String8* packageName, int* cookie)
-{
- if (m_status != NO_ERROR) {
- return m_status;
- }
- if (m_header.type != BACKUP_HEADER_APP_V1) {
- return EINVAL;
- }
- size_t size = m_header.app.packageLen;
- char* buf = packageName->lockBuffer(size);
- if (buf == NULL) {
- packageName->unlockBuffer();
- m_status = ENOMEM;
- return m_status;
- }
- int amt = read(m_fd, buf, size+1);
- CHECK_SIZE(amt, (int)size+1);
- packageName->unlockBuffer(size);
- m_pos += size+1;
- *cookie = m_header.app.cookie;
- return NO_ERROR;
-}
-
bool
BackupDataReader::HasEntities()
{
@@ -355,19 +279,8 @@
if (m_header.type != BACKUP_HEADER_ENTITY_V1) {
return EINVAL;
}
- size_t size = m_header.entity.keyLen;
- char* buf = key->lockBuffer(size);
- if (key == NULL) {
- key->unlockBuffer();
- m_status = ENOMEM;
- return m_status;
- }
- int amt = read(m_fd, buf, size+1);
- CHECK_SIZE(amt, (int)size+1);
- key->unlockBuffer(size);
- m_pos += size+1;
+ *key = m_key;
*dataSize = m_header.entity.dataSize;
- SKIP_PADDING();
return NO_ERROR;
}
@@ -381,42 +294,36 @@
return EINVAL;
}
if (m_header.entity.dataSize > 0) {
- int pos = lseek(m_fd, m_header.entity.dataSize, SEEK_CUR);
+ int pos = lseek(m_fd, m_dataEndPos, SEEK_SET);
return pos == -1 ? (int)errno : (int)NO_ERROR;
} else {
return NO_ERROR;
}
}
-status_t
+ssize_t
BackupDataReader::ReadEntityData(void* data, size_t size)
{
if (m_status != NO_ERROR) {
- return m_status;
+ return -1;
}
+ int remaining = m_dataEndPos - m_pos;
+ //LOGD("ReadEntityData size=%d m_pos=0x%x m_dataEndPos=0x%x remaining=%d\n",
+ // size, m_pos, m_dataEndPos, remaining);
+ if (remaining <= 0) {
+ return 0;
+ }
+ if (((int)size) > remaining) {
+ size = remaining;
+ }
+ //LOGD(" reading %d bytes", size);
int amt = read(m_fd, data, size);
- CHECK_SIZE(amt, (int)size);
- m_pos += size;
- return NO_ERROR;
-}
-
-status_t
-BackupDataReader::ReadAppFooter(int* cookie)
-{
- if (m_status != NO_ERROR) {
- return m_status;
+ if (amt < 0) {
+ m_status = errno;
+ return -1;
}
- if (m_header.type != BACKUP_FOOTER_APP_V1) {
- return EINVAL;
- }
- if (m_header.footer.entityCount != m_entityCount) {
- LOGD("entity count mismatch actual=%d expected=%d", m_entityCount,
- m_header.footer.entityCount);
- m_status = EINVAL;
- return m_status;
- }
- *cookie = m_header.footer.cookie;
- return NO_ERROR;
+ m_pos += amt;
+ return amt;
}
status_t
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index 4c3e37d..99a4abc 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -41,33 +41,39 @@
#define MAGIC0 0x70616e53 // Snap
#define MAGIC1 0x656c6946 // File
+/*
+ * File entity data format (v1):
+ *
+ * - 4-byte version number of the metadata, little endian (0x00000001 for v1)
+ * - 12 bytes of metadata
+ * - the file data itself
+ *
+ * i.e. a 16-byte metadata header followed by the raw file data. If the
+ * restore code does not recognize the metadata version, it can still
+ * interpret the file data itself correctly.
+ *
+ * file_metadata_v1:
+ *
+ * - 4 byte version number === 0x00000001 (little endian)
+ * - 4-byte access mode (little-endian)
+ * - undefined (8 bytes)
+ */
+
+struct file_metadata_v1 {
+ int version;
+ int mode;
+ int undefined_1;
+ int undefined_2;
+};
+
+const static int CURRENT_METADATA_VERSION = 1;
+
#if 1 // TEST_BACKUP_HELPERS
#define LOGP(f, x...) printf(f "\n", x)
#else
#define LOGP(x...) LOGD(x)
#endif
-struct SnapshotHeader {
- int magic0;
- int fileCount;
- int magic1;
- int totalSize;
-};
-
-struct FileState {
- int modTime_sec;
- int modTime_nsec;
- int size;
- int crc32;
- int nameLen;
-};
-
-struct FileRec {
- char const* file; // this object does not own this string
- bool deleted;
- FileState s;
-};
-
const static int ROUND_UP[4] = { 0, 3, 2, 1 };
static inline int
@@ -202,29 +208,48 @@
}
static int
-write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
+write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
char const* realFilename)
{
- LOGP("write_update_file %s (%s)\n", realFilename, key.string());
+ LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);
const int bufsize = 4*1024;
int err;
int amt;
int fileSize;
int bytesLeft;
+ file_metadata_v1 metadata;
char* buf = (char*)malloc(bufsize);
int crc = crc32(0L, Z_NULL, 0);
- bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
+ fileSize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
+ if (sizeof(metadata) != 16) {
+ LOGE("ERROR: metadata block is the wrong size!");
+ }
+
+ bytesLeft = fileSize + sizeof(metadata);
err = dataStream->WriteEntityHeader(key, bytesLeft);
if (err != 0) {
+ free(buf);
return err;
}
+ // store the file metadata first
+ metadata.version = tolel(CURRENT_METADATA_VERSION);
+ metadata.mode = tolel(mode);
+ metadata.undefined_1 = metadata.undefined_2 = 0;
+ err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
+ if (err != 0) {
+ free(buf);
+ return err;
+ }
+ bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
+
+ // now store the file content
while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
bytesLeft -= amt;
if (bytesLeft < 0) {
@@ -232,6 +257,7 @@
}
err = dataStream->WriteEntityData(buf, amt);
if (err != 0) {
+ free(buf);
return err;
}
}
@@ -245,6 +271,7 @@
bytesLeft -= amt;
err = dataStream->WriteEntityData(buf, amt);
if (err != 0) {
+ free(buf);
return err;
}
}
@@ -254,7 +281,6 @@
}
free(buf);
-
return NO_ERROR;
}
@@ -262,11 +288,19 @@
write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
{
int err;
+ struct stat st;
+
+ err = stat(realFilename, &st);
+ if (err < 0) {
+ return errno;
+ }
+
int fd = open(realFilename, O_RDONLY);
if (fd == -1) {
return errno;
}
- err = write_update_file(dataStream, fd, key, realFilename);
+
+ err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
close(fd);
return err;
}
@@ -287,7 +321,6 @@
}
free(buf);
-
return crc;
}
@@ -310,7 +343,8 @@
for (int i=0; i<fileCount; i++) {
String8 key(keys[i]);
FileRec r;
- char const* file = r.file = files[i];
+ char const* file = files[i];
+ r.file = file;
struct stat st;
err = stat(file, &st);
@@ -322,6 +356,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.
@@ -351,31 +386,31 @@
}
else if (cmp > 0) {
// file added
- LOGP("file added: %s", g.file);
- write_update_file(dataStream, q, g.file);
+ LOGP("file added: %s", g.file.string());
+ write_update_file(dataStream, q, g.file.string());
m++;
}
else {
// both files exist, check them
const FileState& f = oldSnapshot.valueAt(n);
- int fd = open(g.file, O_RDONLY);
+ int fd = open(g.file.string(), O_RDONLY);
if (fd < 0) {
// We can't open the file. Don't report it as a delete either. Let the
// server keep the old version. Maybe they'll be able to deal with it
// on restore.
- LOGP("Unable to open file %s - skipping", g.file);
+ LOGP("Unable to open file %s - skipping", g.file.string());
} else {
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) {
- write_update_file(dataStream, fd, p, g.file);
+ || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
+ write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
}
close(fd);
@@ -395,7 +430,7 @@
while (m<fileCount) {
const String8& q = newSnapshot.keyAt(m);
FileRec& g = newSnapshot.editValueAt(m);
- write_update_file(dataStream, q, g.file);
+ write_update_file(dataStream, q, g.file.string());
m++;
}
@@ -404,6 +439,105 @@
return 0;
}
+#define RESTORE_BUF_SIZE (8*1024)
+
+RestoreHelperBase::RestoreHelperBase()
+{
+ m_buf = malloc(RESTORE_BUF_SIZE);
+ m_loggedUnknownMetadata = false;
+}
+
+RestoreHelperBase::~RestoreHelperBase()
+{
+ free(m_buf);
+}
+
+status_t
+RestoreHelperBase::WriteFile(const String8& filename, BackupDataReader* in)
+{
+ ssize_t err;
+ size_t dataSize;
+ String8 key;
+ int fd;
+ void* buf = m_buf;
+ ssize_t amt;
+ int mode;
+ int crc;
+ struct stat st;
+ FileRec r;
+
+ err = in->ReadEntityHeader(&key, &dataSize);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ // Get the metadata block off the head of the file entity and use that to
+ // set up the output file
+ file_metadata_v1 metadata;
+ amt = in->ReadEntityData(&metadata, sizeof(metadata));
+ if (amt != sizeof(metadata)) {
+ LOGW("Could not read metadata for %s -- %ld / %s", filename.string(),
+ (long)amt, strerror(errno));
+ return EIO;
+ }
+ metadata.version = fromlel(metadata.version);
+ metadata.mode = fromlel(metadata.mode);
+ if (metadata.version > CURRENT_METADATA_VERSION) {
+ if (!m_loggedUnknownMetadata) {
+ m_loggedUnknownMetadata = true;
+ LOGW("Restoring file with unsupported metadata version %d (currently %d)",
+ metadata.version, CURRENT_METADATA_VERSION);
+ }
+ }
+ mode = metadata.mode;
+
+ // Write the file and compute the crc
+ crc = crc32(0L, Z_NULL, 0);
+ fd = open(filename.string(), O_CREAT|O_RDWR|O_TRUNC, mode);
+ if (fd == -1) {
+ LOGW("Could not open file %s -- %s", filename.string(), strerror(errno));
+ return errno;
+ }
+
+ while ((amt = in->ReadEntityData(buf, RESTORE_BUF_SIZE)) > 0) {
+ err = write(fd, buf, amt);
+ if (err != amt) {
+ close(fd);
+ LOGW("Error '%s' writing '%s'", strerror(errno), filename.string());
+ return errno;
+ }
+ crc = crc32(crc, (Bytef*)buf, amt);
+ }
+
+ close(fd);
+
+ // Record for the snapshot
+ err = stat(filename.string(), &st);
+ if (err != 0) {
+ LOGW("Error stating file that we just created %s", filename.string());
+ return errno;
+ }
+
+ r.file = filename;
+ r.deleted = false;
+ 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;
+
+ m_files.add(key, r);
+
+ return NO_ERROR;
+}
+
+status_t
+RestoreHelperBase::WriteSnapshot(int fd)
+{
+ return write_snapshot_file(fd, m_files);;
+}
+
#if TEST_BACKUP_HELPERS
#define SCRATCH_DIR "/data/backup_helper_test/"
@@ -476,6 +610,7 @@
}
}
+ free(contents);
return contentsMatch && sizesMatch ? 0 : 1;
}
@@ -560,10 +695,10 @@
FileState states[4];
FileRec r;
r.deleted = false;
- r.file = NULL;
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;
@@ -573,6 +708,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;
@@ -582,6 +718,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;
@@ -591,6 +728,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;
@@ -610,35 +748,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));
@@ -672,14 +813,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;
}
}
@@ -689,41 +830,27 @@
// hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data
const unsigned char DATA_GOLDEN_FILE[] = {
- 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00,
- 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70,
- 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70,
0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00,
0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69,
- 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31,
- 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
+ 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61,
+ 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
- 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00,
- 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
- 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
- 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
- 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33,
- 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
- 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
- 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc,
+ 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc,
0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64,
0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f,
- 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31,
- 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa,
- 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
- 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61,
+ 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61,
0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74,
0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64,
- 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc,
- 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00,
- 0x99, 0x99, 0x77, 0x77
+ 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00
+
};
const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE);
@@ -733,12 +860,6 @@
int err;
String8 text(str);
- err = writer.WriteAppHeader(text, 0xaabbccdd);
- if (err != 0) {
- fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err));
- return err;
- }
-
err = writer.WriteEntityHeader(text, text.length()+1);
if (err != 0) {
fprintf(stderr, "WriteEntityHeader failed with %s\n", strerror(err));
@@ -779,8 +900,6 @@
err |= test_write_header_and_entity(writer, "padded_to_2__");
err |= test_write_header_and_entity(writer, "padded_to1");
- writer.WriteAppFooter(0x77779999);
-
close(fd);
err = compare_file(filename, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE);
@@ -800,70 +919,61 @@
String8 string;
int cookie = 0x11111111;
size_t actualSize;
+ bool done;
+ int type;
+ ssize_t nRead;
// printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
- err = reader.ReadNextHeader();
+ err = reader.ReadNextHeader(&done, &type);
+ if (done) {
+ fprintf(stderr, "should not be done yet\n");
+ goto finished;
+ }
if (err != 0) {
fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
- goto done;
+ goto finished;
}
-
- err = reader.ReadAppHeader(&string, &cookie);
- if (err != 0) {
- fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err));
- goto done;
- }
- if (string != str) {
- fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string());
+ if (type != BACKUP_HEADER_ENTITY_V1) {
err = EINVAL;
- goto done;
- }
- if (cookie != (int)0xaabbccdd) {
- fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie);
- err = EINVAL;
- goto done;
- }
-
- err = reader.ReadNextHeader();
- if (err != 0) {
- fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err));
- goto done;
+ fprintf(stderr, "type=0x%08x expected 0x%08x\n", type, BACKUP_HEADER_ENTITY_V1);
}
err = reader.ReadEntityHeader(&string, &actualSize);
if (err != 0) {
fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err));
- goto done;
+ goto finished;
}
if (string != str) {
fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string());
err = EINVAL;
- goto done;
+ goto finished;
}
if ((int)actualSize != bufSize) {
fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
actualSize);
err = EINVAL;
- goto done;
+ 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 done;
+ goto finished;
}
if (0 != memcmp(buf, str, bufSize)) {
fprintf(stderr, "ReadEntityData expected '%s' but got something starting with "
- "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]);
+ "%02x %02x %02x %02x '%c%c%c%c'\n", str, buf[0], buf[1], buf[2], buf[3],
+ buf[0], buf[1], buf[2], buf[3]);
err = EINVAL;
- goto done;
+ goto finished;
}
// The next read will confirm whether it got the right amount of data.
-done:
+finished:
if (err != NO_ERROR) {
fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err));
}
@@ -923,23 +1033,6 @@
if (err == NO_ERROR) {
err = test_read_header_and_entity(reader, "padded_to1");
}
-
- if (err == NO_ERROR) {
- err = reader.ReadNextHeader();
- if (err != 0) {
- fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err));
- }
-
- if (err == NO_ERROR) {
- int cookie;
- err |= reader.ReadAppFooter(&cookie);
- if (cookie != 0x77779999) {
- fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n",
- 0x77779999, cookie);
- err = EINVAL;
- }
- }
- }
}
close(fd);
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 3d12dca..e4f9f0f 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -544,7 +544,7 @@
return mEventCode;
}
-const int32_t ResXMLParser::getCommentID() const
+int32_t ResXMLParser::getCommentID() const
{
return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
}
@@ -555,12 +555,12 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const uint32_t ResXMLParser::getLineNumber() const
+uint32_t ResXMLParser::getLineNumber() const
{
return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1;
}
-const int32_t ResXMLParser::getTextID() const
+int32_t ResXMLParser::getTextID() const
{
if (mEventCode == TEXT) {
return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index);
@@ -583,7 +583,7 @@
return BAD_TYPE;
}
-const int32_t ResXMLParser::getNamespacePrefixID() const
+int32_t ResXMLParser::getNamespacePrefixID() const
{
if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index);
@@ -598,7 +598,7 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const int32_t ResXMLParser::getNamespaceUriID() const
+int32_t ResXMLParser::getNamespaceUriID() const
{
if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index);
@@ -613,7 +613,7 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const int32_t ResXMLParser::getElementNamespaceID() const
+int32_t ResXMLParser::getElementNamespaceID() const
{
if (mEventCode == START_TAG) {
return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index);
@@ -630,7 +630,7 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const int32_t ResXMLParser::getElementNameID() const
+int32_t ResXMLParser::getElementNameID() const
{
if (mEventCode == START_TAG) {
return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index);
@@ -655,7 +655,7 @@
return 0;
}
-const int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
+int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
{
if (mEventCode == START_TAG) {
const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -678,7 +678,7 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const int32_t ResXMLParser::getAttributeNameID(size_t idx) const
+int32_t ResXMLParser::getAttributeNameID(size_t idx) const
{
if (mEventCode == START_TAG) {
const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -701,7 +701,7 @@
return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
}
-const uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
+uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
{
int32_t id = getAttributeNameID(idx);
if (id >= 0 && (size_t)id < mTree.mNumResIds) {
@@ -710,7 +710,7 @@
return 0;
}
-const int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
+int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
{
if (mEventCode == START_TAG) {
const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -3830,9 +3830,45 @@
#define CHAR16_ARRAY_EQ(constant, var, len) \
((len == (sizeof(constant)/sizeof(constant[0]))) && (0 == memcmp((var), (constant), (len))))
-void ResTable::print() const
+void print_complex(uint32_t complex, bool isFraction)
{
- printf("mError=0x%x (%s)\n", mError, strerror(mError));
+ const float MANTISSA_MULT =
+ 1.0f / (1<<Res_value::COMPLEX_MANTISSA_SHIFT);
+ const float RADIX_MULTS[] = {
+ 1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
+ 1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
+ };
+
+ float value = (complex&(Res_value::COMPLEX_MANTISSA_MASK
+ <<Res_value::COMPLEX_MANTISSA_SHIFT))
+ * RADIX_MULTS[(complex>>Res_value::COMPLEX_RADIX_SHIFT)
+ & Res_value::COMPLEX_RADIX_MASK];
+ printf("%f", value);
+
+ if (isFraction) {
+ switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {
+ case Res_value::COMPLEX_UNIT_PX: printf("px"); break;
+ case Res_value::COMPLEX_UNIT_DIP: printf("dp"); break;
+ case Res_value::COMPLEX_UNIT_SP: printf("sp"); break;
+ case Res_value::COMPLEX_UNIT_PT: printf("pt"); break;
+ case Res_value::COMPLEX_UNIT_IN: printf("in"); break;
+ case Res_value::COMPLEX_UNIT_MM: printf("mm"); break;
+ default: printf(" (unknown unit)"); break;
+ }
+ } else {
+ switch ((complex>>Res_value::COMPLEX_UNIT_SHIFT)&Res_value::COMPLEX_UNIT_MASK) {
+ case Res_value::COMPLEX_UNIT_FRACTION: printf("%%"); break;
+ case Res_value::COMPLEX_UNIT_FRACTION_PARENT: printf("%%p"); break;
+ default: printf(" (unknown unit)"); break;
+ }
+ }
+}
+
+void ResTable::print(bool inclValues) const
+{
+ if (mError != 0) {
+ printf("mError=0x%x (%s)\n", mError, strerror(mError));
+ }
#if 0
printf("mParams=%c%c-%c%c,\n",
mParams.language[0], mParams.language[1],
@@ -3947,6 +3983,8 @@
(void*)(entriesStart + thisOffset));
continue;
}
+
+ const Res_value* value = NULL;
if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) {
printf("<bag>");
} else {
@@ -3962,7 +4000,7 @@
continue;
}
- const Res_value* value = (const Res_value*)
+ value = (const Res_value*)
(((const uint8_t*)ent) + esize);
printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)",
(int)value->dataType, (int)dtohl(value->data),
@@ -3973,6 +4011,49 @@
printf(" (PUBLIC)");
}
printf("\n");
+
+ if (inclValues) {
+ if (value != NULL) {
+ printf(" ");
+ if (value->dataType == Res_value::TYPE_NULL) {
+ printf("(null)\n");
+ } else if (value->dataType == Res_value::TYPE_REFERENCE) {
+ printf("(reference) 0x%08x\n", value->data);
+ } else if (value->dataType == Res_value::TYPE_ATTRIBUTE) {
+ printf("(attribute) 0x%08x\n", value->data);
+ } else if (value->dataType == Res_value::TYPE_STRING) {
+ size_t len;
+ const char16_t* str = pkg->header->values.stringAt(
+ value->data, &len);
+ if (str == NULL) {
+ printf("(string) null\n");
+ } else {
+ printf("(string) \"%s\"\n",
+ String8(str, len).string());
+ }
+ } else if (value->dataType == Res_value::TYPE_FLOAT) {
+ printf("(float) %g\n", *(const float*)&value->data);
+ } else if (value->dataType == Res_value::TYPE_DIMENSION) {
+ printf("(dimension) ");
+ print_complex(value->data, false);
+ printf("\n");
+ } else if (value->dataType == Res_value::TYPE_FRACTION) {
+ printf("(fraction) ");
+ print_complex(value->data, true);
+ printf("\n");
+ } else if (value->dataType >= Res_value::TYPE_FIRST_COLOR_INT
+ || value->dataType <= Res_value::TYPE_LAST_COLOR_INT) {
+ printf("(color) #%08x\n", value->data);
+ } else if (value->dataType == Res_value::TYPE_INT_BOOLEAN) {
+ printf("(boolean) %s\n", value->data ? "true" : "false");
+ } else if (value->dataType >= Res_value::TYPE_FIRST_INT
+ || value->dataType <= Res_value::TYPE_LAST_INT) {
+ printf("(int) 0x%08x or %d\n", value->data, value->data);
+ } else {
+ printf("(unknown type)\n");
+ }
+ }
+ }
}
}
}
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index b6f534b..14a910c 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -900,7 +900,7 @@
memcpy(textureObject->crop_rect, params, 4*sizeof(GLint));
break;
default:
- ogles_error(c, GL_INVALID_ENUM);
+ texParameterx(target, pname, GLfixed(params[0]), c);
return;
}
}
@@ -919,6 +919,13 @@
texParameterx(target, pname, param, c);
}
+void glTexParameteri(
+ GLenum target, GLenum pname, GLint param)
+{
+ ogles_context_t* c = ogles_context_t::get();
+ texParameterx(target, pname, GLfixed(param), c);
+}
+
// ----------------------------------------------------------------------------
#if 0
#pragma mark -
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
index 46958d3..e193483 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -5,7 +5,7 @@
LOCAL_SRC_FILES:= app-linux.c demo.c.arm
LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
LOCAL_MODULE:= angeles
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
@@ -13,5 +13,5 @@
LOCAL_SRC_FILES:= gpustate.c
LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM
LOCAL_MODULE:= gpustate
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index a448f0d..31b7d9a 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -12,6 +12,6 @@
LOCAL_MODULE:= test-opengl-filter
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 26836c1..8b46cd7 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -12,6 +12,6 @@
LOCAL_MODULE:= test-opengl-finish
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index a8c6220..8d5f56d 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -12,6 +12,6 @@
LOCAL_MODULE:= test-opengl-textures
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index 5cd1f04..76fd8dd 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -12,6 +12,6 @@
LOCAL_MODULE:= test-opengl-tritex
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 011a6ed..9bff0b2 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -4,14 +4,31 @@
rm -rf out generated
mkdir out
+
+# Create dummy Java files for Android APIs that are used by the code we generate.
+# This allows us to test the generated code without building the rest of Android.
+
mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/app
mkdir -p out/android/graphics
mkdir -p out/android/opengl
+mkdir -p out/android/content
+mkdir -p out/android/content/pm
+mkdir -p out/android/os
+mkdir -p out/android/util
echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
+echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
+# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
+echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
+echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;}; }" > out/android/os/Build.java
+echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
+echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
+
GLFILE=out/javax/microedition/khronos/opengles/GL.java
cp stubs/jsr239/GLHeader.java-if $GLFILE
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 4896acb..4494643 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -44,9 +44,11 @@
static jclass UOEClass;
static jclass IAEClass;
static jclass AIOOBEClass;
+static jclass G11ImplClass;
static jmethodID getBasePointerID;
static jmethodID getBaseArrayID;
static jmethodID getBaseArrayOffsetID;
+static jmethodID allowIndirectBuffersID;
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
@@ -62,13 +64,17 @@
jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+ jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
+ G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
"getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
"getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
-
+ allowIndirectBuffersID = _env->GetStaticMethodID(g11impClassLocal,
+ "allowIndirectBuffers", "(Ljava/lang/String;)Z");
positionID = _env->GetFieldID(bufferClass, "position", "I");
limitID = _env->GetFieldID(bufferClass, "limit", "I");
elementSizeShiftID =
@@ -118,6 +124,9 @@
*array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
getBaseArrayID, buffer);
+ if (*array == NULL) {
+ return (void*) NULL;
+ }
offset = _env->CallStaticIntMethod(nioAccessClass,
getBaseArrayOffsetID, buffer);
data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
@@ -132,17 +141,43 @@
commit ? 0 : JNI_ABORT);
}
+extern "C" {
+extern char* __progname;
+}
+
+static bool
+allowIndirectBuffers(JNIEnv *_env) {
+ static jint sIndirectBufferCompatability;
+ if (sIndirectBufferCompatability == 0) {
+ jobject appName = _env->NewStringUTF(::__progname);
+ sIndirectBufferCompatability = _env->CallStaticBooleanMethod(G11ImplClass, allowIndirectBuffersID, appName) ? 2 : 1;
+ }
+ return sIndirectBufferCompatability == 2;
+}
+
static void *
getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
- char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+ if (!buffer) {
+ return NULL;
+ }
+ void* buf = _env->GetDirectBufferAddress(buffer);
if (buf) {
jint position = _env->GetIntField(buffer, positionID);
jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
- buf += position << elementSizeShift;
+ buf = ((char*) buf) + (position << elementSizeShift);
} else {
- _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ if (allowIndirectBuffers(_env)) {
+ jarray array = 0;
+ jint remaining;
+ buf = getPointer(_env, buffer, &array, &remaining);
+ if (array) {
+ releasePointer(_env, array, buf, 0);
+ }
+ } else {
+ _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+ }
}
- return (void*) buf;
+ return buf;
}
static int
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index db3a41c..fe60c5d 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -18,6 +18,12 @@
package com.google.android.gles_jni;
+import android.app.ActivityThread;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Build;
+import android.util.Log;
+
import java.nio.Buffer;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL10Ext;
@@ -42,7 +48,28 @@
public GLImpl() {
}
- public void glGetPointerv(int pname, java.nio.Buffer[] params) {
- throw new UnsupportedOperationException("glGetPointerv");
- }
+ public void glGetPointerv(int pname, java.nio.Buffer[] params) {
+ throw new UnsupportedOperationException("glGetPointerv");
+ }
+
+ private static boolean allowIndirectBuffers(String appName) {
+ boolean result = false;
+ int version = 0;
+ IPackageManager pm = ActivityThread.getPackageManager();
+ try {
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+ if (applicationInfo != null) {
+ version = applicationInfo.targetSdkVersion;
+ }
+ } catch (android.os.RemoteException e) {
+ // ignore
+ }
+ Log.e("OpenGLES", String.format(
+ "Application %s (SDK target %d) called a GL11 Pointer method with an indirect Buffer.",
+ appName, version));
+ if (version <= Build.VERSION_CODES.CUPCAKE) {
+ result = true;
+ }
+ return result;
+ }