Merge "goldfish: update to 331578d04"
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..fef7f95
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(BUILD_QEMU_IMAGES),true)
+ subdir_makefiles=$(call first-makefiles-under,$(LOCAL_PATH))
+ $(foreach mk,$(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
+endif
diff --git a/audio/Android.mk b/audio/Android.mk
index 4343a4a..b60ff14 100644
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -17,6 +17,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := audio.primary.goldfish
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
@@ -38,6 +39,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := audio.primary.goldfish_legacy
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 2498e51..781c18f 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -16,7 +16,9 @@
#define LOG_TAG "audio_hw_generic"
+#include <assert.h>
#include <errno.h>
+#include <inttypes.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
@@ -286,7 +288,7 @@
pthread_mutex_lock(&out->lock);
dprintf(fd, "\tout_dump:\n"
"\t\tsample rate: %u\n"
- "\t\tbuffer size: %u\n"
+ "\t\tbuffer size: %zu\n"
"\t\tchannel mask: %08x\n"
"\t\tformat: %d\n"
"\t\tdevice: %08x\n"
@@ -476,7 +478,8 @@
// The device will reuse the same output stream leading to periods of
// underrun.
if (*position > out->frames_written) {
- ALOGW("Not supplying enough data to HAL, expected position %lld , only wrote %lld",
+ ALOGW("Not supplying enough data to HAL, expected position %" PRIu64 " , only wrote "
+ "%" PRIu64,
*position, out->frames_written);
*position = out->frames_written;
@@ -547,7 +550,7 @@
}
if (frames_written < frames) {
- ALOGW("Hardware backing HAL too slow, could only write %d of %zu frames", frames_written, frames);
+ ALOGW("Hardware backing HAL too slow, could only write %zu of %zu frames", frames_written, frames);
}
/* Always consume all bytes */
@@ -795,7 +798,7 @@
pthread_mutex_lock(&in->lock);
dprintf(fd, "\tin_dump:\n"
"\t\tsample rate: %u\n"
- "\t\tbuffer size: %u\n"
+ "\t\tbuffer size: %zu\n"
"\t\tchannel mask: %08x\n"
"\t\tformat: %d\n"
"\t\tdevice: %08x\n"
@@ -1027,8 +1030,9 @@
}
const int64_t frames_available = current_position - in->standby_position - in->standby_frames_read;
+ assert(frames_available >= 0);
- const size_t frames_wait = (frames_available > frames) ? 0 : frames - frames_available;
+ const size_t frames_wait = ((uint64_t)frames_available > frames) ? 0 : frames - frames_available;
int64_t sleep_time_us = frames_wait * 1000000LL /
in_get_sample_rate(&stream->common);
diff --git a/audio/audio_hw_legacy.c b/audio/audio_hw_legacy.c
index 14d82da..5f167b5 100644
--- a/audio/audio_hw_legacy.c
+++ b/audio/audio_hw_legacy.c
@@ -106,7 +106,7 @@
dprintf(fd, "\tout_dump:\n"
"\t\tsample rate: %u\n"
- "\t\tbuffer size: %u\n"
+ "\t\tbuffer size: %zu\n"
"\t\tchannel mask: %08x\n"
"\t\tformat: %d\n"
"\t\tdevice: %08x\n"
@@ -262,7 +262,7 @@
dprintf(fd, "\tin_dump:\n"
"\t\tsample rate: %u\n"
- "\t\tbuffer size: %u\n"
+ "\t\tbuffer size: %zu\n"
"\t\tchannel mask: %08x\n"
"\t\tformat: %d\n"
"\t\tdevice: %08x\n"
diff --git a/camera/Android.mk b/camera/Android.mk
index bd33131..781e94c 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+ifneq ($(filter generic_x86 generic_x86_64 generic generic_arm64 generic_mips generic_mips64, $(TARGET_DEVICE)),)
LOCAL_PATH := $(call my-dir)
@@ -32,8 +33,9 @@
libcamera_client \
libui \
libdl \
- libjpeg \
- libcamera_metadata
+ libjpeg \
+ libcamera_metadata \
+ libhardware
emulator_camera_static_libraries := \
libyuv_static
@@ -77,6 +79,7 @@
# Emulated camera - goldfish / vbox_x86 build###################################
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := ${emulator_camera_module_relative_path}
LOCAL_CFLAGS := ${emulator_camera_cflags}
LOCAL_CLANG_CFLAGS += ${emulator_camera_clang_flags}
@@ -100,6 +103,7 @@
include ${CLEAR_VARS}
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := ${emulator_camera_module_relative_path}
LOCAL_CFLAGS := ${emulator_camera_cflags}
LOCAL_CLANG_CFLAGS += ${emulator_camera_clang_flags}
@@ -116,3 +120,4 @@
# Build all subdirectories #####################################################
include $(call all-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/camera/CallbackNotifier.cpp b/camera/CallbackNotifier.cpp
index 18c5eec..865a34e 100755
--- a/camera/CallbackNotifier.cpp
+++ b/camera/CallbackNotifier.cpp
@@ -239,7 +239,7 @@
// format it expects and the preview callback (or data callback) below
// gets the format that is configured in camera parameters.
const size_t frameSize = camera_dev->getVideoFrameBufferSize();
- camera_memory_t* cam_buff = mGetMemoryCB(-1, frameSize, 1, NULL);
+ camera_memory_t* cam_buff = mGetMemoryCB(-1, frameSize, 1, mCBOpaque);
if (NULL != cam_buff && NULL != cam_buff->data) {
camera_dev->getCurrentFrame(cam_buff->data, V4L2_PIX_FMT_YUV420);
mDataCBTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
@@ -252,7 +252,7 @@
if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
camera_memory_t* cam_buff =
- mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, NULL);
+ mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
if (NULL != cam_buff && NULL != cam_buff->data) {
camera_dev->getCurrentFrame(cam_buff->data,
camera_dev->getOriginalPixelFormat());
@@ -313,7 +313,7 @@
mJpegQuality, exifData);
if (res == NO_ERROR) {
camera_memory_t* jpeg_buff =
- mGetMemoryCB(-1, compressor.getCompressedSize(), 1, NULL);
+ mGetMemoryCB(-1, compressor.getCompressedSize(), 1, mCBOpaque);
if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
compressor.getCompressedImage(jpeg_buff->data);
mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
diff --git a/camera/EmulatedCamera.cpp b/camera/EmulatedCamera.cpp
index bdab833..66cadee 100755
--- a/camera/EmulatedCamera.cpp
+++ b/camera/EmulatedCamera.cpp
@@ -26,7 +26,7 @@
#define LOG_NDEBUG 0
#define LOG_TAG "EmulatedCamera_Camera"
#include <cutils/log.h>
-#include <ui/Rect.h>
+ #include <stdio.h>
#include "EmulatedCamera.h"
//#include "EmulatedFakeCameraDevice.h"
#include "Converters.h"
@@ -386,12 +386,17 @@
status_t EmulatedCamera::storeMetaDataInBuffers(int enable)
{
/* Callback should return a negative errno. */
- return -mCallbackNotifier.storeMetaDataInBuffers(enable);
+ return mCallbackNotifier.storeMetaDataInBuffers(enable);
}
status_t EmulatedCamera::startRecording()
{
/* This callback should return a negative errno, hence all the negations */
+ if (!mPreviewWindow.isPreviewEnabled()) {
+ ALOGE("%s: start recording without preview enabled",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
int frameRate = mParameters.getPreviewFrameRate();
status_t res = mCallbackNotifier.enableVideoRecording(frameRate);
if (res != NO_ERROR) {
@@ -439,6 +444,7 @@
return -EINVAL;
}
}
+ ALOGD("go all the way to the end");
return NO_ERROR;
}
@@ -766,7 +772,8 @@
ALOGV("%s", __FUNCTION__);
/* TODO: Future enhancements. */
- return -EINVAL;
+ dprintf(fd, "dump camera unimplemented\n");
+ return 0;
}
status_t EmulatedCamera::getConfiguredPixelFormat(uint32_t* pixelFormat) const {
diff --git a/camera/EmulatedCameraFactory.h b/camera/EmulatedCameraFactory.h
index 879f925..923fe7e 100755
--- a/camera/EmulatedCameraFactory.h
+++ b/camera/EmulatedCameraFactory.h
@@ -121,13 +121,13 @@
/* Gets fake camera orientation. */
int getFakeCameraOrientation() {
/* TODO: Have a boot property that controls that. */
- return 90;
+ return 0;
}
/* Gets qemu camera orientation. */
int getQemuCameraOrientation() {
/* TODO: Have a boot property that controls that. */
- return 90;
+ return 0;
}
/* Gets number of emulated cameras.
diff --git a/camera/EmulatedFakeCamera.cpp b/camera/EmulatedFakeCamera.cpp
index 3db1a80..c85285d 100755
--- a/camera/EmulatedFakeCamera.cpp
+++ b/camera/EmulatedFakeCamera.cpp
@@ -60,6 +60,8 @@
mParameters.set(EmulatedCamera::ORIENTATION_KEY,
gEmulatedCameraFactory.getFakeCameraOrientation());
+ mParameters.set(CameraParameters::KEY_ROTATION,
+ gEmulatedCameraFactory.getFakeCameraOrientation());
res = EmulatedCamera::Initialize();
if (res != NO_ERROR) {
diff --git a/camera/EmulatedFakeCamera2.cpp b/camera/EmulatedFakeCamera2.cpp
index 7df6f52..9e959c0 100644
--- a/camera/EmulatedFakeCamera2.cpp
+++ b/camera/EmulatedFakeCamera2.cpp
@@ -27,9 +27,7 @@
#include "EmulatedFakeCamera2.h"
#include "EmulatedCameraFactory.h"
-#include <ui/Rect.h>
-#include <ui/GraphicBufferMapper.h>
-#include "gralloc_cb.h"
+#include "GrallocModule.h"
#define ERROR_CAMERA_NOT_PRESENT (-EPIPE)
@@ -51,7 +49,7 @@
const uint32_t EmulatedFakeCamera2::kAvailableRawSizes[2] = {
640, 480
- // Sensor::kResolution[0], Sensor::kResolution[1]
+ // mSensorWidth, mSensorHeight
};
const uint64_t EmulatedFakeCamera2::kAvailableRawMinDurations[1] = {
@@ -60,12 +58,12 @@
const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizesBack[4] = {
640, 480, 320, 240
- // Sensor::kResolution[0], Sensor::kResolution[1]
+ // mSensorWidth, mSensorHeight
};
const uint32_t EmulatedFakeCamera2::kAvailableProcessedSizesFront[4] = {
320, 240, 160, 120
- // Sensor::kResolution[0], Sensor::kResolution[1]
+ // mSensorWidth, mSensorHeight
};
const uint64_t EmulatedFakeCamera2::kAvailableProcessedMinDurations[1] = {
@@ -74,12 +72,12 @@
const uint32_t EmulatedFakeCamera2::kAvailableJpegSizesBack[2] = {
640, 480
- // Sensor::kResolution[0], Sensor::kResolution[1]
+ // mSensorWidth, mSensorHeight
};
const uint32_t EmulatedFakeCamera2::kAvailableJpegSizesFront[2] = {
320, 240
- // Sensor::kResolution[0], Sensor::kResolution[1]
+ // mSensorWidth, mSensorHeight
};
@@ -112,6 +110,24 @@
status_t EmulatedFakeCamera2::Initialize() {
status_t res;
+ // Find max width/height
+ int32_t width = 0, height = 0;
+ size_t rawSizeCount = sizeof(kAvailableRawSizes)/sizeof(kAvailableRawSizes[0]);
+ for (size_t index = 0; index + 1 < rawSizeCount; index += 2) {
+ if (width <= kAvailableRawSizes[index] &&
+ height <= kAvailableRawSizes[index+1]) {
+ width = kAvailableRawSizes[index];
+ height = kAvailableRawSizes[index+1];
+ }
+ }
+
+ if (width < 640 || height < 480) {
+ width = 640;
+ height = 480;
+ }
+ mSensorWidth = width;
+ mSensorHeight = height;
+
res = constructStaticInfo(&mCameraInfo, true);
if (res != OK) {
ALOGE("%s: Unable to allocate static info: %s (%d)",
@@ -156,7 +172,7 @@
mConfigureThread = new ConfigureThread(this);
mReadoutThread = new ReadoutThread(this);
mControlThread = new ControlThread(this);
- mSensor = new Sensor();
+ mSensor = new Sensor(mSensorWidth, mSensorHeight);
mJpegCompressor = new JpegCompressor();
mNextStreamId = 1;
@@ -479,17 +495,6 @@
__FUNCTION__, stream_id, num_buffers);
return BAD_VALUE;
}
- const cb_handle_t *streamBuffer =
- reinterpret_cast<const cb_handle_t*>(buffers[0]);
-
- int finalFormat = streamBuffer->format;
-
- if (finalFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
- ALOGE("%s: Stream %d: Bad final pixel format "
- "HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; "
- "concrete pixel format required!", __FUNCTION__, stream_id);
- return BAD_VALUE;
- }
ssize_t streamIndex = mStreams.indexOfKey(stream_id);
if (streamIndex < 0) {
@@ -499,6 +504,12 @@
Stream &stream = mStreams.editValueAt(streamIndex);
+ int finalFormat = stream.format;
+
+ if (finalFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ finalFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ }
+
ALOGV("%s: Stream %d format set to %x, previously %x",
__FUNCTION__, stream_id, finalFormat, stream.format);
@@ -1058,11 +1069,11 @@
}
/* Lock the buffer from the perspective of the graphics mapper */
- const Rect rect(s.width, s.height);
-
- res = GraphicBufferMapper::get().lock(*(b.buffer),
+ res = GrallocModule::getInstance().lock(*(b.buffer),
GRALLOC_USAGE_HW_CAMERA_WRITE,
- rect, (void**)&(b.img) );
+ 0, 0, s.width, s.height,
+ (void**)&(b.img));
+
if (res != NO_ERROR) {
ALOGE("%s: grbuffer_mapper.lock failure: %s (%d)",
@@ -1086,11 +1097,10 @@
}
/* Lock the buffer from the perspective of the graphics mapper */
- const Rect rect(s.width, s.height);
-
- res = GraphicBufferMapper::get().lock(*(b.buffer),
+ res = GrallocModule::getInstance().lock(*(b.buffer),
GRALLOC_USAGE_HW_CAMERA_READ,
- rect, (void**)&(b.img) );
+ 0, 0, s.width, s.height,
+ (void**)&(b.img) );
if (res != NO_ERROR) {
ALOGE("%s: grbuffer_mapper.lock failure: %s (%d)",
__FUNCTION__, strerror(-res), res);
@@ -1366,7 +1376,7 @@
} else {
ALOGV("Readout: Sending image buffer %zu (%p) to output stream %d",
i, (void*)*(b.buffer), b.streamId);
- GraphicBufferMapper::get().unlock(*(b.buffer));
+ GrallocModule::getInstance().unlock(*(b.buffer));
const Stream &s = mParent->getStreamInfo(b.streamId);
res = s.ops->enqueue_buffer(s.ops, captureTime, b.buffer);
if (res != OK) {
@@ -1410,7 +1420,7 @@
ALOGV("%s: Compression complete, pushing to stream %d", __FUNCTION__,
jpegBuffer.streamId);
- GraphicBufferMapper::get().unlock(*(jpegBuffer.buffer));
+ GrallocModule::getInstance().unlock(*(jpegBuffer.buffer));
const Stream &s = mParent->getStreamInfo(jpegBuffer.streamId);
res = s.ops->enqueue_buffer(s.ops, mJpegTimestamp, jpegBuffer.buffer);
}
@@ -1418,7 +1428,7 @@
void EmulatedFakeCamera2::ReadoutThread::onJpegInputDone(
const StreamBuffer &inputBuffer) {
status_t res;
- GraphicBufferMapper::get().unlock(*(inputBuffer.buffer));
+ GrallocModule::getInstance().unlock(*(inputBuffer.buffer));
const ReprocessStream &s =
mParent->getReprocessStreamInfo(-inputBuffer.streamId);
res = s.ops->release_buffer(s.ops, inputBuffer.buffer);
@@ -1455,15 +1465,15 @@
// the rectangles don't line up quite right.
const size_t numFaces = 2;
int32_t rects[numFaces * 4] = {
- static_cast<int32_t>(Sensor::kResolution[0] * 10 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 15 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 12 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 17 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 10 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 15 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 12 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 17 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 16 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 15 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 18 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 17 / 20)
+ static_cast<int32_t>(mParent->mSensorWidth * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 15 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 18 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 17 / 20)
};
// To simulate some kind of real detection going on, we jitter the rectangles on
// each frame by a few pixels in each dimension.
@@ -1496,19 +1506,19 @@
// coordinates in order are (leftEyeX, leftEyeY, rightEyeX, rightEyeY,
// mouthX, mouthY). The mapping is the same as the face rectangles.
int32_t features[numFaces * 6] = {
- static_cast<int32_t>(Sensor::kResolution[0] * 10.5 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 11.5 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 11 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16.5 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 10.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 11.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 11 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16.5 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 16.5 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 17.5 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16 / 20),
- static_cast<int32_t>(Sensor::kResolution[0] * 17 / 20),
- static_cast<int32_t>(Sensor::kResolution[1] * 16.5 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 16.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 17.5 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16 / 20),
+ static_cast<int32_t>(mParent->mSensorWidth * 17 / 20),
+ static_cast<int32_t>(mParent->mSensorHeight * 16.5 / 20),
};
// Jitter these a bit less than the rects
for (size_t i = 0; i < numFaces * 6; i++) {
@@ -2124,11 +2134,12 @@
ADD_OR_SIZE(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
sensorPhysicalSize, 2);
+ const int32_t pixelArray[] = {mSensorWidth, mSensorHeight};
ADD_OR_SIZE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- Sensor::kResolution, 2);
+ pixelArray, 2);
ADD_OR_SIZE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- Sensor::kResolution, 2);
+ pixelArray, 2);
ADD_OR_SIZE(ANDROID_SENSOR_INFO_WHITE_LEVEL,
&Sensor::kMaxRawValue, 1);
@@ -2498,7 +2509,7 @@
/** android.scaler */
static const int32_t cropRegion[3] = {
- 0, 0, static_cast<int32_t>(Sensor::kResolution[0])
+ 0, 0, static_cast<int32_t>(mSensorWidth)
};
ADD_OR_SIZE(ANDROID_SCALER_CROP_REGION, cropRegion, 3);
@@ -2586,8 +2597,8 @@
static const int32_t controlRegions[5] = {
0, 0,
- static_cast<int32_t>(Sensor::kResolution[0]),
- static_cast<int32_t>(Sensor::kResolution[1]),
+ static_cast<int32_t>(mSensorWidth),
+ static_cast<int32_t>(mSensorHeight),
1000
};
ADD_OR_SIZE(ANDROID_CONTROL_AE_REGIONS, controlRegions, 5);
diff --git a/camera/EmulatedFakeCamera2.h b/camera/EmulatedFakeCamera2.h
index 64c8667..b695016 100644
--- a/camera/EmulatedFakeCamera2.h
+++ b/camera/EmulatedFakeCamera2.h
@@ -402,6 +402,8 @@
private:
bool mIsConnected;
+ int32_t mSensorWidth, mSensorHeight;
+
/** Stream manipulation */
uint32_t mNextStreamId;
uint32_t mRawStreamCount;
diff --git a/camera/EmulatedFakeCamera3.cpp b/camera/EmulatedFakeCamera3.cpp
index 0e305f9..6aa3c5b 100644
--- a/camera/EmulatedFakeCamera3.cpp
+++ b/camera/EmulatedFakeCamera3.cpp
@@ -30,9 +30,7 @@
#include "EmulatedFakeCamera3.h"
#include "EmulatedCameraFactory.h"
#include <ui/Fence.h>
-#include <ui/Rect.h>
-#include <ui/GraphicBufferMapper.h>
-#include "gralloc_cb.h"
+#include "GrallocModule.h"
#include "fake-pipeline2/Sensor.h"
#include "fake-pipeline2/JpegCompressor.h"
@@ -68,6 +66,12 @@
HAL_PIXEL_FORMAT_Y16
};
+const uint32_t EmulatedFakeCamera3::kAvailableRawSizes[2] = {
+ 640, 480
+ // mSensorWidth, mSensorHeight
+};
+
+
/**
* 3A constants
*/
@@ -77,7 +81,8 @@
const nsecs_t EmulatedFakeCamera3::kFacePriorityExposureTime = 30 * MSEC;
const int EmulatedFakeCamera3::kNormalSensitivity = 100;
const int EmulatedFakeCamera3::kFacePrioritySensitivity = 400;
-const float EmulatedFakeCamera3::kExposureTrackRate = 0.1;
+//CTS requires 8 frames timeout in waitForAeStable
+const float EmulatedFakeCamera3::kExposureTrackRate = 0.2;
const int EmulatedFakeCamera3::kPrecaptureMinFrames = 10;
const int EmulatedFakeCamera3::kStableAeMaxFrames = 100;
const float EmulatedFakeCamera3::kExposureWanderMin = -2;
@@ -97,7 +102,6 @@
for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) {
mDefaultTemplates[i] = NULL;
}
-
}
EmulatedFakeCamera3::~EmulatedFakeCamera3() {
@@ -144,7 +148,7 @@
return INVALID_OPERATION;
}
- mSensor = new Sensor();
+ mSensor = new Sensor(mSensorWidth, mSensorHeight);
mSensor->setSensorListener(this);
res = mSensor->startUp();
@@ -536,7 +540,7 @@
/** android.scaler */
if (hasCapability(BACKWARD_COMPATIBLE)) {
static const int32_t cropRegion[4] = {
- 0, 0, (int32_t)Sensor::kResolution[0], (int32_t)Sensor::kResolution[1]
+ 0, 0, mSensorWidth, mSensorHeight
};
settings.update(ANDROID_SCALER_CROP_REGION, cropRegion, 4);
}
@@ -666,28 +670,33 @@
settings.update(ANDROID_CONTROL_AWB_LOCK, &awbLock, 1);
uint8_t afMode = 0;
- switch (type) {
- case CAMERA3_TEMPLATE_PREVIEW:
- afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
- break;
- case CAMERA3_TEMPLATE_STILL_CAPTURE:
- afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
- break;
- case CAMERA3_TEMPLATE_VIDEO_RECORD:
- afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
- break;
- case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
- afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
- break;
- case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
- afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
- break;
- case CAMERA3_TEMPLATE_MANUAL:
- afMode = ANDROID_CONTROL_AF_MODE_OFF;
- break;
- default:
- afMode = ANDROID_CONTROL_AF_MODE_AUTO;
- break;
+
+ if (mFacingBack) {
+ switch (type) {
+ case CAMERA3_TEMPLATE_PREVIEW:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_STILL_CAPTURE:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_RECORD:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+ break;
+ case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
+ afMode = ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+ break;
+ case CAMERA3_TEMPLATE_MANUAL:
+ afMode = ANDROID_CONTROL_AF_MODE_OFF;
+ break;
+ default:
+ afMode = ANDROID_CONTROL_AF_MODE_AUTO;
+ break;
+ }
+ } else {
+ afMode = ANDROID_CONTROL_AF_MODE_OFF;
}
settings.update(ANDROID_CONTROL_AF_MODE, &afMode, 1);
@@ -863,18 +872,15 @@
// structures for them, and lock them for writing.
for (size_t i = 0; i < request->num_output_buffers; i++) {
const camera3_stream_buffer &srcBuf = request->output_buffers[i];
- const cb_handle_t *privBuffer =
- static_cast<const cb_handle_t*>(*srcBuf.buffer);
- if (!cb_handle_t::validate(privBuffer)) {
- privBuffer = nullptr;
- }
StreamBuffer destBuf;
destBuf.streamId = kGenericStreamId;
destBuf.width = srcBuf.stream->width;
destBuf.height = srcBuf.stream->height;
- // If we have more specific format information, use it.
- destBuf.format = (privBuffer) ? privBuffer->format : srcBuf.stream->format;
- destBuf.stride = srcBuf.stream->width; // TODO: query from gralloc
+ // For goldfish, IMPLEMENTATION_DEFINED is always RGBx_8888
+ destBuf.format = (srcBuf.stream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) ?
+ HAL_PIXEL_FORMAT_RGBA_8888 :
+ srcBuf.stream->format;
+ destBuf.stride = srcBuf.stream->width;
destBuf.dataSpace = srcBuf.stream->data_space;
destBuf.buffer = srcBuf.buffer;
@@ -891,13 +897,13 @@
}
if (res == OK) {
// Lock buffer for writing
- const Rect rect(destBuf.width, destBuf.height);
if (srcBuf.stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- if (destBuf.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ if (destBuf.format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
android_ycbcr ycbcr = android_ycbcr();
- res = GraphicBufferMapper::get().lockYCbCr(
+ res = GrallocModule::getInstance().lock_ycbcr(
*(destBuf.buffer),
- GRALLOC_USAGE_HW_CAMERA_WRITE, rect,
+ GRALLOC_USAGE_HW_CAMERA_WRITE,
+ 0, 0, destBuf.width, destBuf.height,
&ycbcr);
// This is only valid because we know that emulator's
// YCbCr_420_888 is really contiguous NV21 under the hood
@@ -908,9 +914,12 @@
res = INVALID_OPERATION;
}
} else {
- res = GraphicBufferMapper::get().lock(*(destBuf.buffer),
- GRALLOC_USAGE_HW_CAMERA_WRITE, rect,
- (void**)&(destBuf.img));
+ res = GrallocModule::getInstance().lock(
+ *(destBuf.buffer),
+ GRALLOC_USAGE_HW_CAMERA_WRITE,
+ 0, 0, destBuf.width, destBuf.height,
+ (void**)&(destBuf.img));
+
}
if (res != OK) {
ALOGE("%s: Request %d: Buffer %zu: Unable to lock buffer",
@@ -922,7 +931,7 @@
// Either waiting or locking failed. Unlock locked buffers and bail
// out.
for (size_t j = 0; j < i; j++) {
- GraphicBufferMapper::get().unlock(
+ GrallocModule::getInstance().unlock(
*(request->output_buffers[i].buffer));
}
delete sensorBuffers;
@@ -938,12 +947,17 @@
* Wait for JPEG compressor to not be busy, if needed
*/
if (needJpeg) {
- bool ready = mJpegCompressor->waitForDone(kFenceTimeoutMs);
+ bool ready = mJpegCompressor->waitForDone(kJpegTimeoutNs);
if (!ready) {
ALOGE("%s: Timeout waiting for JPEG compression to complete!",
__FUNCTION__);
return NO_INIT;
}
+ res = mJpegCompressor->reserve();
+ if (res != OK) {
+ ALOGE("%s: Error managing JPEG compressor resources, can't reserve it!", __FUNCTION__);
+ return NO_INIT;
+ }
}
/**
@@ -1083,6 +1097,24 @@
Vector<int32_t> availableCharacteristicsKeys;
status_t res;
+ // Find max width/height
+ int32_t width = 0, height = 0;
+ size_t rawSizeCount = sizeof(kAvailableRawSizes)/sizeof(kAvailableRawSizes[0]);
+ for (size_t index = 0; index + 1 < rawSizeCount; index += 2) {
+ if (width <= kAvailableRawSizes[index] &&
+ height <= kAvailableRawSizes[index+1]) {
+ width = kAvailableRawSizes[index];
+ height = kAvailableRawSizes[index+1];
+ }
+ }
+
+ if (width < 640 || height < 480) {
+ width = 640;
+ height = 480;
+ }
+ mSensorWidth = width;
+ mSensorHeight = height;
+
#define ADD_STATIC_ENTRY(name, varptr, count) \
availableCharacteristicsKeys.add(name); \
res = info.update(name, varptr, count); \
@@ -1111,11 +1143,12 @@
ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
sensorPhysicalSize, 2);
+ const int32_t pixelArray[] = {mSensorWidth, mSensorHeight};
ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
- (int32_t*)Sensor::kResolution, 2);
-
+ pixelArray, 2);
+ const int32_t activeArray[] = {0, 0, mSensorWidth, mSensorHeight};
ADD_STATIC_ENTRY(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
- (int32_t*)Sensor::kActiveArray, 4);
+ activeArray, 4);
static const int32_t orientation = 90; // Aligned with 'long edge'
ADD_STATIC_ENTRY(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
@@ -1210,10 +1243,10 @@
sizeof(lensPoseTranslation)/sizeof(float));
// Intrinsics are 'ideal' (f_x, f_y, c_x, c_y, s) match focal length and active array size
- float f_x = focalLength * Sensor::kActiveArray[2] / sensorPhysicalSize[0];
- float f_y = focalLength * Sensor::kActiveArray[3] / sensorPhysicalSize[1];
- float c_x = Sensor::kActiveArray[2] / 2.f;
- float c_y = Sensor::kActiveArray[3] / 2.f;
+ float f_x = focalLength * mSensorWidth / sensorPhysicalSize[0];
+ float f_y = focalLength * mSensorHeight / sensorPhysicalSize[1];
+ float c_x = mSensorWidth / 2.f;
+ float c_y = mSensorHeight / 2.f;
float s = 0.f;
const float lensIntrinsics[] = { f_x, f_y, c_x, c_y, s };
@@ -1256,18 +1289,27 @@
// android.scaler
const std::vector<int32_t> availableStreamConfigurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_RGBA_8888, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_BLOB, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
+ HAL_PIXEL_FORMAT_BLOB, 320, 240, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
};
- const std::vector<int32_t> availableStreamConfigurationsRaw = {
- HAL_PIXEL_FORMAT_RAW16, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
- };
- const std::vector<int32_t> availableStreamConfigurationsBurst = {
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int32_t> availableStreamConfigurationsBasic640 = {
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
- HAL_PIXEL_FORMAT_RGBA_8888, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
+ HAL_PIXEL_FORMAT_BLOB, 640, 480, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT
+ };
+
+ const std::vector<int32_t> availableStreamConfigurationsRaw = {
+ HAL_PIXEL_FORMAT_RAW16, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ };
+
+ const std::vector<int32_t> availableStreamConfigurationsBurst = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+ HAL_PIXEL_FORMAT_RGBA_8888, width, height, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
};
std::vector<int32_t> availableStreamConfigurations;
@@ -1276,6 +1318,11 @@
availableStreamConfigurations.insert(availableStreamConfigurations.end(),
availableStreamConfigurationsBasic.begin(),
availableStreamConfigurationsBasic.end());
+ if (width > 640) {
+ availableStreamConfigurations.insert(availableStreamConfigurations.end(),
+ availableStreamConfigurationsBasic640.begin(),
+ availableStreamConfigurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableStreamConfigurations.insert(availableStreamConfigurations.end(),
@@ -1295,18 +1342,27 @@
}
const std::vector<int64_t> availableMinFrameDurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB, width, height, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_RGBA_8888, 320, 240, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0]
+ HAL_PIXEL_FORMAT_BLOB, 320, 240, Sensor::kFrameDurationRange[0],
};
- const std::vector<int64_t> availableMinFrameDurationsRaw = {
- HAL_PIXEL_FORMAT_RAW16, 640, 480, Sensor::kFrameDurationRange[0]
- };
- const std::vector<int64_t> availableMinFrameDurationsBurst = {
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int64_t> availableMinFrameDurationsBasic640 = {
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, Sensor::kFrameDurationRange[0],
- HAL_PIXEL_FORMAT_RGBA_8888, 640, 480, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0]
+ };
+
+ const std::vector<int64_t> availableMinFrameDurationsRaw = {
+ HAL_PIXEL_FORMAT_RAW16, width, height, Sensor::kFrameDurationRange[0],
+ };
+
+ const std::vector<int64_t> availableMinFrameDurationsBurst = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, width, height, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_YCbCr_420_888, width, height, Sensor::kFrameDurationRange[0],
+ HAL_PIXEL_FORMAT_RGBA_8888, width, height, Sensor::kFrameDurationRange[0],
};
std::vector<int64_t> availableMinFrameDurations;
@@ -1315,6 +1371,11 @@
availableMinFrameDurations.insert(availableMinFrameDurations.end(),
availableMinFrameDurationsBasic.begin(),
availableMinFrameDurationsBasic.end());
+ if (width > 640) {
+ availableMinFrameDurations.insert(availableMinFrameDurations.end(),
+ availableMinFrameDurationsBasic640.begin(),
+ availableMinFrameDurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableMinFrameDurations.insert(availableMinFrameDurations.end(),
@@ -1334,11 +1395,19 @@
}
const std::vector<int64_t> availableStallDurationsBasic = {
+ HAL_PIXEL_FORMAT_BLOB, width, height, Sensor::kFrameDurationRange[0],
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 320, 240, 0,
HAL_PIXEL_FORMAT_YCbCr_420_888, 320, 240, 0,
HAL_PIXEL_FORMAT_RGBA_8888, 320, 240, 0,
+ };
+
+ // Always need to include 640x480 in basic formats
+ const std::vector<int64_t> availableStallDurationsBasic640 = {
+ HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 640, 480, 0,
+ HAL_PIXEL_FORMAT_YCbCr_420_888, 640, 480, 0,
HAL_PIXEL_FORMAT_BLOB, 640, 480, Sensor::kFrameDurationRange[0]
};
+
const std::vector<int64_t> availableStallDurationsRaw = {
HAL_PIXEL_FORMAT_RAW16, 640, 480, Sensor::kFrameDurationRange[0]
};
@@ -1354,6 +1423,11 @@
availableStallDurations.insert(availableStallDurations.end(),
availableStallDurationsBasic.begin(),
availableStallDurationsBasic.end());
+ if (width > 640) {
+ availableStallDurations.insert(availableStallDurations.end(),
+ availableStallDurationsBasic640.begin(),
+ availableStallDurationsBasic640.end());
+ }
}
if (hasCapability(RAW)) {
availableStallDurations.insert(availableStallDurations.end(),
@@ -1786,6 +1860,9 @@
uint8_t controlMode = e.data.u8[0];
if (controlMode == ANDROID_CONTROL_MODE_OFF) {
+ mAeMode = ANDROID_CONTROL_AE_MODE_OFF;
+ mAfMode = ANDROID_CONTROL_AF_MODE_OFF;
+ mAwbMode = ANDROID_CONTROL_AWB_MODE_OFF;
mAeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
mAfState = ANDROID_CONTROL_AF_STATE_INACTIVE;
mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
@@ -1843,6 +1920,7 @@
return BAD_VALUE;
}
uint8_t aeMode = (e.count > 0) ? e.data.u8[0] : (uint8_t)ANDROID_CONTROL_AE_MODE_ON;
+ mAeMode = aeMode;
switch (aeMode) {
case ANDROID_CONTROL_AE_MODE_OFF:
@@ -1908,8 +1986,10 @@
} else if (!aeLocked) {
// Run standard occasional AE scan
switch (mAeState) {
- case ANDROID_CONTROL_AE_STATE_CONVERGED:
case ANDROID_CONTROL_AE_STATE_INACTIVE:
+ mAeState = ANDROID_CONTROL_AE_STATE_SEARCHING;
+ break;
+ case ANDROID_CONTROL_AE_STATE_CONVERGED:
mAeCounter++;
if (mAeCounter > kStableAeMaxFrames) {
mAeTargetExposureTime =
@@ -2171,16 +2251,21 @@
// TODO: Add white balance simulation
+ e = settings.find(ANDROID_CONTROL_AWB_LOCK);
+ bool awbLocked = (e.count > 0) ? (e.data.u8[0] == ANDROID_CONTROL_AWB_LOCK_ON) : false;
+
switch (awbMode) {
case ANDROID_CONTROL_AWB_MODE_OFF:
mAwbState = ANDROID_CONTROL_AWB_STATE_INACTIVE;
- return OK;
+ break;
case ANDROID_CONTROL_AWB_MODE_AUTO:
case ANDROID_CONTROL_AWB_MODE_INCANDESCENT:
case ANDROID_CONTROL_AWB_MODE_FLUORESCENT:
case ANDROID_CONTROL_AWB_MODE_DAYLIGHT:
case ANDROID_CONTROL_AWB_MODE_SHADE:
- // OK
+ // Always magically right, or locked
+ mAwbState = awbLocked ? ANDROID_CONTROL_AWB_STATE_LOCKED :
+ ANDROID_CONTROL_AWB_STATE_CONVERGED;
break;
default:
ALOGE("%s: Emulator doesn't support AWB mode %d",
@@ -2387,7 +2472,7 @@
__FUNCTION__, strerror(-res), res);
// fallthrough for cleanup
}
- GraphicBufferMapper::get().unlock(*(buf->buffer));
+ GrallocModule::getInstance().unlock(*(buf->buffer));
buf->status = goodBuffer ? CAMERA3_BUFFER_STATUS_OK :
CAMERA3_BUFFER_STATUS_ERROR;
@@ -2489,7 +2574,7 @@
const StreamBuffer &jpegBuffer, bool success) {
Mutex::Autolock jl(mJpegLock);
- GraphicBufferMapper::get().unlock(*(jpegBuffer.buffer));
+ GrallocModule::getInstance().unlock(*(jpegBuffer.buffer));
mJpegHalBuffer.status = success ?
CAMERA3_BUFFER_STATUS_OK : CAMERA3_BUFFER_STATUS_ERROR;
@@ -2498,10 +2583,13 @@
mJpegWaiting = false;
camera3_capture_result result;
+
result.frame_number = mJpegFrameNumber;
result.result = NULL;
result.num_output_buffers = 1;
result.output_buffers = &mJpegHalBuffer;
+ result.input_buffer = nullptr;
+ result.partial_result = 0;
if (!success) {
ALOGE("%s: Compression failure, returning error state buffer to"
diff --git a/camera/EmulatedFakeCamera3.h b/camera/EmulatedFakeCamera3.h
index 4835009..3921178 100644
--- a/camera/EmulatedFakeCamera3.h
+++ b/camera/EmulatedFakeCamera3.h
@@ -139,10 +139,11 @@
// no concept of a stream id.
static const uint32_t kGenericStreamId = 1;
static const int32_t kAvailableFormats[];
-
+ static const uint32_t kAvailableRawSizes[];
static const int64_t kSyncWaitTimeout = 10000000; // 10 ms
static const int32_t kMaxSyncTimeoutCount = 1000; // 1000 kSyncWaitTimeouts
static const uint32_t kFenceTimeoutMs = 2000; // 2 s
+ static const nsecs_t kJpegTimeoutNs = 5000000000l; // 5 s
/****************************************************************************
* Data members.
@@ -153,6 +154,8 @@
/* Facing back (true) or front (false) switch. */
bool mFacingBack;
+ int32_t mSensorWidth;
+ int32_t mSensorHeight;
SortedVector<AvailableCapabilities> mCapabilities;
diff --git a/camera/EmulatedQemuCamera.cpp b/camera/EmulatedQemuCamera.cpp
index ce47f07..eb2c4be 100755
--- a/camera/EmulatedQemuCamera.cpp
+++ b/camera/EmulatedQemuCamera.cpp
@@ -138,6 +138,8 @@
mParameters.set(EmulatedCamera::FACING_KEY, facing_dir);
mParameters.set(EmulatedCamera::ORIENTATION_KEY,
gEmulatedCameraFactory.getQemuCameraOrientation());
+ mParameters.set(CameraParameters::KEY_ROTATION,
+ gEmulatedCameraFactory.getQemuCameraOrientation());
mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
sizes.c_str());
mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
diff --git a/camera/Exif.cpp b/camera/Exif.cpp
index aa58f4b..d444824 100644
--- a/camera/Exif.cpp
+++ b/camera/Exif.cpp
@@ -280,11 +280,16 @@
float triplet[3];
float floatValue = 0.0f;
const char* stringValue;
+ int64_t degrees;
// Datetime, creating and initializing a datetime tag will automatically
// set the current date and time in the tag so just do that.
createEntry(exifData, EXIF_IFD_0, EXIF_TAG_DATE_TIME);
+ // Make and model
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MAKE, "Emulator-Goldfish");
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_MODEL, "Emulator-Goldfish");
+
// Picture size
int width = -1, height = -1;
params.getPictureSize(&width, &height);
@@ -294,6 +299,38 @@
createEntry(exifData, EXIF_IFD_EXIF,
EXIF_TAG_PIXEL_Y_DIMENSION, height);
}
+ // Orientation
+ if (getCameraParam(params,
+ CameraParameters::KEY_ROTATION,
+ °rees)) {
+ // Exif orientation values, please refer to
+ // http://www.exif.org/Exif2-2.PDF, Section 4.6.4-A-Orientation
+ // Or these websites:
+ // http://sylvana.net/jpegcrop/exif_orientation.html
+ // http://www.impulseadventure.com/photo/exif-orientation.html
+ enum {
+ EXIF_ROTATE_CAMERA_CW0 = 1,
+ EXIF_ROTATE_CAMERA_CW90 = 6,
+ EXIF_ROTATE_CAMERA_CW180 = 3,
+ EXIF_ROTATE_CAMERA_CW270 = 8,
+ };
+ uint16_t exifOrien = 1;
+ switch (degrees) {
+ case 0:
+ exifOrien = EXIF_ROTATE_CAMERA_CW0;
+ break;
+ case 90:
+ exifOrien = EXIF_ROTATE_CAMERA_CW90;
+ break;
+ case 180:
+ exifOrien = EXIF_ROTATE_CAMERA_CW180;
+ break;
+ case 270:
+ exifOrien = EXIF_ROTATE_CAMERA_CW270;
+ break;
+ }
+ createEntry(exifData, EXIF_IFD_0, EXIF_TAG_ORIENTATION, exifOrien);
+ }
// Focal length
if (getCameraParam(params,
CameraParameters::KEY_FOCAL_LENGTH,
diff --git a/camera/GrallocModule.h b/camera/GrallocModule.h
new file mode 100644
index 0000000..1f5a8f2
--- /dev/null
+++ b/camera/GrallocModule.h
@@ -0,0 +1,43 @@
+#ifndef EMU_CAMERA_GRALLOC_MODULE_H
+#define EMU_CAMERA_GRALLOC_MODULE_H
+
+#include <hardware/gralloc.h>
+
+class GrallocModule
+{
+public:
+ static GrallocModule &getInstance() {
+ static GrallocModule instance;
+ return instance;
+ }
+
+ int lock(buffer_handle_t handle,
+ int usage, int l, int t, int w, int h, void **vaddr) {
+ return mModule->lock(mModule, handle, usage, l, t, w, h, vaddr);
+ }
+
+#ifdef GRALLOC_MODULE_API_VERSION_0_2
+ int lock_ycbcr(buffer_handle_t handle,
+ int usage, int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr) {
+ return mModule->lock_ycbcr(mModule, handle, usage, l, t, w, h, ycbcr);
+ }
+#endif
+
+ int unlock(buffer_handle_t handle) {
+ return mModule->unlock(mModule, handle);
+ }
+
+private:
+ GrallocModule() {
+ const hw_module_t *module = NULL;
+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (ret) {
+ ALOGE("%s: Failed to get gralloc module: %d", __FUNCTION__, ret);
+ }
+ mModule = reinterpret_cast<const gralloc_module_t*>(module);
+ }
+ const gralloc_module_t *mModule;
+};
+
+#endif
diff --git a/camera/JpegCompressor.cpp b/camera/JpegCompressor.cpp
index 9694ca3..d757a3d 100644
--- a/camera/JpegCompressor.cpp
+++ b/camera/JpegCompressor.cpp
@@ -46,7 +46,7 @@
NV21JpegCompressor::NV21JpegCompressor()
{
- const char dlName[] = "/system/lib/hw/camera.goldfish.jpeg.so";
+ const char dlName[] = "/vendor/lib/hw/camera.goldfish.jpeg.so";
if (mDl == NULL) {
mDl = dlopen(dlName, RTLD_NOW);
}
diff --git a/camera/PreviewWindow.cpp b/camera/PreviewWindow.cpp
index 68d3d5d..607ad7d 100755
--- a/camera/PreviewWindow.cpp
+++ b/camera/PreviewWindow.cpp
@@ -22,10 +22,9 @@
#define LOG_NDEBUG 0
#define LOG_TAG "EmulatedCamera_Preview"
#include <cutils/log.h>
-#include <ui/Rect.h>
-#include <ui/GraphicBufferMapper.h>
#include "EmulatedCameraDevice.h"
#include "PreviewWindow.h"
+#include "GrallocModule.h"
namespace android {
@@ -150,11 +149,11 @@
/* Now let the graphics framework to lock the buffer, and provide
* us with the framebuffer data address. */
void* img = NULL;
- const Rect rect(mPreviewFrameWidth, mPreviewFrameHeight);
- GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get());
- res = grbuffer_mapper.lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, rect, &img);
+ res = GrallocModule::getInstance().lock(
+ *buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ 0, 0, mPreviewFrameWidth, mPreviewFrameHeight, &img);
if (res != NO_ERROR) {
- ALOGE("%s: grbuffer_mapper.lock failure: %d -> %s",
+ ALOGE("%s: gralloc.lock failure: %d -> %s",
__FUNCTION__, res, strerror(res));
mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
return;
@@ -171,7 +170,7 @@
ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
}
- grbuffer_mapper.unlock(*buffer);
+ GrallocModule::getInstance().unlock(*buffer);
}
/***************************************************************************
diff --git a/camera/fake-pipeline2/Base.h b/camera/fake-pipeline2/Base.h
index 724b3f9..473a9f3 100644
--- a/camera/fake-pipeline2/Base.h
+++ b/camera/fake-pipeline2/Base.h
@@ -22,7 +22,6 @@
#ifndef HW_EMULATOR_CAMERA2_BASE_H
#define HW_EMULATOR_CAMERA2_BASE_H
-#include <system/window.h>
#include <hardware/camera2.h>
#include <utils/Vector.h>
diff --git a/camera/fake-pipeline2/JpegCompressor.cpp b/camera/fake-pipeline2/JpegCompressor.cpp
index d0dce26..5dad236 100644
--- a/camera/fake-pipeline2/JpegCompressor.cpp
+++ b/camera/fake-pipeline2/JpegCompressor.cpp
@@ -18,7 +18,6 @@
#define LOG_TAG "EmulatedCamera2_JpegCompressor"
#include <utils/Log.h>
-#include <ui/GraphicBufferMapper.h>
#include "JpegCompressor.h"
#include "../EmulatedFakeCamera2.h"
@@ -38,6 +37,16 @@
Mutex::Autolock lock(mMutex);
}
+status_t JpegCompressor::reserve() {
+ Mutex::Autolock busyLock(mBusyMutex);
+ if (mIsBusy) {
+ ALOGE("%s: Already processing a buffer!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ mIsBusy = true;
+ return OK;
+}
+
status_t JpegCompressor::start(Buffers *buffers, JpegListener *listener) {
if (listener == NULL) {
ALOGE("%s: NULL listener not allowed!", __FUNCTION__);
@@ -47,12 +56,10 @@
{
Mutex::Autolock busyLock(mBusyMutex);
- if (mIsBusy) {
- ALOGE("%s: Already processing a buffer!", __FUNCTION__);
+ if (!mIsBusy) {
+ ALOGE("Called start without reserve() first!");
return INVALID_OPERATION;
}
-
- mIsBusy = true;
mSynchronous = false;
mBuffers = buffers;
mListener = listener;
@@ -117,7 +124,6 @@
status_t JpegCompressor::compress() {
// Find source and target buffers. Assumes only one buffer matches
// each condition!
-
bool foundJpeg = false, mFoundAux = false;
for (size_t i = 0; i < mBuffers->size(); i++) {
const StreamBuffer &b = (*mBuffers)[i];
@@ -215,11 +221,11 @@
bool JpegCompressor::waitForDone(nsecs_t timeout) {
Mutex::Autolock lock(mBusyMutex);
- status_t res = OK;
- if (mIsBusy) {
- res = mDone.waitRelative(mBusyMutex, timeout);
+ while (mIsBusy) {
+ status_t res = mDone.waitRelative(mBusyMutex, timeout);
+ if (res != OK) return false;
}
- return (res == OK);
+ return true;
}
bool JpegCompressor::checkError(const char *msg) {
diff --git a/camera/fake-pipeline2/JpegCompressor.h b/camera/fake-pipeline2/JpegCompressor.h
index ff6f8a4..597cbdf 100644
--- a/camera/fake-pipeline2/JpegCompressor.h
+++ b/camera/fake-pipeline2/JpegCompressor.h
@@ -56,6 +56,7 @@
// Start compressing COMPRESSED format buffers; JpegCompressor takes
// ownership of the Buffers vector.
+ // Reserve() must be called first.
status_t start(Buffers *buffers, JpegListener *listener);
// Compress and block until buffer is complete.
@@ -68,6 +69,9 @@
bool waitForDone(nsecs_t timeout);
+ // Reserve the compressor for a later start() call.
+ status_t reserve();
+
// TODO: Measure this
static const size_t kMaxJpegSize = 300000;
diff --git a/camera/fake-pipeline2/Sensor.cpp b/camera/fake-pipeline2/Sensor.cpp
index 61c7f28..02c6835 100644
--- a/camera/fake-pipeline2/Sensor.cpp
+++ b/camera/fake-pipeline2/Sensor.cpp
@@ -34,9 +34,6 @@
namespace android {
-const unsigned int Sensor::kResolution[2] = {640, 480};
-const unsigned int Sensor::kActiveArray[4] = {0, 0, 640, 480};
-
//const nsecs_t Sensor::kExposureTimeRange[2] =
// {1000L, 30000000000L} ; // 1 us - 30 sec
//const nsecs_t Sensor::kFrameDurationRange[2] =
@@ -76,13 +73,6 @@
Sensor::kReadNoiseStddevAfterGain *
Sensor::kReadNoiseStddevAfterGain;
-// While each row has to read out, reset, and then expose, the (reset +
-// expose) sequence can be overlapped by other row readouts, so the final
-// minimum frame duration is purely a function of row readout time, at least
-// if there's a reasonable number of rows.
-const nsecs_t Sensor::kRowReadoutTime =
- Sensor::kFrameDurationRange[0] / Sensor::kResolution[1];
-
const int32_t Sensor::kSensitivityRange[2] = {100, 1600};
const uint32_t Sensor::kDefaultSensitivity = 100;
@@ -105,8 +95,11 @@
-Sensor::Sensor():
+Sensor::Sensor(uint32_t width, uint32_t height):
Thread(false),
+ mResolution{width, height},
+ mActiveArray{0, 0, width, height},
+ mRowReadoutTime(kFrameDurationRange[0] / height),
mGotVSync(false),
mExposureTime(kFrameDurationRange[0]-kMinVerticalBlank),
mFrameDuration(kFrameDurationRange[0]),
@@ -115,9 +108,9 @@
mFrameNumber(0),
mCapturedBuffers(NULL),
mListener(NULL),
- mScene(kResolution[0], kResolution[1], kElectronsPerLuxSecond)
+ mScene(width, height, kElectronsPerLuxSecond)
{
-
+ ALOGV("Sensor created with pixel array %d x %d", width, height);
}
Sensor::~Sensor() {
@@ -207,9 +200,8 @@
ALOGE("Error waiting for sensor readout signal: %d", res);
return false;
}
- } else {
- mReadoutComplete.signal();
}
+ mReadoutComplete.signal();
*captureTime = mCaptureTime;
mCapturedBuffers = NULL;
@@ -279,7 +271,7 @@
nsecs_t simulatedTime = startRealTime;
nsecs_t frameEndRealTime = startRealTime + frameDuration;
nsecs_t frameReadoutEndRealTime = startRealTime +
- kRowReadoutTime * kResolution[1];
+ mRowReadoutTime * mResolution[1];
if (mNextCapturedBuffers != NULL) {
ALOGVV("Sensor starting readout");
@@ -287,7 +279,7 @@
capturedBuffers = mNextCapturedBuffers;
captureTime = mNextCaptureTime;
}
- simulatedTime += kRowReadoutTime + kMinVerticalBlank;
+ simulatedTime += mRowReadoutTime + kMinVerticalBlank;
// TODO: Move this signal to another thread to simulate readout
// time properly
@@ -357,7 +349,7 @@
captureDepthCloud(b.img);
}
break;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
captureNV21(b.img, gain, b.stride);
break;
case HAL_PIXEL_FORMAT_YV12:
@@ -403,10 +395,10 @@
int bayerSelect[4] = {Scene::R, Scene::Gr, Scene::Gb, Scene::B}; // RGGB
mScene.setReadoutPixel(0,0);
- for (unsigned int y = 0; y < kResolution[1]; y++ ) {
+ for (unsigned int y = 0; y < mResolution[1]; y++ ) {
int *bayerRow = bayerSelect + (y & 0x1) * 2;
uint16_t *px = (uint16_t*)img + y * stride;
- for (unsigned int x = 0; x < kResolution[0]; x++) {
+ for (unsigned int x = 0; x < mResolution[0]; x++) {
uint32_t electronCount;
electronCount = mScene.getPixelElectrons()[bayerRow[x & 0x1]];
@@ -431,7 +423,7 @@
*px++ = rawCount;
}
// TODO: Handle this better
- //simulatedTime += kRowReadoutTime;
+ //simulatedTime += mRowReadoutTime;
}
ALOGVV("Raw sensor image captured");
}
@@ -440,12 +432,12 @@
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate total scaling from electrons to 8bpp
int scale64x = 64 * totalGain * 255 / kMaxRawValue;
- uint32_t inc = kResolution[0] / stride;
+ uint32_t inc = ceil( (float) mResolution[0] / stride);
- for (unsigned int y = 0, outY = 0; y < kResolution[1]; y+=inc, outY++ ) {
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y+=inc, outY++ ) {
uint8_t *px = img + outY * stride * 4;
mScene.setReadoutPixel(0, y);
- for (unsigned int x = 0; x < kResolution[0]; x+=inc) {
+ for (unsigned int x = 0; x < mResolution[0]; x+=inc) {
uint32_t rCount, gCount, bCount;
// TODO: Perfect demosaicing is a cheat
const uint32_t *pixel = mScene.getPixelElectrons();
@@ -461,7 +453,7 @@
mScene.getPixelElectrons();
}
// TODO: Handle this better
- //simulatedTime += kRowReadoutTime;
+ //simulatedTime += mRowReadoutTime;
}
ALOGVV("RGBA sensor image captured");
}
@@ -470,12 +462,12 @@
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate total scaling from electrons to 8bpp
int scale64x = 64 * totalGain * 255 / kMaxRawValue;
- uint32_t inc = kResolution[0] / stride;
+ uint32_t inc = ceil( (float) mResolution[0] / stride);
- for (unsigned int y = 0, outY = 0; y < kResolution[1]; y += inc, outY++ ) {
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++ ) {
mScene.setReadoutPixel(0, y);
uint8_t *px = img + outY * stride * 3;
- for (unsigned int x = 0; x < kResolution[0]; x += inc) {
+ for (unsigned int x = 0; x < mResolution[0]; x += inc) {
uint32_t rCount, gCount, bCount;
// TODO: Perfect demosaicing is a cheat
const uint32_t *pixel = mScene.getPixelElectrons();
@@ -490,7 +482,7 @@
mScene.getPixelElectrons();
}
// TODO: Handle this better
- //simulatedTime += kRowReadoutTime;
+ //simulatedTime += mRowReadoutTime;
}
ALOGVV("RGB sensor image captured");
}
@@ -512,10 +504,13 @@
const int scaleOut = 64;
const int scaleOutSq = scaleOut * scaleOut; // after multiplies
- uint32_t inc = kResolution[0] / stride;
- uint32_t outH = kResolution[1] / inc;
+ // inc = how many pixels to skip while reading every next pixel
+ // horizontally.
+ uint32_t inc = ceil( (float) mResolution[0] / stride);
+ // outH = projected vertical resolution based on stride.
+ uint32_t outH = mResolution[1] / inc;
for (unsigned int y = 0, outY = 0;
- y < kResolution[1]; y+=inc, outY++) {
+ y < mResolution[1]; y+=inc, outY++) {
uint8_t *pxY = img + outY * stride;
uint8_t *pxVU = img + (outH + outY / 2) * stride;
mScene.setReadoutPixel(0,y);
@@ -554,12 +549,12 @@
float totalGain = gain/100.0 * kBaseGainFactor;
// In fixed-point math, calculate scaling factor to 13bpp millimeters
int scale64x = 64 * totalGain * 8191 / kMaxRawValue;
- uint32_t inc = kResolution[0] / stride;
+ uint32_t inc = ceil( (float) mResolution[0] / stride);
- for (unsigned int y = 0, outY = 0; y < kResolution[1]; y += inc, outY++ ) {
+ for (unsigned int y = 0, outY = 0; y < mResolution[1]; y += inc, outY++ ) {
mScene.setReadoutPixel(0, y);
uint16_t *px = ((uint16_t*)img) + outY * stride;
- for (unsigned int x = 0; x < kResolution[0]; x += inc) {
+ for (unsigned int x = 0; x < mResolution[0]; x += inc) {
uint32_t depthCount;
// TODO: Make up real depth scene instead of using green channel
// as depth
@@ -571,7 +566,7 @@
mScene.getPixelElectrons();
}
// TODO: Handle this better
- //simulatedTime += kRowReadoutTime;
+ //simulatedTime += mRowReadoutTime;
}
ALOGVV("Depth sensor image captured");
}
diff --git a/camera/fake-pipeline2/Sensor.h b/camera/fake-pipeline2/Sensor.h
index 720fbc2..cdf1e97 100644
--- a/camera/fake-pipeline2/Sensor.h
+++ b/camera/fake-pipeline2/Sensor.h
@@ -89,7 +89,9 @@
class Sensor: private Thread, public virtual RefBase {
public:
- Sensor();
+ // width: Width of pixel array
+ // height: Height of pixel array
+ Sensor(uint32_t width, uint32_t height);
~Sensor();
/*
@@ -157,8 +159,8 @@
/**
* Static sensor characteristics
*/
- static const unsigned int kResolution[2];
- static const unsigned int kActiveArray[4];
+ const uint32_t mResolution[2];
+ const uint32_t mActiveArray[4];
static const nsecs_t kExposureTimeRange[2];
static const nsecs_t kFrameDurationRange[2];
@@ -187,7 +189,7 @@
// expose) sequence can be overlapped by other row readouts, so the final
// minimum frame duration is purely a function of row readout time, at least
// if there's a reasonable number of rows.
- static const nsecs_t kRowReadoutTime;
+ const nsecs_t mRowReadoutTime;
static const int32_t kSensitivityRange[2];
static const uint32_t kDefaultSensitivity;
diff --git a/camera/jpeg-stub/Android.mk b/camera/jpeg-stub/Android.mk
index eea0ced..e017ac1 100644
--- a/camera/jpeg-stub/Android.mk
+++ b/camera/jpeg-stub/Android.mk
@@ -22,6 +22,7 @@
ifneq ($(TARGET_BUILD_PDK),true)
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
jpeg_module_relative_path := hw
jpeg_cflags := -fno-short-enums -DQEMU_HARDWARE
@@ -59,6 +60,7 @@
include ${CLEAR_VARS}
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := camera.ranchu.jpeg
LOCAL_MODULE_RELATIVE_PATH := ${jpeg_module_relative_path}
diff --git a/camera/media_codecs_performance.xml b/camera/media_codecs_performance.xml
index 3d12ceb..b82e4c8 100644
--- a/camera/media_codecs_performance.xml
+++ b/camera/media_codecs_performance.xml
@@ -100,10 +100,10 @@
<Limit name="measured-frame-rate-320x180" range="968-1101" />
<!-- 3 runs, min 291 max 338 gmean 319 -->
<Limit name="measured-frame-rate-640x360" range="291-338" />
- <!-- 3 runs, min 109 max 128 gmean 118 -->
- <Limit name="measured-frame-rate-1280x720" range="109-128" />
- <!-- 5 runs, min 69 max 76 gmean 73 -->
- <Limit name="measured-frame-rate-1920x1080" range="69-76" />
+ <!-- Those values are from buildbots -->
+ <Limit name="measured-frame-rate-1280x720" range="280-400" />
+ <!-- Buildbot gets ~180 if it is in the first run, ~230 if it is the second run -->
+ <Limit name="measured-frame-rate-1920x1080" range="178-240" />
</MediaCodec>
</Decoders>
</MediaCodecs>
diff --git a/compatibility_matrix.xml b/compatibility_matrix.xml
new file mode 100644
index 0000000..3082485
--- /dev/null
+++ b/compatibility_matrix.xml
@@ -0,0 +1,59 @@
+<compatibility-matrix version="1.0" type="device">
+ <hal format="hidl" optional="false">
+ <name>android.frameworks.schedulerservice</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISchedulingPolicyService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.frameworks.sensorservice</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISensorManager</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hidl.allocator</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>ashmem</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hidl.manager</name>
+ <version>1.0</version>
+ <interface>
+ <name>IServiceManager</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hidl.memory</name>
+ <version>1.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>ashmem</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hidl.token</name>
+ <version>1.0</version>
+ <interface>
+ <name>ITokenManager</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.system.wifi.keystore</name>
+ <version>1.0</version>
+ <interface>
+ <name>IKeystore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+
+</compatibility-matrix>
diff --git a/data/etc/config.ini b/data/etc/config.ini
new file mode 100644
index 0000000..c78b6b8
--- /dev/null
+++ b/data/etc/config.ini
@@ -0,0 +1,20 @@
+avd.ini.encoding=UTF-8
+disk.dataPartition.size=2G
+hw.accelerometer=yes
+hw.audioInput=yes
+hw.battery=yes
+hw.camera.back=emulated
+hw.camera.front=none
+hw.dPad=no
+hw.gps=yes
+hw.gpu.enabled=yes
+hw.keyboard=yes
+hw.lcd.density=240
+hw.mainKeys=no
+hw.ramSize=2048
+hw.sensors.orientation=yes
+hw.sensors.proximity=yes
+image.sysdir.1=x86/
+skin.dynamic=no
+skin.name=480x800
+skin.path=480x800
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index b2aaf13..728e5ba 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -32,6 +32,7 @@
android.hardware.sensor.light
android.hardware.sensor.proximity
android.hardware.sensor.relative_humidity
+ android.hardware.sensor.gyroscope
android.hardware.telephony
android.hardware.telephony.gsm
android.software.midi
@@ -49,6 +50,7 @@
<feature name="android.hardware.sensor.light" />
<feature name="android.hardware.sensor.proximity" />
<feature name="android.hardware.sensor.relative_humidity" />
+ <feature name="android.hardware.sensor.gyroscope" />
<feature name="android.hardware.telephony" />
<feature name="android.hardware.telephony.gsm" />
<feature name="android.hardware.touchscreen" />
diff --git a/fingerprint/Android.mk b/fingerprint/Android.mk
index be21c97..55e513c 100644
--- a/fingerprint/Android.mk
+++ b/fingerprint/Android.mk
@@ -16,6 +16,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := fingerprint.goldfish
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
@@ -26,6 +27,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := fingerprint.ranchu
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
diff --git a/fingerprint/fingerprint.c b/fingerprint/fingerprint.c
index 6041005..dd37770 100644
--- a/fingerprint/fingerprint.c
+++ b/fingerprint/fingerprint.c
@@ -308,11 +308,15 @@
const hw_auth_token_t *hat,
uint32_t __unused gid,
uint32_t __unused timeout_sec) {
+ fingerprint_msg_t msg = {0, {0}};
+ msg.type = FINGERPRINT_ERROR;
+ msg.data.error = FINGERPRINT_ERROR_UNABLE_TO_PROCESS;
ALOGD("fingerprint_enroll");
qemu_fingerprint_device_t* dev = (qemu_fingerprint_device_t*)device;
if (!hat) {
ALOGW("%s: null auth token", __func__);
- return -EPROTONOSUPPORT;
+ dev->device.notify(&msg);
+ return 0;
}
if (hat->challenge == dev->challenge) {
// The secure_user_id retrieved from the auth token should be stored
@@ -324,10 +328,12 @@
}
if (hat->version != HW_AUTH_TOKEN_VERSION) {
- return -EPROTONOSUPPORT;
+ dev->device.notify(&msg);
+ return 0;
}
if (hat->challenge != dev->challenge && !(hat->authenticator_type & HW_AUTH_FINGERPRINT)) {
- return -EPERM;
+ dev->device.notify(&msg);
+ return 0;
}
dev->user_id = hat->user_id;
@@ -447,7 +453,7 @@
ALOGE("Can't remove fingerprint (gid=%d, fid=%d); "
"device not initialized properly",
gid, fid);
- return -1;
+ return -ENODEV;
}
qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
@@ -472,6 +478,7 @@
pthread_mutex_unlock(&qdev->lock);
msg.type = FINGERPRINT_TEMPLATE_REMOVED;
msg.data.removed.finger.fid = theFid;
+ msg.data.removed.finger.gid = qdev->group_id;
device->notify(&msg);
// Because we released the mutex, the list
@@ -486,6 +493,7 @@
pthread_mutex_unlock(&qdev->lock);
msg.type = FINGERPRINT_TEMPLATE_REMOVED;
msg.data.removed.finger.fid = 0;
+ msg.data.removed.finger.gid = qdev->group_id;
device->notify(&msg);
} else {
// Delete one fingerprint
@@ -502,7 +510,15 @@
qdev->listener.state = STATE_IDLE;
pthread_mutex_unlock(&qdev->lock);
ALOGE("Fingerprint ID %d not found", fid);
- return FINGERPRINT_ERROR;
+ //msg.type = FINGERPRINT_ERROR;
+ //msg.data.error = FINGERPRINT_ERROR_UNABLE_TO_REMOVE;
+ //device->notify(&msg);
+ msg.type = FINGERPRINT_TEMPLATE_REMOVED;
+ msg.data.removed.finger.fid = 0;
+ msg.data.removed.finger.gid = qdev->group_id;
+ msg.data.removed.remaining_templates = 0;
+ device->notify(&msg);
+ return 0;
}
qdev->listener.secureid[idx] = 0;
diff --git a/fstab.ranchu b/fstab.ranchu
index a4a0817..e5040bd 100644
--- a/fstab.ranchu
+++ b/fstab.ranchu
@@ -4,4 +4,4 @@
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
/dev/block/vdb /cache ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait
/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota,forceencrypt=/dev/block/vdd
-/devices/*/block/vde auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
+/devices/*/block/vdf auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
diff --git a/fstab.ranchu.arm b/fstab.ranchu.arm
new file mode 100644
index 0000000..6197823
--- /dev/null
+++ b/fstab.ranchu.arm
@@ -0,0 +1,7 @@
+# Android fstab file.
+#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
+# The filesystem that contains the filesystem checker binary (typically /system) cannot
+# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
+/dev/block/vdb /cache ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait
+/dev/block/vdc /data ext4 noatime,nosuid,nodev,nomblk_io_submit,errors=panic wait,check,quota
+/devices/*/block/vde auto auto defaults voldmanaged=sdcard:auto,encryptable=userdata
diff --git a/fstab.ranchu.early b/fstab.ranchu.early
new file mode 100644
index 0000000..915d923
--- /dev/null
+++ b/fstab.ranchu.early
@@ -0,0 +1,6 @@
+# Android fstab file.
+#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
+# The filesystem that contains the filesystem checker binary (typically /system) cannot
+# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
+/dev/block/vda /system ext4 ro wait
+/dev/block/vde /vendor ext4 ro wait
diff --git a/fstab.ranchu.early.arm b/fstab.ranchu.early.arm
new file mode 100644
index 0000000..5854b59
--- /dev/null
+++ b/fstab.ranchu.early.arm
@@ -0,0 +1,6 @@
+# Android fstab file.
+#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
+# The filesystem that contains the filesystem checker binary (typically /system) cannot
+# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
+/dev/block/vda /system ext4 ro wait
+/dev/block/vdd /vendor ext4 ro wait
diff --git a/gatekeeper/Android.mk b/gatekeeper/Android.mk
new file mode 100644
index 0000000..dc995e4
--- /dev/null
+++ b/gatekeeper/Android.mk
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE := gatekeeper.ranchu
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
+LOCAL_SRC_FILES := \
+ module.cpp \
+ SoftGateKeeperDevice.cpp
+
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libgatekeeper \
+ liblog \
+ libhardware \
+ libbase \
+ libutils \
+ libcrypto \
+ libkeystore_binder \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
+ android.hardware.gatekeeper@1.0 \
+
+LOCAL_STATIC_LIBRARIES := libscrypt_static
+LOCAL_C_INCLUDES := external/scrypt/lib/crypto
+include $(BUILD_SHARED_LIBRARY)
diff --git a/gatekeeper/SoftGateKeeper.h b/gatekeeper/SoftGateKeeper.h
new file mode 100644
index 0000000..2f4f4d7
--- /dev/null
+++ b/gatekeeper/SoftGateKeeper.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef SOFT_GATEKEEPER_H_
+#define SOFT_GATEKEEPER_H_
+
+extern "C" {
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <crypto_scrypt.h>
+}
+
+#include <android-base/memory.h>
+#include <gatekeeper/gatekeeper.h>
+
+#include <iostream>
+#include <unordered_map>
+#include <memory>
+
+namespace gatekeeper {
+
+struct fast_hash_t {
+ uint64_t salt;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+};
+
+class SoftGateKeeper : public GateKeeper {
+public:
+ static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
+
+ // scrypt params
+ static const uint64_t N = 16384;
+ static const uint32_t r = 8;
+ static const uint32_t p = 1;
+
+ static const int MAX_UINT_32_CHARS = 11;
+
+ SoftGateKeeper() {
+ key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
+ memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
+ }
+
+ virtual ~SoftGateKeeper() {
+ }
+
+ virtual bool GetAuthTokenKey(const uint8_t **auth_token_key,
+ uint32_t *length) const {
+ if (auth_token_key == NULL || length == NULL) return false;
+ uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
+ memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
+
+ *auth_token_key = auth_token_key_copy;
+ *length = SIGNATURE_LENGTH_BYTES;
+ return true;
+ }
+
+ virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) {
+ if (password_key == NULL || length == NULL) return;
+ uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES];
+ memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES);
+
+ *password_key = password_key_copy;
+ *length = SIGNATURE_LENGTH_BYTES;
+ }
+
+ virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
+ const uint8_t *, uint32_t, const uint8_t *password,
+ uint32_t password_length, salt_t salt) const {
+ if (signature == NULL) return;
+ crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt),
+ sizeof(salt), N, r, p, signature, signature_length);
+ }
+
+ virtual void GetRandom(void *random, uint32_t requested_length) const {
+ if (random == NULL) return;
+ RAND_pseudo_bytes((uint8_t *) random, requested_length);
+ }
+
+ virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
+ const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const {
+ if (signature == NULL) return;
+ memset(signature, 0, signature_length);
+ }
+
+ virtual uint64_t GetMillisecondsSinceBoot() const {
+ struct timespec time;
+ int res = clock_gettime(CLOCK_BOOTTIME, &time);
+ if (res < 0) return 0;
+ return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+ }
+
+ virtual bool IsHardwareBacked() const {
+ return false;
+ }
+
+ virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record,
+ bool /* secure */) {
+ failure_record_t *stored = &failure_map_[uid];
+ if (user_id != stored->secure_user_id) {
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ }
+ memcpy(record, stored, sizeof(*record));
+ return true;
+ }
+
+ virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
+ failure_record_t *stored = &failure_map_[uid];
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ return true;
+ }
+
+ virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool /* secure */) {
+ failure_map_[uid] = *record;
+ return true;
+ }
+
+ fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) {
+ fast_hash_t fast_hash;
+ size_t digest_size = password.length + sizeof(salt);
+ std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
+ memcpy(digest.get(), &salt, sizeof(salt));
+ memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length);
+
+ SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest);
+
+ fast_hash.salt = salt;
+ return fast_hash;
+ }
+
+ bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) {
+ fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
+ return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
+ }
+
+ bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
+ uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
+ FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
+ if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
+ return true;
+ } else {
+ if (GateKeeper::DoVerify(expected_handle, password)) {
+ uint64_t salt;
+ GetRandom(&salt, sizeof(salt));
+ fast_hash_map_[user_id] = ComputeFastHash(password, salt);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+private:
+
+ typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
+ typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
+
+ std::unique_ptr<uint8_t[]> key_;
+ FailureRecordMap failure_map_;
+ FastHashMap fast_hash_map_;
+};
+}
+
+#endif // SOFT_GATEKEEPER_H_
diff --git a/gatekeeper/SoftGateKeeperDevice.cpp b/gatekeeper/SoftGateKeeperDevice.cpp
new file mode 100644
index 0000000..3dc6997
--- /dev/null
+++ b/gatekeeper/SoftGateKeeperDevice.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "SoftGateKeeper.h"
+#include "SoftGateKeeperDevice.h"
+
+namespace goldfish {
+
+int SoftGateKeeperDevice::enroll(uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+
+ if (enrolled_password_handle == NULL || enrolled_password_handle_length == NULL ||
+ desired_password == NULL || desired_password_length == 0)
+ return -EINVAL;
+
+ // Current password and current password handle go together
+ if (current_password_handle == NULL || current_password_handle_length == 0 ||
+ current_password == NULL || current_password_length == 0) {
+ current_password_handle = NULL;
+ current_password_handle_length = 0;
+ current_password = NULL;
+ current_password_length = 0;
+ }
+
+ SizedBuffer desired_password_buffer(desired_password_length);
+ memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length);
+
+ SizedBuffer current_password_handle_buffer(current_password_handle_length);
+ if (current_password_handle) {
+ memcpy(current_password_handle_buffer.buffer.get(), current_password_handle,
+ current_password_handle_length);
+ }
+
+ SizedBuffer current_password_buffer(current_password_length);
+ if (current_password) {
+ memcpy(current_password_buffer.buffer.get(), current_password, current_password_length);
+ }
+
+ EnrollRequest request(uid, ¤t_password_handle_buffer, &desired_password_buffer,
+ ¤t_password_buffer);
+ EnrollResponse response;
+
+ impl_->Enroll(request, &response);
+
+ if (response.error == ERROR_RETRY) {
+ return response.retry_timeout;
+ } else if (response.error != ERROR_NONE) {
+ return -EINVAL;
+ }
+
+ *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
+ gatekeeper::password_handle_t *handle =
+ reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
+ //FIXIT: We need to move this module to host with gatekeeper pipe
+ handle->hardware_backed = true;
+
+ *enrolled_password_handle_length = response.enrolled_password_handle.length;
+ return 0;
+}
+
+int SoftGateKeeperDevice::verify(uint32_t uid,
+ uint64_t challenge, const uint8_t *enrolled_password_handle,
+ uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
+ uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
+ bool *request_reenroll) {
+
+ if (enrolled_password_handle == NULL ||
+ provided_password == NULL) {
+ return -EINVAL;
+ }
+
+ SizedBuffer password_handle_buffer(enrolled_password_handle_length);
+ memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle,
+ enrolled_password_handle_length);
+ SizedBuffer provided_password_buffer(provided_password_length);
+ memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length);
+
+ VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer);
+ VerifyResponse response;
+
+ impl_->Verify(request, &response);
+
+ if (response.error == ERROR_RETRY) {
+ return response.retry_timeout;
+ } else if (response.error != ERROR_NONE) {
+ return -EINVAL;
+ }
+
+ if (auth_token != NULL && auth_token_length != NULL) {
+ *auth_token = response.auth_token.buffer.release();
+ *auth_token_length = response.auth_token.length;
+ }
+
+ if (request_reenroll != NULL) {
+ *request_reenroll = response.request_reenroll;
+ }
+
+ return 0;
+}
+
+} // namespace goldfish
diff --git a/gatekeeper/SoftGateKeeperDevice.h b/gatekeeper/SoftGateKeeperDevice.h
new file mode 100644
index 0000000..af3a1bc
--- /dev/null
+++ b/gatekeeper/SoftGateKeeperDevice.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SOFT_GATEKEEPER_DEVICE_H_
+#define SOFT_GATEKEEPER_DEVICE_H_
+
+#include "SoftGateKeeper.h"
+
+#include <memory>
+
+using namespace gatekeeper;
+
+namespace goldfish {
+
+/**
+ * Software based GateKeeper implementation
+ */
+class SoftGateKeeperDevice {
+public:
+ SoftGateKeeperDevice() {
+ impl_.reset(new SoftGateKeeper());
+ }
+
+ // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API.
+
+ /**
+ * Enrolls password_payload, which should be derived from a user selected pin or password,
+ * with the authentication factor private key used only for enrolling authentication
+ * factor data.
+ *
+ * Returns: 0 on success or an error code less than 0 on error.
+ * On error, enrolled_password_handle will not be allocated.
+ */
+ int enroll(uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);
+
+ /**
+ * Verifies provided_password matches enrolled_password_handle.
+ *
+ * Implementations of this module may retain the result of this call
+ * to attest to the recency of authentication.
+ *
+ * On success, writes the address of a verification token to auth_token,
+ * usable to attest password verification to other trusted services. Clients
+ * may pass NULL for this value.
+ *
+ * Returns: 0 on success or an error code less than 0 on error
+ * On error, verification token will not be allocated
+ */
+ int verify(uint32_t uid, uint64_t challenge,
+ const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+ const uint8_t *provided_password, uint32_t provided_password_length,
+ uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
+private:
+ std::unique_ptr<SoftGateKeeper> impl_;
+};
+
+} // namespace gatekeeper
+
+#endif //SOFT_GATEKEEPER_DEVICE_H_
diff --git a/gatekeeper/module.cpp b/gatekeeper/module.cpp
new file mode 100644
index 0000000..787d3a5
--- /dev/null
+++ b/gatekeeper/module.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hardware/hardware.h>
+#include <hardware/gatekeeper.h>
+#define LOG_TAG "GoldfishGatekeeper"
+#include <cutils/log.h>
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "SoftGateKeeper.h"
+#include "SoftGateKeeperDevice.h"
+
+using goldfish::SoftGateKeeperDevice;
+
+struct goldfish_gatekeeper_device {
+ gatekeeper_device device;
+ SoftGateKeeperDevice *s_gatekeeper;
+};
+
+static goldfish_gatekeeper_device s_device;
+
+static int enroll(const struct gatekeeper_device *dev __unused, uint32_t uid,
+ const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+ const uint8_t *current_password, uint32_t current_password_length,
+ const uint8_t *desired_password, uint32_t desired_password_length,
+ uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ if (s_gatekeeper == nullptr) {
+ abort();
+ return -EINVAL;
+ }
+
+ return s_gatekeeper->enroll(uid,
+ current_password_handle, current_password_handle_length,
+ current_password, current_password_length,
+ desired_password, desired_password_length,
+ enrolled_password_handle, enrolled_password_handle_length);
+}
+
+static int verify(const struct gatekeeper_device *dev __unused, uint32_t uid, uint64_t challenge,
+ const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+ const uint8_t *provided_password, uint32_t provided_password_length,
+ uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ if (s_gatekeeper == nullptr) return -EINVAL;
+ return s_gatekeeper->verify(uid, challenge,
+ enrolled_password_handle, enrolled_password_handle_length,
+ provided_password, provided_password_length,
+ auth_token, auth_token_length, request_reenroll);
+}
+
+static int close_device(hw_device_t* dev __unused) {
+ SoftGateKeeperDevice *s_gatekeeper = ((goldfish_gatekeeper_device*)(dev))->s_gatekeeper;
+ if (s_gatekeeper == nullptr) return 0;
+ delete s_gatekeeper;
+ s_gatekeeper = nullptr;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, dev);
+ return 0;
+}
+
+static int goldfish_gatekeeper_open(const hw_module_t *module, const char *name,
+ hw_device_t **device) {
+
+ if (strcmp(name, HARDWARE_GATEKEEPER) != 0) {
+ abort();
+ return -EINVAL;
+ }
+
+ memset(&s_device, 0, sizeof(s_device));
+
+ SoftGateKeeperDevice *s_gatekeeper = new SoftGateKeeperDevice();
+ if (s_gatekeeper == nullptr) return -ENOMEM;
+
+ s_device.s_gatekeeper = s_gatekeeper;
+
+ s_device.device.common.tag = HARDWARE_DEVICE_TAG;
+ s_device.device.common.version = 1;
+ s_device.device.common.module = const_cast<hw_module_t *>(module);
+ s_device.device.common.close = close_device;
+
+ s_device.device.enroll = enroll;
+ s_device.device.verify = verify;
+ s_device.device.delete_user = nullptr;
+ s_device.device.delete_all_users = nullptr;
+
+ *device = &s_device.device.common;
+ ALOGE("called %s with gate keeper %p device %p\n", __func__, s_gatekeeper, *device);
+
+ return 0;
+}
+
+static struct hw_module_methods_t gatekeeper_module_methods = {
+ .open = goldfish_gatekeeper_open,
+};
+
+struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = GATEKEEPER_HARDWARE_MODULE_ID,
+ .name = "Goldfish GateKeeper HAL",
+ .author = "The Android Open Source Project",
+ .methods = &gatekeeper_module_methods,
+ .dso = 0,
+ .reserved = {}
+ },
+};
diff --git a/gps/Android.mk b/gps/Android.mk
index c143981..d1b593a 100644
--- a/gps/Android.mk
+++ b/gps/Android.mk
@@ -24,6 +24,7 @@
# hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_CFLAGS += -DQEMU_HARDWARE
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware
@@ -39,6 +40,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_CFLAGS += -DQEMU_HARDWARE
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware
diff --git a/gps/gps_qemu.c b/gps/gps_qemu.c
index e623418..dc7351f 100644
--- a/gps/gps_qemu.c
+++ b/gps/gps_qemu.c
@@ -240,7 +240,6 @@
if (cb != NULL && r->fix.flags != 0) {
D("%s: sending latest fix to new callback", __FUNCTION__);
r->callback( &r->fix );
- r->fix.flags = 0;
}
}
@@ -466,6 +465,7 @@
Token tok_altitude = nmea_tokenizer_get(tzer,9);
Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
+ r->fix.flags = 0;
nmea_reader_update_time(r, tok_time);
nmea_reader_update_latlong(r, tok_latitude,
tok_latitudeHemi.p[0],
@@ -489,6 +489,7 @@
D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
if (tok_fixStatus.p[0] == 'A')
{
+ r->fix.flags = 0;
nmea_reader_update_date( r, tok_date, tok_time );
nmea_reader_update_latlong( r, tok_latitude,
@@ -536,7 +537,6 @@
#endif
if (r->callback) {
r->callback( &r->fix );
- r->fix.flags = 0;
}
else {
D("no callback, keeping data until needed !");
@@ -688,6 +688,17 @@
int started = 0;
int gps_fd = state->fd;
int control_fd = state->control[1];
+ GpsStatus gps_status;
+ gps_status.size = sizeof(gps_status);
+ GpsSvStatus gps_sv_status;
+ memset(&gps_sv_status, 0, sizeof(gps_sv_status));
+ gps_sv_status.size = sizeof(gps_sv_status);
+ gps_sv_status.num_svs = 1;
+ gps_sv_status.sv_list[0].size = sizeof(gps_sv_status.sv_list[0]);
+ gps_sv_status.sv_list[0].prn = 17;
+ gps_sv_status.sv_list[0].snr = 60.0;
+ gps_sv_status.sv_list[0].elevation = 30.0;
+ gps_sv_status.sv_list[0].azimuth = 30.0;
nmea_reader_init( reader );
@@ -702,7 +713,15 @@
struct epoll_event events[2];
int ne, nevents;
- nevents = epoll_wait( epoll_fd, events, 2, -1 );
+ int timeout = -1;
+ if (gps_status.status == GPS_STATUS_SESSION_BEGIN) {
+ timeout = 10 * 1000; // 10 seconds
+ }
+ nevents = epoll_wait( epoll_fd, events, 2, timeout );
+ if (state->callbacks.sv_status_cb) {
+ state->callbacks.sv_status_cb(&gps_sv_status);
+ }
+ // update satilite info
if (nevents < 0) {
if (errno != EINTR)
ALOGE("epoll_wait() unexpected error: %s", strerror(errno));
@@ -735,6 +754,10 @@
D("gps thread starting location_cb=%p", state->callbacks.location_cb);
started = 1;
nmea_reader_set_callback( reader, state->callbacks.location_cb );
+ gps_status.status = GPS_STATUS_SESSION_BEGIN;
+ if (state->callbacks.status_cb) {
+ state->callbacks.status_cb(&gps_status);
+ }
}
}
else if (cmd == CMD_STOP) {
@@ -742,6 +765,10 @@
D("gps thread stopping");
started = 0;
nmea_reader_set_callback( reader, NULL );
+ gps_status.status = GPS_STATUS_SESSION_END;
+ if (state->callbacks.status_cb) {
+ state->callbacks.status_cb(&gps_status);
+ }
}
}
}
@@ -807,6 +834,16 @@
state->callbacks = *callbacks;
+ // Explicitly initialize capabilities
+ state->callbacks.set_capabilities_cb(0);
+
+
+ // Setup system info, we are pre 2016 hardware.
+ GnssSystemInfo sysinfo;
+ sysinfo.size = sizeof(GnssSystemInfo);
+ sysinfo.year_of_hw = 2015;
+ state->callbacks.set_system_info_cb(&sysinfo);
+
D("gps state initialized");
return;
diff --git a/hwcomposer/Android.mk b/hwcomposer/Android.mk
index 5f20c58..55c66bb 100644
--- a/hwcomposer/Android.mk
+++ b/hwcomposer/Android.mk
@@ -17,6 +17,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
emulator_hwcomposer_shared_libraries := \
liblog \
libutils \
@@ -54,6 +55,7 @@
# RANCHU BUILD
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
LOCAL_SRC_FILES := $(emulator_hwcomposer_src_files)
LOCAL_CFLAGS := $(emulator_hwcomposer_cflags)
diff --git a/include/qemu_pipe.h b/include/qemu_pipe.h
index d76ba3b..1056bb3 100644
--- a/include/qemu_pipe.h
+++ b/include/qemu_pipe.h
@@ -81,7 +81,7 @@
{
char buff[256];
int buffLen;
- int fd, ret;
+ int fd;
if (pipeName == NULL || pipeName[0] == '\0') {
errno = EINVAL;
diff --git a/include/qemud.h b/include/qemud.h
index 71ec3bf..c6327ee 100644
--- a/include/qemud.h
+++ b/include/qemud.h
@@ -36,7 +36,10 @@
* that sends its formatted string argument(s) to the log.
* If not, ignore the traces.
*/
-# define D(...) ((void)0)
+#ifndef D
+# define D(...) do{}while(0)
+#endif
+
static __inline__ int
qemud_channel_open(const char* name)
@@ -108,7 +111,7 @@
qemud_channel_recv(int fd, void* msg, int msgsize)
{
char header[5];
- int size, avail;
+ int size;
if (!ReadFully(fd, header, 4)) {
D("can't read qemud frame header: %s", strerror(errno));
diff --git a/init.goldfish.rc b/init.goldfish.rc
index b1613a4..db958d7 100644
--- a/init.goldfish.rc
+++ b/init.goldfish.rc
@@ -112,7 +112,7 @@
user system
service bugreport /system/bin/dumpstate -d -p -B \
- -o /data/data/com.android.shell/files/bugreports/bugreport
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
class main
disabled
oneshot
diff --git a/init.ranchu-net.sh b/init.ranchu-net.sh
index e4347d3..a14ab18 100755
--- a/init.ranchu-net.sh
+++ b/init.ranchu-net.sh
@@ -1,4 +1,4 @@
-#!/system/bin/sh
+#!/vendor/bin/sh
# Setup networking when boot starts
ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up
diff --git a/init.ranchu.rc b/init.ranchu.rc
index c9abe1d..c3cc065 100644
--- a/init.ranchu.rc
+++ b/init.ranchu.rc
@@ -12,6 +12,7 @@
on post-fs-data
setprop vold.post_fs_data_done 1
+
on boot
setprop net.eth0.gw 10.0.2.2
setprop net.eth0.dns1 10.0.2.3
@@ -71,13 +72,13 @@
chown root system /sys/power/wake_lock
chown root system /sys/power/wake_unlock
-service ranchu-setup /system/bin/init.ranchu-core.sh
+service ranchu-setup /vendor/bin/init.ranchu-core.sh
class core
user root
group root
oneshot
-service ranchu-net /system/bin/init.ranchu-net.sh
+service ranchu-net /vendor/bin/init.ranchu-net.sh
class late_start
user root
group root wakelock
@@ -89,7 +90,7 @@
# might read them (e.g. surface flinger), so define it in
# class 'core'
#
-service qemu-props /system/bin/qemu-props
+service qemu-props /vendor/bin/qemu-props
class core
user root
group root
@@ -115,7 +116,7 @@
user system
service bugreport /system/bin/dumpstate -d -p -B \
- -o /data/data/com.android.shell/files/bugreports/bugreport
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
class main
disabled
oneshot
diff --git a/keymaster/Android.mk b/keymaster/Android.mk
new file mode 100644
index 0000000..600e32d
--- /dev/null
+++ b/keymaster/Android.mk
@@ -0,0 +1,47 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_MODULE := libgoldfishkeymaster
+LOCAL_SRC_FILES := keymaster_openssl.c
+LOCAL_C_INCLUDES := system/security/keystore \
+ $(LOCAL_PATH)/../include
+LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
+LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder
+LOCAL_MODULE_TAGS := optional
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_SHARED_LIBRARY)
+
+# Emulated keymaster - ranchu build##########################################
+
+include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_MODULE := keystore.ranchu
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := module.cpp
+LOCAL_C_INCLUDES := system/security/keystore
+LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
+LOCAL_SHARED_LIBRARIES := libcrypto liblog libkeystore_binder libgoldfishkeymaster
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
diff --git a/keymaster/keymaster_openssl.c b/keymaster/keymaster_openssl.c
new file mode 100644
index 0000000..69c9572
--- /dev/null
+++ b/keymaster/keymaster_openssl.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <hardware/keymaster_common.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <string.h>
+
+#define LOG_TAG "OpenSSLKeyMaster"
+#include <cutils/log.h>
+
+#ifdef DEBUG
+# define D(...) ALOGD(__VA_ARGS__)
+#else
+# define D(...) ((void)0)
+#endif
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+#include "qemud.h"
+
+#define KEYMASTER_SERVICE_NAME "KeymasterService"
+
+typedef struct qemu_keymaster0_device_t {
+ keymaster0_device_t device; // "inheritance", must be the first member
+ int qchanfd;
+ pthread_mutex_t lock;
+} qemu_keymaster0_device_t;
+
+enum {
+ GenerateKeypair = 0,
+ ImportKeypair,
+ GetKeypairPublic,
+ SignData,
+ VerifyData,
+};
+
+static int32_t unwrap_key_type(const uint8_t* key_blob) {
+ int32_t key_type = 0;
+ const uint8_t* p = key_blob;
+ size_t i;
+ for (i = 0; i < sizeof(key_type); i++) {
+ key_type = (key_type << 8) | *p++;
+ }
+ return key_type;
+}
+
+static int keymaster_fd_write(int fd, const void* buff, int len) {
+ int ret = WriteFully(fd, buff, len);
+ assert(ret);
+ return ret;
+}
+
+static int keymaster_fd_read(int fd, void* buff, int len) {
+ int ret = ReadFully(fd, buff, len);
+ assert(ret);
+ return ret;
+}
+
+static int EVP2EncoderType(int evpType) {
+ switch (evpType) {
+ case 6: // RSA
+ return TYPE_RSA;
+ case 408: // EC:
+ return TYPE_EC;
+ case 116: // DSA:
+ return TYPE_DSA;
+ default:
+ D("Unsupported evp key type %d", evpType);
+ return -1;
+ }
+}
+
+static int gen_param_length(int type, const void* params) {
+ switch (type) {
+ case TYPE_DSA: {
+ keymaster_dsa_keygen_params_t* dsa_params =
+ (keymaster_dsa_keygen_params_t*)params;
+ return 4 + 4 + 4 + 4 + dsa_params->generator_len
+ + dsa_params->prime_p_len
+ + dsa_params->prime_q_len;
+ }
+ case TYPE_EC:
+ return 4;
+ case TYPE_RSA:
+ return 8 + 4;
+ default:
+ D("Unsupported key type %d", type);
+ return -1;
+ }
+}
+
+static int sign_param_length(int type) {
+ switch (type) {
+ case TYPE_DSA:
+ return sizeof(keymaster_digest_algorithm_t);
+ break;
+ case TYPE_EC:
+ return sizeof(keymaster_digest_algorithm_t);
+ break;
+ case TYPE_RSA:
+ return sizeof(keymaster_digest_algorithm_t)
+ + sizeof(keymaster_rsa_padding_t);
+ break;
+ default:
+ D("Unsupported key type %d", type);
+ return -1;
+ }
+}
+
+static void write_gen_param(int fd,
+ const keymaster_keypair_t type,
+ const void* key_params) {
+ switch (type) {
+ case TYPE_DSA: {
+ keymaster_dsa_keygen_params_t* dsa_params =
+ (keymaster_dsa_keygen_params_t*)key_params;
+
+ keymaster_fd_write(fd, (void*)&dsa_params->key_size,
+ sizeof(dsa_params->key_size));
+
+ keymaster_fd_write(fd, (void*)&dsa_params->generator_len,
+ sizeof(dsa_params->generator_len));
+ keymaster_fd_write(fd, (void*)&dsa_params->prime_p_len,
+ sizeof(dsa_params->prime_p_len));
+ keymaster_fd_write(fd, (void*)&dsa_params->prime_q_len,
+ sizeof(dsa_params->prime_q_len));
+
+ keymaster_fd_write(fd, (void*)dsa_params->generator,
+ dsa_params->generator_len);
+ keymaster_fd_write(fd, (void*)dsa_params->prime_p,
+ dsa_params->prime_p_len);
+ keymaster_fd_write(fd, (void*)dsa_params->prime_q,
+ dsa_params->prime_q_len);
+ break;
+ }
+ case TYPE_EC: {
+ keymaster_ec_keygen_params_t* ec_params =
+ (keymaster_ec_keygen_params_t*)key_params;
+ keymaster_fd_write(fd, (void*)&ec_params->field_size,
+ sizeof(ec_params->field_size));
+ break;
+ }
+ case TYPE_RSA: {
+ keymaster_rsa_keygen_params_t* rsa_params =
+ (keymaster_rsa_keygen_params_t*)key_params;
+ keymaster_fd_write(fd, (void*)&rsa_params->modulus_size,
+ sizeof(rsa_params->modulus_size));
+ keymaster_fd_write(fd, (void*)&rsa_params->public_exponent,
+ sizeof(rsa_params->public_exponent));
+ break;
+ }
+ default:
+ D("Unsupported key type %d", type);
+ return;
+ }
+}
+
+static void write_sign_param(int fd,
+ const keymaster_keypair_t type,
+ const void* key_params) {
+ switch (type) {
+ case TYPE_DSA: {
+ keymaster_dsa_sign_params_t* dsa_params =
+ (keymaster_dsa_sign_params_t*)key_params;
+ keymaster_fd_write(fd, (void*)&dsa_params->digest_type,
+ sizeof(dsa_params->digest_type));
+ break;
+ }
+ case TYPE_EC: {
+ keymaster_ec_sign_params_t* ec_params =
+ (keymaster_ec_sign_params_t*)key_params;
+ keymaster_fd_write(fd, (void*)&ec_params->digest_type,
+ sizeof(ec_params->digest_type));
+ break;
+ }
+ case TYPE_RSA: {
+ keymaster_rsa_sign_params_t* rsa_params =
+ (keymaster_rsa_sign_params_t*)key_params;
+ keymaster_fd_write(fd, (void*)&rsa_params->digest_type,
+ sizeof(rsa_params->digest_type));
+ keymaster_fd_write(fd, (void*)&rsa_params->padding_type,
+ sizeof(rsa_params->padding_type));
+ break;
+ }
+ default:
+ D("Unsupported key type %d", type);
+ return;
+ }
+}
+
+static int openssl_generate_keypair(const keymaster0_device_t* device,
+ const keymaster_keypair_t key_type, const void* key_params,
+ uint8_t** key_blob, size_t* key_blob_length) {
+ D("generate keypair");
+ if (key_params == NULL) {
+ ALOGE("key_params == null");
+ return -1;
+ }
+ const uint32_t cmd = GenerateKeypair;
+ int32_t _key_type = (int)key_type;
+ int32_t key_params_len = gen_param_length(key_type, key_params);
+ if (key_params_len < 0) {
+ return -1;
+ }
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
+ pthread_mutex_lock(&qemu_dev->lock);
+ // send
+ const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_type) + sizeof(key_params_len)
+ + key_params_len;
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_type, sizeof(_key_type));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_params_len, sizeof(key_params_len));
+ write_gen_param(qemu_dev->qchanfd, key_type, key_params);
+
+ // receive
+ uint32_t _key_blob_len = 0;
+ int32_t ret;
+ keymaster_fd_read(qemu_dev->qchanfd, &_key_blob_len, sizeof(_key_blob_len));
+ *key_blob_length = _key_blob_len;
+ if (_key_blob_len) {
+ *key_blob = malloc(_key_blob_len);
+ keymaster_fd_read(qemu_dev->qchanfd, *key_blob, _key_blob_len);
+ }
+ keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
+
+ pthread_mutex_unlock(&qemu_dev->lock);
+ return ret;
+}
+
+static int openssl_import_keypair(const keymaster0_device_t* device,
+ const uint8_t* key,
+ const size_t key_length,
+ uint8_t** key_blob,
+ size_t* key_blob_length) {
+ D("import keypair");
+ if (key == NULL) {
+ ALOGW("input key == NULL");
+ return -1;
+ } else if (key_blob == NULL || key_blob_length == NULL) {
+ ALOGW("output key blob or length == NULL");
+ return -1;
+ }
+
+ const uint32_t cmd = ImportKeypair;
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
+ pthread_mutex_lock(&qemu_dev->lock);
+ // send
+ const uint32_t _key_length = (uint32_t)key_length;
+ const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_length) + _key_length;
+
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_length, sizeof(_key_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)key, key_length);
+
+ // receive
+ uint32_t _key_blob_len = 0;
+ int32_t ret;
+ keymaster_fd_read(qemu_dev->qchanfd, &_key_blob_len, sizeof(_key_blob_len));
+ *key_blob_length = _key_blob_len;
+ *key_blob = malloc(_key_blob_len);
+ keymaster_fd_read(qemu_dev->qchanfd, *key_blob, _key_blob_len);
+ keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
+
+ pthread_mutex_unlock(&qemu_dev->lock);
+ return ret;
+}
+
+static int openssl_get_keypair_public(const keymaster0_device_t* device,
+ const uint8_t* key_blob, const size_t key_blob_length,
+ uint8_t** x509_data, size_t* x509_data_length) {
+ D("get keypair public");
+ if (x509_data == NULL || x509_data_length == NULL) {
+ ALOGW("output public key buffer == NULL");
+ return -1;
+ }
+
+ const uint32_t cmd = GetKeypairPublic;
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
+ pthread_mutex_lock(&qemu_dev->lock);
+ // send
+ const uint32_t _key_blob_length = (uint32_t)key_blob_length;
+ const uint64_t cmdLen = sizeof(cmd) + sizeof(_key_blob_length) +
+ _key_blob_length;
+
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
+
+ // receive
+ uint32_t _x509_data_length = 0;
+ int32_t ret;
+ keymaster_fd_read(qemu_dev->qchanfd, &_x509_data_length,
+ sizeof(_x509_data_length));
+ *x509_data_length = _x509_data_length;
+ if (_x509_data_length) {
+ *x509_data = malloc(_x509_data_length);
+ keymaster_fd_read(qemu_dev->qchanfd, *x509_data, _x509_data_length);
+ } else {
+ *x509_data = NULL;
+ }
+ keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
+
+ pthread_mutex_unlock(&qemu_dev->lock);
+ return ret;
+}
+
+static int openssl_sign_data(const keymaster0_device_t* device, const void* params,
+ const uint8_t* key_blob, const size_t key_blob_length,
+ const uint8_t* data, const size_t data_length,
+ uint8_t** signed_data, size_t* signed_data_length) {
+ D("sign data");
+ if (signed_data == NULL || signed_data_length == NULL) {
+ ALOGW("output signature buffer == NULL");
+ return -1;
+ }
+
+ int32_t key_type = EVP2EncoderType(unwrap_key_type(key_blob));
+ int32_t params_len = sign_param_length(key_type);
+ if (params_len < 0) {
+ return -1;
+ }
+
+ const uint32_t cmd = SignData;
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
+ pthread_mutex_lock(&qemu_dev->lock);
+ // send
+ const uint32_t _key_blob_length = (uint32_t)key_blob_length;
+ const uint32_t _data_length = (uint32_t)data_length;
+ const uint64_t cmdLen = sizeof(cmd) + sizeof(key_type) + sizeof(params_len) + params_len +
+ sizeof(_key_blob_length) + _key_blob_length +
+ sizeof(_data_length) + _data_length;
+
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_type, sizeof(key_type));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)¶ms_len, sizeof(params_len));
+ write_sign_param(qemu_dev->qchanfd, key_type, params);
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_data_length, sizeof(_data_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)data, _data_length);
+
+ // receive
+ uint32_t _signed_data_length = 0;
+ int32_t ret;
+ keymaster_fd_read(qemu_dev->qchanfd, &_signed_data_length,
+ sizeof(_signed_data_length));
+ *signed_data_length = _signed_data_length;
+ if (_signed_data_length) {
+ *signed_data = malloc(_signed_data_length);
+ keymaster_fd_read(qemu_dev->qchanfd, *signed_data, _signed_data_length);
+ }
+ keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
+
+ pthread_mutex_unlock(&qemu_dev->lock);
+ return ret;
+}
+
+static int openssl_verify_data(const keymaster0_device_t* device, const void* params,
+ const uint8_t* key_blob, const size_t key_blob_length,
+ const uint8_t* signed_data, const size_t signed_data_length,
+ const uint8_t* signature, const size_t signature_length) {
+ D("verify data");
+ if (signed_data == NULL || signature == NULL) {
+ ALOGW("data or signature buffers == NULL");
+ return -1;
+ }
+
+ int32_t key_type = EVP2EncoderType(unwrap_key_type(key_blob));
+ int32_t params_len = sign_param_length(key_type);
+ if (params_len < 0) {
+ return -1;
+ }
+
+ const uint32_t cmd = VerifyData;
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)device;
+ pthread_mutex_lock(&qemu_dev->lock);
+ // send
+ const uint32_t _key_blob_length = (uint32_t)key_blob_length;
+ const uint32_t _signed_data_length = (uint32_t)signed_data_length;
+ const uint32_t _signature_length = (uint32_t)signature_length;
+ const uint64_t cmdLen = sizeof(cmd) + sizeof(key_type) + sizeof(params_len) + params_len +
+ sizeof(_key_blob_length) + _key_blob_length +
+ sizeof(_signed_data_length) + _signed_data_length +
+ sizeof(_signature_length) + _signature_length;
+
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmdLen, sizeof(cmdLen));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&cmd, sizeof(cmd));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&key_type, sizeof(key_type));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)¶ms_len, sizeof(params_len));
+ write_sign_param(qemu_dev->qchanfd, key_type, params);
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_key_blob_length, sizeof(_key_blob_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)key_blob, _key_blob_length);
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_signed_data_length, sizeof(_signed_data_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)signed_data, _signed_data_length);
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)&_signature_length, sizeof(_signature_length));
+ keymaster_fd_write(qemu_dev->qchanfd, (void*)signature, _signature_length);
+
+ // receive
+ int32_t ret;
+ keymaster_fd_read(qemu_dev->qchanfd, &ret, sizeof(ret));
+
+ pthread_mutex_unlock(&qemu_dev->lock);
+ return ret;
+}
+
+/* Close an opened OpenSSL instance */
+static int openssl_close(hw_device_t* dev) {
+ D("close device");
+ qemu_keymaster0_device_t* qemu_dev = (qemu_keymaster0_device_t*)dev;
+ pthread_mutex_destroy(&qemu_dev->lock);
+ close(qemu_dev->qchanfd);
+ free(qemu_dev);
+ return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int openssl_open(const hw_module_t* module, const char* name,
+ hw_device_t** device) {
+ D("open device");
+ if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
+ return -EINVAL;
+
+ qemu_keymaster0_device_t* qemu_dev = calloc(1, sizeof(qemu_keymaster0_device_t));
+ if (qemu_dev == NULL)
+ return -ENOMEM;
+ keymaster0_device_t* dev = (keymaster0_device_t*)qemu_dev;
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 1;
+ dev->common.module = (struct hw_module_t*)module;
+ dev->common.close = openssl_close;
+
+ dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_DSA |
+ KEYMASTER_SUPPORTS_EC;
+
+ dev->generate_keypair = openssl_generate_keypair;
+ dev->import_keypair = openssl_import_keypair;
+ dev->get_keypair_public = openssl_get_keypair_public;
+ dev->delete_keypair = NULL;
+ dev->delete_all = NULL;
+ dev->sign_data = openssl_sign_data;
+ dev->verify_data = openssl_verify_data;
+
+ // set up the pipe
+ qemu_dev->qchanfd = qemu_pipe_open(KEYMASTER_SERVICE_NAME);
+ if (qemu_dev->qchanfd < 0) {
+ ALOGE("keymaster: failed to get host connection while opening %s\n", name);
+ free(qemu_dev);
+ return -EIO;
+ }
+ pthread_mutex_init(&qemu_dev->lock, NULL);
+
+ *device = &dev->common;
+
+ return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+ .open = openssl_open,
+};
+
+struct keystore_module goldfishkeymaster_module __attribute__((visibility("default"))) = {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = KEYMASTER_MODULE_API_VERSION_0_2,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = KEYSTORE_HARDWARE_MODULE_ID,
+ .name = "Keymaster OpenSSL HAL",
+ .author = "The Android Open Source Project",
+ .methods = &keystore_module_methods,
+ .dso = 0,
+ .reserved = {},
+ },
+};
diff --git a/keymaster/module.cpp b/keymaster/module.cpp
new file mode 100644
index 0000000..97a15cc
--- /dev/null
+++ b/keymaster/module.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <keystore/keystore.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+
+extern struct keystore_module goldfishkeymaster_module;
+struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
+ = goldfishkeymaster_module;
diff --git a/lights/Android.mk b/lights/Android.mk
index dadcabc..41ab150 100644
--- a/lights/Android.mk
+++ b/lights/Android.mk
@@ -17,11 +17,12 @@
# HAL module implemenation, not prelinked and stored in
# hw/<LIGHTS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
+LOCAL_RENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_C_INC := lights_qemu.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_SRC_FILES := lights_qemu.c
-LOCAL_MODULE := lights.goldfish
+LOCAL_MODULE := lights.ranchu
LOCAL_CFLAGS += -DLIGHT_BACKLIGHT
include $(BUILD_SHARED_LIBRARY)
diff --git a/manifest.xml b/manifest.xml
index 7d359a0..2b7e0d4 100644
--- a/manifest.xml
+++ b/manifest.xml
@@ -1,17 +1,71 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.drm</name>
- <transport arch="32">passthrough</transport>
- <impl level="generic"></impl>
+ <transport>hwbinder</transport>
<version>1.0</version>
- <!-- TODO(b/36371166): change to default -->
<interface>
<name>ICryptoFactory</name>
- <instance>crypto</instance>
+ <instance>default</instance>
+ <instance>widevine</instance>
</interface>
<interface>
<name>IDrmFactory</name>
- <instance>drm</instance>
+ <instance>default</instance>
+ <instance>widevine</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.soundtrigger</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>ISoundTriggerHw</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.audio.effect</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IEffectsFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.biometrics.fingerprint</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IBiometricsFingerprint</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.configstore</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ISurfaceFlingerConfigs</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.audio</name>
+ <transport>hwbinder</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IDevicesFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.keymaster</name>
+ <transport>hwbinder</transport>
+ <version>3.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>default</instance>
</interface>
</hal>
<hal format="hidl">
@@ -24,6 +78,24 @@
</interface>
</hal>
<hal format="hidl">
+ <name>android.hardware.graphics.mapper</name>
+ <transport arch="32+64">passthrough</transport>
+ <version>2.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.graphics.composer</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
<name>android.hardware.power</name>
<transport>hwbinder</transport>
<version>1.0</version>
@@ -32,4 +104,83 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="hidl">
+ <name>android.hardware.broadcastradio</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IBroadcastRadioFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.camera.provider</name>
+ <transport>hwbinder</transport>
+ <version>2.4</version>
+ <interface>
+ <name>ICameraProvider</name>
+ <instance>legacy/0</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.sensors</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.gatekeeper</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IGatekeeper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.gnss</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IGnss</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.media.omx</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IOmx</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IOmxStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.radio.deprecated</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IOemHook</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.radio</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <sepolicy>
+ <version>10000.0</version>
+ </sepolicy>
</manifest>
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
index fb7c56f..e7923e4 100644
--- a/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -30,4 +30,10 @@
<!-- Set to true to add links to Cell Broadcast app from Settings and MMS app. -->
<bool name="config_cellBroadcastAppLinks">true</bool>
+ <!-- MMS user agent string -->
+ <string name="config_mms_user_agent" translatable="false">GoldfishNexus</string>
+
+ <!-- MMS user agent prolfile url -->
+ <string name="config_mms_user_agent_profile_url" translatable="false">http://gsm.lge.com/html/gsm/Nexus5-M3.xml</string>
+
</resources>
diff --git a/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
index 56fbf89..6602627 100644
--- a/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
+++ b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
@@ -18,9 +18,7 @@
-->
<resources>
- <!-- cannot set this to true because O-CTS is testing the keyguard b/37465076
<bool name="def_lockscreen_disabled">true</bool>
- -->
<!-- Allow users to use both the on-screen keyboard, as well as a real
keyboard -->
diff --git a/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml b/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml
new file mode 100644
index 0000000..f5034ed
--- /dev/null
+++ b/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<!-- This is a place for vendor-specific config values. The format and
+ filtering rules are the same as those in carrier_config*.xml files. This
+ file is read after any specific config file from the assets folder, so it
+ must use explicit filters for MCC ad MNC if that is desired. -->
+
+<carrier_config_list>
+<carrier_config>
+<boolean name="enabledMMS" value="false"/>
+</carrier_config>
+</carrier_config_list>
diff --git a/power/Android.mk b/power/Android.mk
index 3839088..a4d4a2c 100644
--- a/power/Android.mk
+++ b/power/Android.mk
@@ -19,6 +19,7 @@
# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_CFLAGS += -DQEMU_HARDWARE
LOCAL_SHARED_LIBRARIES := liblog libcutils
@@ -30,6 +31,7 @@
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_CFLAGS += -DQEMU_HARDWARE
LOCAL_SHARED_LIBRARIES := liblog libcutils
diff --git a/qemu-props/Android.mk b/qemu-props/Android.mk
index d2af64d..b1b14db 100644
--- a/qemu-props/Android.mk
+++ b/qemu-props/Android.mk
@@ -22,6 +22,7 @@
# to setup various system properties sent by the emulator program.
#
include $(CLEAR_VARS)
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE := qemu-props
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_SRC_FILES := qemu-props.c
diff --git a/qemud/Android.mk b/qemud/Android.mk
deleted file mode 100644
index 30ee5eb..0000000
--- a/qemud/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2008 The Android Open Source Project
-
-# We're moving the emulator-specific platform libs to
-# development.git/tools/emulator/. The following test is to ensure
-# smooth builds even if the tree contains both versions.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- qemud.c
-
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils liblog
-
-LOCAL_MODULE:= qemud
-
-include $(BUILD_EXECUTABLE)
diff --git a/qemud/qemud.c b/qemud/qemud.c
deleted file mode 100644
index 3d18893..0000000
--- a/qemud/qemud.c
+++ /dev/null
@@ -1,1720 +0,0 @@
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <termios.h>
-#include <unistd.h>
-#include <cutils/sockets.h>
-
-/*
- * the qemud daemon program is only used within Android as a bridge
- * between the emulator program and the emulated system. it really works as
- * a simple stream multiplexer that works as follows:
- *
- * - qemud is started by init following instructions in
- * /system/etc/init.goldfish.rc (i.e. it is never started on real devices)
- *
- * - qemud communicates with the emulator program through a single serial
- * port, whose name is passed through a kernel boot parameter
- * (e.g. android.qemud=ttyS1)
- *
- * - qemud binds one unix local stream socket (/dev/socket/qemud, created
- * by init through /system/etc/init.goldfish.rc).
- *
- *
- * emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1
- * |
- * +--> client2
- *
- * - the special channel index 0 is used by the emulator and qemud only.
- * other channel numbers correspond to clients. More specifically,
- * connection are created like this:
- *
- * * the client connects to /dev/socket/qemud
- *
- * * the client sends the service name through the socket, as
- * <service-name>
- *
- * * qemud creates a "Client" object internally, assigns it an
- * internal unique channel number > 0, then sends a connection
- * initiation request to the emulator (i.e. through channel 0):
- *
- * connect:<id>:<name>
- *
- * where <name> is the service name, and <id> is a 2-hexchar
- * number corresponding to the channel number.
- *
- * * in case of success, the emulator responds through channel 0
- * with:
- *
- * ok:connect:<id>
- *
- * after this, all messages between the client and the emulator
- * are passed in pass-through mode.
- *
- * * if the emulator refuses the service connection, it will
- * send the following through channel 0:
- *
- * ko:connect:<id>:reason-for-failure
- *
- * * If the client closes the connection, qemud sends the following
- * to the emulator:
- *
- * disconnect:<id>
- *
- * The same message is the opposite direction if the emulator
- * chooses to close the connection.
- *
- * * any command sent through channel 0 to the emulator that is
- * not properly recognized will be answered by:
- *
- * ko:unknown command
- *
- *
- * Internally, the daemon maintains a "Client" object for each client
- * connection (i.e. accepting socket connection).
- */
-
-/* name of the single control socket used by the daemon */
-#define CONTROL_SOCKET_NAME "qemud"
-
-#define DEBUG 0
-#define T_ACTIVE 0 /* set to 1 to dump traffic */
-
-#if DEBUG
-# define LOG_TAG "qemud"
-# include <cutils/log.h>
-# define D(...) ALOGD(__VA_ARGS__)
-#else
-# define D(...) ((void)0)
-# define T(...) ((void)0)
-#endif
-
-#if T_ACTIVE
-# define T(...) D(__VA_ARGS__)
-#else
-# define T(...) ((void)0)
-#endif
-
-/** UTILITIES
- **/
-
-static void
-fatal( const char* fmt, ... )
-{
- va_list args;
- va_start(args, fmt);
- fprintf(stderr, "PANIC: ");
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n" );
- va_end(args);
- exit(1);
-}
-
-static void*
-xalloc( size_t sz )
-{
- void* p;
-
- if (sz == 0)
- return NULL;
-
- p = malloc(sz);
- if (p == NULL)
- fatal( "not enough memory" );
-
- return p;
-}
-
-#define xnew(p) (p) = xalloc(sizeof(*(p)))
-
-static void*
-xalloc0( size_t sz )
-{
- void* p = xalloc(sz);
- memset( p, 0, sz );
- return p;
-}
-
-#define xnew0(p) (p) = xalloc0(sizeof(*(p)))
-
-#define xfree(p) (free((p)), (p) = NULL)
-
-static void*
-xrealloc( void* block, size_t size )
-{
- void* p = realloc( block, size );
-
- if (p == NULL && size > 0)
- fatal( "not enough memory" );
-
- return p;
-}
-
-#define xrenew(p,count) (p) = xrealloc((p),sizeof(*(p))*(count))
-
-static int
-hex2int( const uint8_t* data, int len )
-{
- int result = 0;
- while (len > 0) {
- int c = *data++;
- unsigned d;
-
- result <<= 4;
- do {
- d = (unsigned)(c - '0');
- if (d < 10)
- break;
-
- d = (unsigned)(c - 'a');
- if (d < 6) {
- d += 10;
- break;
- }
-
- d = (unsigned)(c - 'A');
- if (d < 6) {
- d += 10;
- break;
- }
-
- return -1;
- }
- while (0);
-
- result |= d;
- len -= 1;
- }
- return result;
-}
-
-
-static void
-int2hex( int value, uint8_t* to, int width )
-{
- int nn = 0;
- static const char hexchars[16] = "0123456789abcdef";
-
- for ( --width; width >= 0; width--, nn++ ) {
- to[nn] = hexchars[(value >> (width*4)) & 15];
- }
-}
-
-static int
-fd_read(int fd, void* to, int len)
-{
- int ret;
-
- do {
- ret = read(fd, to, len);
- } while (ret < 0 && errno == EINTR);
-
- return ret;
-}
-
-static int
-fd_write(int fd, const void* from, int len)
-{
- int ret;
-
- do {
- ret = write(fd, from, len);
- } while (ret < 0 && errno == EINTR);
-
- return ret;
-}
-
-static void
-fd_setnonblock(int fd)
-{
- int ret, flags;
-
- do {
- flags = fcntl(fd, F_GETFD);
- } while (flags < 0 && errno == EINTR);
-
- if (flags < 0) {
- fatal( "%s: could not get flags for fd %d: %s",
- __FUNCTION__, fd, strerror(errno) );
- }
-
- do {
- ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0) {
- fatal( "%s: could not set fd %d to non-blocking: %s",
- __FUNCTION__, fd, strerror(errno) );
- }
-}
-
-
-static int
-fd_accept(int fd)
-{
- struct sockaddr from;
- socklen_t fromlen = sizeof(from);
- int ret;
-
- do {
- ret = accept(fd, &from, &fromlen);
- } while (ret < 0 && errno == EINTR);
-
- return ret;
-}
-
-/** FD EVENT LOOP
- **/
-
-/* A Looper object is used to monitor activity on one or more
- * file descriptors (e.g sockets).
- *
- * - call looper_add() to register a function that will be
- * called when events happen on the file descriptor.
- *
- * - call looper_enable() or looper_disable() to enable/disable
- * the set of monitored events for a given file descriptor.
- *
- * - call looper_del() to unregister a file descriptor.
- * this does *not* close the file descriptor.
- *
- * Note that you can only provide a single function to handle
- * all events related to a given file descriptor.
-
- * You can call looper_enable/_disable/_del within a function
- * callback.
- */
-
-/* the current implementation uses Linux's epoll facility
- * the event mask we use are simply combinations of EPOLLIN
- * EPOLLOUT, EPOLLHUP and EPOLLERR
- */
-#include <sys/epoll.h>
-
-#define MAX_CHANNELS 16
-#define MAX_EVENTS (MAX_CHANNELS+1) /* each channel + the serial fd */
-
-/* the event handler function type, 'user' is a user-specific
- * opaque pointer passed to looper_add().
- */
-typedef void (*EventFunc)( void* user, int events );
-
-/* bit flags for the LoopHook structure.
- *
- * HOOK_PENDING means that an event happened on the
- * corresponding file descriptor.
- *
- * HOOK_CLOSING is used to delay-close monitored
- * file descriptors.
- */
-enum {
- HOOK_PENDING = (1 << 0),
- HOOK_CLOSING = (1 << 1),
-};
-
-/* A LoopHook structure is used to monitor a given
- * file descriptor and record its event handler.
- */
-typedef struct {
- int fd;
- int wanted; /* events we are monitoring */
- int events; /* events that occured */
- int state; /* see HOOK_XXX constants */
- void* ev_user; /* user-provided handler parameter */
- EventFunc ev_func; /* event handler callback */
-} LoopHook;
-
-/* Looper is the main object modeling a looper object
- */
-typedef struct {
- int epoll_fd;
- int num_fds;
- int max_fds;
- struct epoll_event* events;
- LoopHook* hooks;
-} Looper;
-
-/* initialize a looper object */
-static void
-looper_init( Looper* l )
-{
- l->epoll_fd = epoll_create(4);
- l->num_fds = 0;
- l->max_fds = 0;
- l->events = NULL;
- l->hooks = NULL;
-}
-
-/* finalize a looper object */
-static void
-looper_done( Looper* l )
-{
- xfree(l->events);
- xfree(l->hooks);
- l->max_fds = 0;
- l->num_fds = 0;
-
- close(l->epoll_fd);
- l->epoll_fd = -1;
-}
-
-/* return the LoopHook corresponding to a given
- * monitored file descriptor, or NULL if not found
- */
-static LoopHook*
-looper_find( Looper* l, int fd )
-{
- LoopHook* hook = l->hooks;
- LoopHook* end = hook + l->num_fds;
-
- for ( ; hook < end; hook++ ) {
- if (hook->fd == fd)
- return hook;
- }
- return NULL;
-}
-
-/* grow the arrays in the looper object */
-static void
-looper_grow( Looper* l )
-{
- int old_max = l->max_fds;
- int new_max = old_max + (old_max >> 1) + 4;
- int n;
-
- xrenew( l->events, new_max );
- xrenew( l->hooks, new_max );
- l->max_fds = new_max;
-
- /* now change the handles to all events */
- for (n = 0; n < l->num_fds; n++) {
- struct epoll_event ev;
- LoopHook* hook = l->hooks + n;
-
- ev.events = hook->wanted;
- ev.data.ptr = hook;
- epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, hook->fd, &ev );
- }
-}
-
-/* register a file descriptor and its event handler.
- * no event mask will be enabled
- */
-static void
-looper_add( Looper* l, int fd, EventFunc func, void* user )
-{
- struct epoll_event ev;
- LoopHook* hook;
-
- if (l->num_fds >= l->max_fds)
- looper_grow(l);
-
- hook = l->hooks + l->num_fds;
-
- hook->fd = fd;
- hook->ev_user = user;
- hook->ev_func = func;
- hook->state = 0;
- hook->wanted = 0;
- hook->events = 0;
-
- fd_setnonblock(fd);
-
- ev.events = 0;
- ev.data.ptr = hook;
- epoll_ctl( l->epoll_fd, EPOLL_CTL_ADD, fd, &ev );
-
- l->num_fds += 1;
-}
-
-/* unregister a file descriptor and its event handler
- */
-static void
-looper_del( Looper* l, int fd )
-{
- LoopHook* hook = looper_find( l, fd );
-
- if (!hook) {
- D( "%s: invalid fd: %d", __FUNCTION__, fd );
- return;
- }
- /* don't remove the hook yet */
- hook->state |= HOOK_CLOSING;
-
- epoll_ctl( l->epoll_fd, EPOLL_CTL_DEL, fd, NULL );
-}
-
-/* enable monitoring of certain events for a file
- * descriptor. This adds 'events' to the current
- * event mask
- */
-static void
-looper_enable( Looper* l, int fd, int events )
-{
- LoopHook* hook = looper_find( l, fd );
-
- if (!hook) {
- D("%s: invalid fd: %d", __FUNCTION__, fd );
- return;
- }
-
- if (events & ~hook->wanted) {
- struct epoll_event ev;
-
- hook->wanted |= events;
- ev.events = hook->wanted;
- ev.data.ptr = hook;
-
- epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev );
- }
-}
-
-/* disable monitoring of certain events for a file
- * descriptor. This ignores events that are not
- * currently enabled.
- */
-static void
-looper_disable( Looper* l, int fd, int events )
-{
- LoopHook* hook = looper_find( l, fd );
-
- if (!hook) {
- D("%s: invalid fd: %d", __FUNCTION__, fd );
- return;
- }
-
- if (events & hook->wanted) {
- struct epoll_event ev;
-
- hook->wanted &= ~events;
- ev.events = hook->wanted;
- ev.data.ptr = hook;
-
- epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev );
- }
-}
-
-/* wait until an event occurs on one of the registered file
- * descriptors. Only returns in case of error !!
- */
-static void
-looper_loop( Looper* l )
-{
- for (;;) {
- int n, count;
-
- do {
- count = epoll_wait( l->epoll_fd, l->events, l->num_fds, -1 );
- } while (count < 0 && errno == EINTR);
-
- if (count < 0) {
- D("%s: error: %s", __FUNCTION__, strerror(errno) );
- return;
- }
-
- if (count == 0) {
- D("%s: huh ? epoll returned count=0", __FUNCTION__);
- continue;
- }
-
- /* mark all pending hooks */
- for (n = 0; n < count; n++) {
- LoopHook* hook = l->events[n].data.ptr;
- hook->state = HOOK_PENDING;
- hook->events = l->events[n].events;
- }
-
- /* execute hook callbacks. this may change the 'hooks'
- * and 'events' array, as well as l->num_fds, so be careful */
- for (n = 0; n < l->num_fds; n++) {
- LoopHook* hook = l->hooks + n;
- if (hook->state & HOOK_PENDING) {
- hook->state &= ~HOOK_PENDING;
- hook->ev_func( hook->ev_user, hook->events );
- }
- }
-
- /* now remove all the hooks that were closed by
- * the callbacks */
- for (n = 0; n < l->num_fds;) {
- struct epoll_event ev;
- LoopHook* hook = l->hooks + n;
-
- if (!(hook->state & HOOK_CLOSING)) {
- n++;
- continue;
- }
-
- hook[0] = l->hooks[l->num_fds-1];
- l->num_fds -= 1;
- ev.events = hook->wanted;
- ev.data.ptr = hook;
- epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, hook->fd, &ev );
- }
- }
-}
-
-#if T_ACTIVE
-char*
-quote( const void* data, int len )
-{
- const char* p = data;
- const char* end = p + len;
- int count = 0;
- int phase = 0;
- static char* buff = NULL;
-
- for (phase = 0; phase < 2; phase++) {
- if (phase != 0) {
- xfree(buff);
- buff = xalloc(count+1);
- }
- count = 0;
- for (p = data; p < end; p++) {
- int c = *p;
-
- if (c == '\\') {
- if (phase != 0) {
- buff[count] = buff[count+1] = '\\';
- }
- count += 2;
- continue;
- }
-
- if (c >= 32 && c < 127) {
- if (phase != 0)
- buff[count] = c;
- count += 1;
- continue;
- }
-
-
- if (c == '\t') {
- if (phase != 0) {
- memcpy(buff+count, "<TAB>", 5);
- }
- count += 5;
- continue;
- }
- if (c == '\n') {
- if (phase != 0) {
- memcpy(buff+count, "<LN>", 4);
- }
- count += 4;
- continue;
- }
- if (c == '\r') {
- if (phase != 0) {
- memcpy(buff+count, "<CR>", 4);
- }
- count += 4;
- continue;
- }
-
- if (phase != 0) {
- buff[count+0] = '\\';
- buff[count+1] = 'x';
- buff[count+2] = "0123456789abcdef"[(c >> 4) & 15];
- buff[count+3] = "0123456789abcdef"[ (c) & 15];
- }
- count += 4;
- }
- }
- buff[count] = 0;
- return buff;
-}
-#endif /* T_ACTIVE */
-
-/** PACKETS
- **
- ** We need a way to buffer data before it can be sent to the
- ** corresponding file descriptor. We use linked list of Packet
- ** objects to do this.
- **/
-
-typedef struct Packet Packet;
-
-#define MAX_PAYLOAD 4000
-
-struct Packet {
- Packet* next;
- int len;
- int channel;
- uint8_t data[ MAX_PAYLOAD ];
-};
-
-/* we expect to alloc/free a lot of packets during
- * operations so use a single linked list of free packets
- * to keep things speedy and simple.
- */
-static Packet* _free_packets;
-
-/* Allocate a packet */
-static Packet*
-packet_alloc(void)
-{
- Packet* p = _free_packets;
- if (p != NULL) {
- _free_packets = p->next;
- } else {
- xnew(p);
- }
- p->next = NULL;
- p->len = 0;
- p->channel = -1;
- return p;
-}
-
-/* Release a packet. This takes the address of a packet
- * pointer that will be set to NULL on exit (avoids
- * referencing dangling pointers in case of bugs)
- */
-static void
-packet_free( Packet* *ppacket )
-{
- Packet* p = *ppacket;
- if (p) {
- p->next = _free_packets;
- _free_packets = p;
- *ppacket = NULL;
- }
-}
-
-/** PACKET RECEIVER
- **
- ** Simple abstraction for something that can receive a packet
- ** from a FDHandler (see below) or something else.
- **
- ** Send a packet to it with 'receiver_post'
- **
- ** Call 'receiver_close' to indicate that the corresponding
- ** packet source was closed.
- **/
-
-typedef void (*PostFunc) ( void* user, Packet* p );
-typedef void (*CloseFunc)( void* user );
-
-typedef struct {
- PostFunc post;
- CloseFunc close;
- void* user;
-} Receiver;
-
-/* post a packet to a receiver. Note that this transfers
- * ownership of the packet to the receiver.
- */
-static __inline__ void
-receiver_post( Receiver* r, Packet* p )
-{
- if (r->post)
- r->post( r->user, p );
- else
- packet_free(&p);
-}
-
-/* tell a receiver the packet source was closed.
- * this will also prevent further posting to the
- * receiver.
- */
-static __inline__ void
-receiver_close( Receiver* r )
-{
- if (r->close) {
- r->close( r->user );
- r->close = NULL;
- }
- r->post = NULL;
-}
-
-
-/** FD HANDLERS
- **
- ** these are smart listeners that send incoming packets to a receiver
- ** and can queue one or more outgoing packets and send them when
- ** possible to the FD.
- **
- ** note that we support clean shutdown of file descriptors,
- ** i.e. we try to send all outgoing packets before destroying
- ** the FDHandler.
- **/
-
-typedef struct FDHandler FDHandler;
-typedef struct FDHandlerList FDHandlerList;
-
-struct FDHandler {
- int fd;
- FDHandlerList* list;
- char closing;
- Receiver receiver[1];
-
- /* queue of outgoing packets */
- int out_pos;
- Packet* out_first;
- Packet** out_ptail;
-
- FDHandler* next;
- FDHandler** pref;
-
-};
-
-struct FDHandlerList {
- /* the looper that manages the fds */
- Looper* looper;
-
- /* list of active FDHandler objects */
- FDHandler* active;
-
- /* list of closing FDHandler objects.
- * these are waiting to push their
- * queued packets to the fd before
- * freeing themselves.
- */
- FDHandler* closing;
-
-};
-
-/* remove a FDHandler from its current list */
-static void
-fdhandler_remove( FDHandler* f )
-{
- f->pref[0] = f->next;
- if (f->next)
- f->next->pref = f->pref;
-}
-
-/* add a FDHandler to a given list */
-static void
-fdhandler_prepend( FDHandler* f, FDHandler** list )
-{
- f->next = list[0];
- f->pref = list;
- list[0] = f;
- if (f->next)
- f->next->pref = &f->next;
-}
-
-/* initialize a FDHandler list */
-static void
-fdhandler_list_init( FDHandlerList* list, Looper* looper )
-{
- list->looper = looper;
- list->active = NULL;
- list->closing = NULL;
-}
-
-
-/* close a FDHandler (and free it). Note that this will not
- * perform a graceful shutdown, i.e. all packets in the
- * outgoing queue will be immediately free.
- *
- * this *will* notify the receiver that the file descriptor
- * was closed.
- *
- * you should call fdhandler_shutdown() if you want to
- * notify the FDHandler that its packet source is closed.
- */
-static void
-fdhandler_close( FDHandler* f )
-{
- /* notify receiver */
- receiver_close(f->receiver);
-
- /* remove the handler from its list */
- fdhandler_remove(f);
-
- /* get rid of outgoing packet queue */
- if (f->out_first != NULL) {
- Packet* p;
- while ((p = f->out_first) != NULL) {
- f->out_first = p->next;
- packet_free(&p);
- }
- }
-
- /* get rid of file descriptor */
- if (f->fd >= 0) {
- looper_del( f->list->looper, f->fd );
- close(f->fd);
- f->fd = -1;
- }
-
- f->list = NULL;
- xfree(f);
-}
-
-/* Ask the FDHandler to cleanly shutdown the connection,
- * i.e. send any pending outgoing packets then auto-free
- * itself.
- */
-static void
-fdhandler_shutdown( FDHandler* f )
-{
- /* prevent later fdhandler_close() to
- * call the receiver's close.
- */
- f->receiver->close = NULL;
-
- if (f->out_first != NULL && !f->closing)
- {
- /* move the handler to the 'closing' list */
- f->closing = 1;
- fdhandler_remove(f);
- fdhandler_prepend(f, &f->list->closing);
- return;
- }
-
- fdhandler_close(f);
-}
-
-/* Enqueue a new packet that the FDHandler will
- * send through its file descriptor.
- */
-static void
-fdhandler_enqueue( FDHandler* f, Packet* p )
-{
- Packet* first = f->out_first;
-
- p->next = NULL;
- f->out_ptail[0] = p;
- f->out_ptail = &p->next;
-
- if (first == NULL) {
- f->out_pos = 0;
- looper_enable( f->list->looper, f->fd, EPOLLOUT );
- }
-}
-
-
-/* FDHandler file descriptor event callback for read/write ops */
-static void
-fdhandler_event( FDHandler* f, int events )
-{
- int len;
-
- /* in certain cases, it's possible to have both EPOLLIN and
- * EPOLLHUP at the same time. This indicates that there is incoming
- * data to read, but that the connection was nonetheless closed
- * by the sender. Be sure to read the data before closing
- * the receiver to avoid packet loss.
- */
-
- if (events & EPOLLIN) {
- Packet* p = packet_alloc();
- int len;
-
- if ((len = fd_read(f->fd, p->data, MAX_PAYLOAD)) < 0) {
- D("%s: can't recv: %s", __FUNCTION__, strerror(errno));
- packet_free(&p);
- } else if (len > 0) {
- p->len = len;
- p->channel = -101; /* special debug value, not used */
- receiver_post( f->receiver, p );
- }
- }
-
- if (events & (EPOLLHUP|EPOLLERR)) {
- /* disconnection */
- D("%s: disconnect on fd %d", __FUNCTION__, f->fd);
- fdhandler_close(f);
- return;
- }
-
- if (events & EPOLLOUT && f->out_first) {
- Packet* p = f->out_first;
- int avail, len;
-
- avail = p->len - f->out_pos;
- if ((len = fd_write(f->fd, p->data + f->out_pos, avail)) < 0) {
- D("%s: can't send: %s", __FUNCTION__, strerror(errno));
- } else {
- f->out_pos += len;
- if (f->out_pos >= p->len) {
- f->out_pos = 0;
- f->out_first = p->next;
- packet_free(&p);
- if (f->out_first == NULL) {
- f->out_ptail = &f->out_first;
- looper_disable( f->list->looper, f->fd, EPOLLOUT );
- }
- }
- }
- }
-}
-
-
-/* Create a new FDHandler that monitors read/writes */
-static FDHandler*
-fdhandler_new( int fd,
- FDHandlerList* list,
- Receiver* receiver )
-{
- FDHandler* f = xalloc0(sizeof(*f));
-
- f->fd = fd;
- f->list = list;
- f->receiver[0] = receiver[0];
- f->out_first = NULL;
- f->out_ptail = &f->out_first;
- f->out_pos = 0;
-
- fdhandler_prepend(f, &list->active);
-
- looper_add( list->looper, fd, (EventFunc) fdhandler_event, f );
- looper_enable( list->looper, fd, EPOLLIN );
-
- return f;
-}
-
-
-/* event callback function to monitor accepts() on server sockets.
- * the convention used here is that the receiver will receive a
- * dummy packet with the new client socket in p->channel
- */
-static void
-fdhandler_accept_event( FDHandler* f, int events )
-{
- if (events & EPOLLIN) {
- /* this is an accept - send a dummy packet to the receiver */
- Packet* p = packet_alloc();
-
- D("%s: accepting on fd %d", __FUNCTION__, f->fd);
- p->data[0] = 1;
- p->len = 1;
- p->channel = fd_accept(f->fd);
- if (p->channel < 0) {
- D("%s: accept failed ?: %s", __FUNCTION__, strerror(errno));
- packet_free(&p);
- return;
- }
- receiver_post( f->receiver, p );
- }
-
- if (events & (EPOLLHUP|EPOLLERR)) {
- /* disconnecting !! */
- D("%s: closing accept fd %d", __FUNCTION__, f->fd);
- fdhandler_close(f);
- return;
- }
-}
-
-
-/* Create a new FDHandler used to monitor new connections on a
- * server socket. The receiver must expect the new connection
- * fd in the 'channel' field of a dummy packet.
- */
-static FDHandler*
-fdhandler_new_accept( int fd,
- FDHandlerList* list,
- Receiver* receiver )
-{
- FDHandler* f = xalloc0(sizeof(*f));
-
- f->fd = fd;
- f->list = list;
- f->receiver[0] = receiver[0];
-
- fdhandler_prepend(f, &list->active);
-
- looper_add( list->looper, fd, (EventFunc) fdhandler_accept_event, f );
- looper_enable( list->looper, fd, EPOLLIN );
- listen( fd, 5 );
-
- return f;
-}
-
-/** SERIAL CONNECTION STATE
- **
- ** The following is used to handle the framing protocol
- ** used on the serial port connection.
- **/
-
-/* each packet is made of a 6 byte header followed by a payload
- * the header looks like:
- *
- * offset size description
- * 0 2 a 2-byte hex string for the channel number
- * 4 4 a 4-char hex string for the size of the payload
- * 6 n the payload itself
- */
-#define HEADER_SIZE 6
-#define CHANNEL_OFFSET 0
-#define LENGTH_OFFSET 2
-#define CHANNEL_SIZE 2
-#define LENGTH_SIZE 4
-
-#define CHANNEL_CONTROL 0
-
-/* The Serial object receives data from the serial port,
- * extracts the payload size and channel index, then sends
- * the resulting messages as a packet to a generic receiver.
- *
- * You can also use serial_send to send a packet through
- * the serial port.
- */
-typedef struct Serial {
- FDHandler* fdhandler; /* used to monitor serial port fd */
- Receiver receiver[1]; /* send payload there */
- int in_len; /* current bytes in input packet */
- int in_datalen; /* payload size, or 0 when reading header */
- int in_channel; /* extracted channel number */
- Packet* in_packet; /* used to read incoming packets */
-} Serial;
-
-
-/* a callback called when the serial port's fd is closed */
-static void
-serial_fd_close( Serial* s )
-{
- fatal("unexpected serial port close !!");
-}
-
-static void
-serial_dump( Packet* p, const char* funcname )
-{
- T("%s: %03d bytes: '%s'",
- funcname, p->len, quote(p->data, p->len));
-}
-
-/* a callback called when a packet arrives from the serial port's FDHandler.
- *
- * This will essentially parse the header, extract the channel number and
- * the payload size and store them in 'in_datalen' and 'in_channel'.
- *
- * After that, the payload is sent to the receiver once completed.
- */
-static void
-serial_fd_receive( Serial* s, Packet* p )
-{
- int rpos = 0, rcount = p->len;
- Packet* inp = s->in_packet;
- int inpos = s->in_len;
-
- serial_dump( p, __FUNCTION__ );
-
- while (rpos < rcount)
- {
- int avail = rcount - rpos;
-
- /* first, try to read the header */
- if (s->in_datalen == 0) {
- int wanted = HEADER_SIZE - inpos;
- if (avail > wanted)
- avail = wanted;
-
- memcpy( inp->data + inpos, p->data + rpos, avail );
- inpos += avail;
- rpos += avail;
-
- if (inpos == HEADER_SIZE) {
- s->in_datalen = hex2int( inp->data + LENGTH_OFFSET, LENGTH_SIZE );
- s->in_channel = hex2int( inp->data + CHANNEL_OFFSET, CHANNEL_SIZE );
-
- if (s->in_datalen <= 0) {
- D("ignoring %s packet from serial port",
- s->in_datalen ? "empty" : "malformed");
- s->in_datalen = 0;
- }
-
- //D("received %d bytes packet for channel %d", s->in_datalen, s->in_channel);
- inpos = 0;
- }
- }
- else /* then, populate the packet itself */
- {
- int wanted = s->in_datalen - inpos;
-
- if (avail > wanted)
- avail = wanted;
-
- memcpy( inp->data + inpos, p->data + rpos, avail );
- inpos += avail;
- rpos += avail;
-
- if (inpos == s->in_datalen) {
- if (s->in_channel < 0) {
- D("ignoring %d bytes addressed to channel %d",
- inpos, s->in_channel);
- } else {
- inp->len = inpos;
- inp->channel = s->in_channel;
- receiver_post( s->receiver, inp );
- s->in_packet = inp = packet_alloc();
- }
- s->in_datalen = 0;
- inpos = 0;
- }
- }
- }
- s->in_len = inpos;
- packet_free(&p);
-}
-
-
-/* send a packet to the serial port.
- * this assumes that p->len and p->channel contain the payload's
- * size and channel and will add the appropriate header.
- */
-static void
-serial_send( Serial* s, Packet* p )
-{
- Packet* h = packet_alloc();
-
- //D("sending to serial %d bytes from channel %d: '%.*s'", p->len, p->channel, p->len, p->data);
-
- /* insert a small header before this packet */
- h->len = HEADER_SIZE;
- int2hex( p->len, h->data + LENGTH_OFFSET, LENGTH_SIZE );
- int2hex( p->channel, h->data + CHANNEL_OFFSET, CHANNEL_SIZE );
-
- serial_dump( h, __FUNCTION__ );
- serial_dump( p, __FUNCTION__ );
-
- fdhandler_enqueue( s->fdhandler, h );
- fdhandler_enqueue( s->fdhandler, p );
-}
-
-
-/* initialize serial reader */
-static void
-serial_init( Serial* s,
- int fd,
- FDHandlerList* list,
- Receiver* receiver )
-{
- Receiver recv;
-
- recv.user = s;
- recv.post = (PostFunc) serial_fd_receive;
- recv.close = (CloseFunc) serial_fd_close;
-
- s->receiver[0] = receiver[0];
-
- s->fdhandler = fdhandler_new( fd, list, &recv );
- s->in_len = 0;
- s->in_datalen = 0;
- s->in_channel = 0;
- s->in_packet = packet_alloc();
-}
-
-
-/** CLIENTS
- **/
-
-typedef struct Client Client;
-typedef struct Multiplexer Multiplexer;
-
-/* A Client object models a single qemud client socket
- * connection in the emulated system.
- *
- * the client first sends the name of the system service
- * it wants to contact (no framing), then waits for a 2
- * byte answer from qemud.
- *
- * the answer is either "OK" or "KO" to indicate
- * success or failure.
- *
- * In case of success, the client can send messages
- * to the service.
- *
- * In case of failure, it can disconnect or try sending
- * the name of another service.
- */
-struct Client {
- Client* next;
- Client** pref;
- int channel;
- char registered;
- FDHandler* fdhandler;
- Multiplexer* multiplexer;
-};
-
-struct Multiplexer {
- Client* clients;
- int last_channel;
- Serial serial[1];
- Looper looper[1];
- FDHandlerList fdhandlers[1];
-};
-
-
-static int multiplexer_open_channel( Multiplexer* mult, Packet* p );
-static void multiplexer_close_channel( Multiplexer* mult, int channel );
-static void multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p );
-
-static void
-client_dump( Client* c, Packet* p, const char* funcname )
-{
- T("%s: client %p (%d): %3d bytes: '%s'",
- funcname, c, c->fdhandler->fd,
- p->len, quote(p->data, p->len));
-}
-
-/* destroy a client */
-static void
-client_free( Client* c )
-{
- /* remove from list */
- c->pref[0] = c->next;
- if (c->next)
- c->next->pref = c->pref;
-
- c->channel = -1;
- c->registered = 0;
-
- /* gently ask the FDHandler to shutdown to
- * avoid losing queued outgoing packets */
- if (c->fdhandler != NULL) {
- fdhandler_shutdown(c->fdhandler);
- c->fdhandler = NULL;
- }
-
- xfree(c);
-}
-
-
-/* a function called when a client socket receives data */
-static void
-client_fd_receive( Client* c, Packet* p )
-{
- client_dump(c, p, __FUNCTION__);
-
- if (c->registered) {
- /* the client is registered, just send the
- * data through the serial port
- */
- multiplexer_serial_send(c->multiplexer, c->channel, p);
- return;
- }
-
- if (c->channel > 0) {
- /* the client is waiting registration results.
- * this should not happen because the client
- * should wait for our 'ok' or 'ko'.
- * close the connection.
- */
- D("%s: bad client sending data before end of registration",
- __FUNCTION__);
- BAD_CLIENT:
- packet_free(&p);
- client_free(c);
- return;
- }
-
- /* the client hasn't registered a service yet,
- * so this must be the name of a service, call
- * the multiplexer to start registration for
- * it.
- */
- D("%s: attempting registration for service '%.*s'",
- __FUNCTION__, p->len, p->data);
- c->channel = multiplexer_open_channel(c->multiplexer, p);
- if (c->channel < 0) {
- D("%s: service name too long", __FUNCTION__);
- goto BAD_CLIENT;
- }
- D("%s: -> received channel id %d", __FUNCTION__, c->channel);
- packet_free(&p);
-}
-
-
-/* a function called when the client socket is closed. */
-static void
-client_fd_close( Client* c )
-{
- T("%s: client %p (%d)", __FUNCTION__, c, c->fdhandler->fd);
-
- /* no need to shutdown the FDHandler */
- c->fdhandler = NULL;
-
- /* tell the emulator we're out */
- if (c->channel > 0)
- multiplexer_close_channel(c->multiplexer, c->channel);
-
- /* free the client */
- client_free(c);
-}
-
-/* a function called when the multiplexer received a registration
- * response from the emulator for a given client.
- */
-static void
-client_registration( Client* c, int registered )
-{
- Packet* p = packet_alloc();
-
- /* sends registration status to client */
- if (!registered) {
- D("%s: registration failed for client %d", __FUNCTION__, c->channel);
- memcpy( p->data, "KO", 2 );
- p->len = 2;
- } else {
- D("%s: registration succeeded for client %d", __FUNCTION__, c->channel);
- memcpy( p->data, "OK", 2 );
- p->len = 2;
- }
- client_dump(c, p, __FUNCTION__);
- fdhandler_enqueue(c->fdhandler, p);
-
- /* now save registration state
- */
- c->registered = registered;
- if (!registered) {
- /* allow the client to try registering another service */
- c->channel = -1;
- }
-}
-
-/* send data to a client */
-static void
-client_send( Client* c, Packet* p )
-{
- client_dump(c, p, __FUNCTION__);
- fdhandler_enqueue(c->fdhandler, p);
-}
-
-
-/* Create new client socket handler */
-static Client*
-client_new( Multiplexer* mult,
- int fd,
- FDHandlerList* pfdhandlers,
- Client** pclients )
-{
- Client* c;
- Receiver recv;
-
- xnew(c);
-
- c->multiplexer = mult;
- c->next = NULL;
- c->pref = &c->next;
- c->channel = -1;
- c->registered = 0;
-
- recv.user = c;
- recv.post = (PostFunc) client_fd_receive;
- recv.close = (CloseFunc) client_fd_close;
-
- c->fdhandler = fdhandler_new( fd, pfdhandlers, &recv );
-
- /* add to client list */
- c->next = *pclients;
- c->pref = pclients;
- *pclients = c;
- if (c->next)
- c->next->pref = &c->next;
-
- return c;
-}
-
-/** GLOBAL MULTIPLEXER
- **/
-
-/* find a client by its channel */
-static Client*
-multiplexer_find_client( Multiplexer* mult, int channel )
-{
- Client* c = mult->clients;
-
- for ( ; c != NULL; c = c->next ) {
- if (c->channel == channel)
- return c;
- }
- return NULL;
-}
-
-/* handle control messages coming from the serial port
- * on CONTROL_CHANNEL.
- */
-static void
-multiplexer_handle_control( Multiplexer* mult, Packet* p )
-{
- /* connection registration success */
- if (p->len == 13 && !memcmp(p->data, "ok:connect:", 11)) {
- int channel = hex2int(p->data+11, 2);
- Client* client = multiplexer_find_client(mult, channel);
-
- /* note that 'client' can be NULL if the corresponding
- * socket was closed before the emulator response arrived.
- */
- if (client != NULL) {
- client_registration(client, 1);
- } else {
- D("%s: NULL client: '%.*s'", __FUNCTION__, p->len, p->data+11);
- }
- goto EXIT;
- }
-
- /* connection registration failure */
- if (p->len == 13 && !memcmp(p->data, "ko:connect:",11)) {
- int channel = hex2int(p->data+11, 2);
- Client* client = multiplexer_find_client(mult, channel);
-
- if (client != NULL)
- client_registration(client, 0);
-
- goto EXIT;
- }
-
- /* emulator-induced client disconnection */
- if (p->len == 13 && !memcmp(p->data, "disconnect:",11)) {
- int channel = hex2int(p->data+11, 2);
- Client* client = multiplexer_find_client(mult, channel);
-
- if (client != NULL)
- client_free(client);
-
- goto EXIT;
- }
-
- /* A message that begins with "X00" is a probe sent by
- * the emulator used to detect which version of qemud it runs
- * against (in order to detect 1.0/1.1 system images. Just
- * silently ignore it there instead of printing an error
- * message.
- */
- if (p->len >= 3 && !memcmp(p->data,"X00",3)) {
- goto EXIT;
- }
-
- D("%s: unknown control message (%d bytes): '%.*s'",
- __FUNCTION__, p->len, p->len, p->data);
-
-EXIT:
- packet_free(&p);
-}
-
-/* a function called when an incoming packet comes from the serial port */
-static void
-multiplexer_serial_receive( Multiplexer* mult, Packet* p )
-{
- Client* client;
-
- T("%s: channel=%d '%.*s'", __FUNCTION__, p->channel, p->len, p->data);
-
- if (p->channel == CHANNEL_CONTROL) {
- multiplexer_handle_control(mult, p);
- return;
- }
-
- client = multiplexer_find_client(mult, p->channel);
- if (client != NULL) {
- client_send(client, p);
- return;
- }
-
- D("%s: discarding packet for unknown channel %d", __FUNCTION__, p->channel);
- packet_free(&p);
-}
-
-/* a function called when the serial reader closes */
-static void
-multiplexer_serial_close( Multiplexer* mult )
-{
- fatal("unexpected close of serial reader");
-}
-
-/* a function called to send a packet to the serial port */
-static void
-multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p )
-{
- p->channel = channel;
- serial_send( mult->serial, p );
-}
-
-
-
-/* a function used by a client to allocate a new channel id and
- * ask the emulator to open it. 'service' must be a packet containing
- * the name of the service in its payload.
- *
- * returns -1 if the service name is too long.
- *
- * notice that client_registration() will be called later when
- * the answer arrives.
- */
-static int
-multiplexer_open_channel( Multiplexer* mult, Packet* service )
-{
- Packet* p = packet_alloc();
- int len, channel;
-
- /* find a free channel number, assume we don't have many
- * clients here. */
- {
- Client* c;
- TRY_AGAIN:
- channel = (++mult->last_channel) & 0xff;
-
- for (c = mult->clients; c != NULL; c = c->next)
- if (c->channel == channel)
- goto TRY_AGAIN;
- }
-
- len = snprintf((char*)p->data, sizeof p->data, "connect:%.*s:%02x", service->len, service->data, channel);
- if (len >= (int)sizeof(p->data)) {
- D("%s: weird, service name too long (%d > %d)", __FUNCTION__, len, sizeof(p->data));
- packet_free(&p);
- return -1;
- }
- p->channel = CHANNEL_CONTROL;
- p->len = len;
-
- serial_send(mult->serial, p);
- return channel;
-}
-
-/* used to tell the emulator a channel was closed by a client */
-static void
-multiplexer_close_channel( Multiplexer* mult, int channel )
-{
- Packet* p = packet_alloc();
- int len = snprintf((char*)p->data, sizeof(p->data), "disconnect:%02x", channel);
-
- if (len > (int)sizeof(p->data)) {
- /* should not happen */
- return;
- }
-
- p->channel = CHANNEL_CONTROL;
- p->len = len;
-
- serial_send(mult->serial, p);
-}
-
-/* this function is used when a new connection happens on the control
- * socket.
- */
-static void
-multiplexer_control_accept( Multiplexer* m, Packet* p )
-{
- /* the file descriptor for the new socket connection is
- * in p->channel. See fdhandler_accept_event() */
- int fd = p->channel;
- Client* client = client_new( m, fd, m->fdhandlers, &m->clients );
-
- D("created client %p listening on fd %d", client, fd);
-
- /* free dummy packet */
- packet_free(&p);
-}
-
-static void
-multiplexer_control_close( Multiplexer* m )
-{
- fatal("unexpected multiplexer control close");
-}
-
-static void
-multiplexer_init( Multiplexer* m, const char* serial_dev )
-{
- int fd, control_fd;
- Receiver recv;
-
- /* initialize looper and fdhandlers list */
- looper_init( m->looper );
- fdhandler_list_init( m->fdhandlers, m->looper );
-
- /* open the serial port */
- do {
- fd = open(serial_dev, O_RDWR);
- } while (fd < 0 && errno == EINTR);
-
- if (fd < 0) {
- fatal( "%s: could not open '%s': %s", __FUNCTION__, serial_dev,
- strerror(errno) );
- }
- // disable echo on serial lines
- if ( !memcmp( serial_dev, "/dev/tty", 8 ) ) {
- struct termios ios;
- tcgetattr( fd, &ios );
- ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
- tcsetattr( fd, TCSANOW, &ios );
- }
-
- /* initialize the serial reader/writer */
- recv.user = m;
- recv.post = (PostFunc) multiplexer_serial_receive;
- recv.close = (CloseFunc) multiplexer_serial_close;
-
- serial_init( m->serial, fd, m->fdhandlers, &recv );
-
- /* open the qemud control socket */
- recv.user = m;
- recv.post = (PostFunc) multiplexer_control_accept;
- recv.close = (CloseFunc) multiplexer_control_close;
-
- fd = android_get_control_socket(CONTROL_SOCKET_NAME);
- if (fd < 0) {
- fatal("couldn't get fd for control socket '%s'", CONTROL_SOCKET_NAME);
- }
-
- fdhandler_new_accept( fd, m->fdhandlers, &recv );
-
- /* initialize clients list */
- m->clients = NULL;
-}
-
-/** MAIN LOOP
- **/
-
-static Multiplexer _multiplexer[1];
-
-int main( void )
-{
- Multiplexer* m = _multiplexer;
-
- /* extract the name of our serial device from the kernel
- * boot options that are stored in /proc/cmdline
- */
-#define KERNEL_OPTION "android.qemud="
-
- {
- char buff[1024];
- int fd, len;
- char* p;
- char* q;
-
- fd = open( "/proc/cmdline", O_RDONLY );
- if (fd < 0) {
- D("%s: can't open /proc/cmdline !!: %s", __FUNCTION__,
- strerror(errno));
- exit(1);
- }
-
- len = fd_read( fd, buff, sizeof(buff)-1 );
- close(fd);
- if (len < 0) {
- D("%s: can't read /proc/cmdline: %s", __FUNCTION__,
- strerror(errno));
- exit(1);
- }
- buff[len] = 0;
-
- p = strstr( buff, KERNEL_OPTION );
- if (p == NULL) {
- D("%s: can't find '%s' in /proc/cmdline",
- __FUNCTION__, KERNEL_OPTION );
- exit(1);
- }
-
- p += sizeof(KERNEL_OPTION)-1; /* skip option */
- q = p;
- while ( *q && *q != ' ' && *q != '\t' )
- q += 1;
-
- snprintf( buff, sizeof(buff), "/dev/%.*s", q-p, p );
-
- multiplexer_init( m, buff );
- }
-
- D( "entering main loop");
- looper_loop( m->looper );
- D( "unexpected termination !!" );
- return 0;
-}
diff --git a/sensors/Android.mk b/sensors/Android.mk
index e3df473..7a57bec 100644
--- a/sensors/Android.mk
+++ b/sensors/Android.mk
@@ -17,23 +17,9 @@
# HAL module implemenation stored in
# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.hardware>.so
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SHARED_LIBRARIES := liblog libcutils
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
-LOCAL_SRC_FILES := sensors_qemu.c
-ifeq ($(TARGET_PRODUCT),vbox_x86)
-LOCAL_MODULE := sensors.vbox_x86
-else
-LOCAL_MODULE := sensors.goldfish
-endif
-include $(BUILD_SHARED_LIBRARY)
-
-
include $(CLEAR_VARS)
-
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
diff --git a/sensors/sensors_qemu.c b/sensors/sensors_qemu.c
index 9eee746..7954cf5 100644
--- a/sensors/sensors_qemu.c
+++ b/sensors/sensors_qemu.c
@@ -50,40 +50,46 @@
/** SENSOR IDS AND NAMES
**/
-#define MAX_NUM_SENSORS 8
+#define MAX_NUM_SENSORS 10
#define SUPPORTED_SENSORS ((1<<MAX_NUM_SENSORS)-1)
-#define ID_BASE SENSORS_HANDLE_BASE
-#define ID_ACCELERATION (ID_BASE+0)
-#define ID_MAGNETIC_FIELD (ID_BASE+1)
-#define ID_ORIENTATION (ID_BASE+2)
-#define ID_TEMPERATURE (ID_BASE+3)
-#define ID_PROXIMITY (ID_BASE+4)
-#define ID_LIGHT (ID_BASE+5)
-#define ID_PRESSURE (ID_BASE+6)
-#define ID_HUMIDITY (ID_BASE+7)
+#define ID_BASE SENSORS_HANDLE_BASE
+#define ID_ACCELERATION (ID_BASE+0)
+#define ID_GYROSCOPE (ID_BASE+1)
+#define ID_MAGNETIC_FIELD (ID_BASE+2)
+#define ID_ORIENTATION (ID_BASE+3)
+#define ID_TEMPERATURE (ID_BASE+4)
+#define ID_PROXIMITY (ID_BASE+5)
+#define ID_LIGHT (ID_BASE+6)
+#define ID_PRESSURE (ID_BASE+7)
+#define ID_HUMIDITY (ID_BASE+8)
+#define ID_MAGNETIC_FIELD_UNCALIBRATED (ID_BASE+9)
-#define SENSORS_ACCELERATION (1 << ID_ACCELERATION)
-#define SENSORS_MAGNETIC_FIELD (1 << ID_MAGNETIC_FIELD)
-#define SENSORS_ORIENTATION (1 << ID_ORIENTATION)
-#define SENSORS_TEMPERATURE (1 << ID_TEMPERATURE)
-#define SENSORS_PROXIMITY (1 << ID_PROXIMITY)
-#define SENSORS_LIGHT (1 << ID_LIGHT)
-#define SENSORS_PRESSURE (1 << ID_PRESSURE)
-#define SENSORS_HUMIDITY (1 << ID_HUMIDITY)
+#define SENSORS_ACCELERATION (1 << ID_ACCELERATION)
+#define SENSORS_GYROSCOPE (1 << ID_GYROSCOPE)
+#define SENSORS_MAGNETIC_FIELD (1 << ID_MAGNETIC_FIELD)
+#define SENSORS_ORIENTATION (1 << ID_ORIENTATION)
+#define SENSORS_TEMPERATURE (1 << ID_TEMPERATURE)
+#define SENSORS_PROXIMITY (1 << ID_PROXIMITY)
+#define SENSORS_LIGHT (1 << ID_LIGHT)
+#define SENSORS_PRESSURE (1 << ID_PRESSURE)
+#define SENSORS_HUMIDITY (1 << ID_HUMIDITY)
+#define SENSORS_MAGNETIC_FIELD_UNCALIBRATED (1 << ID_MAGNETIC_FIELD)
#define ID_CHECK(x) ((unsigned)((x) - ID_BASE) < MAX_NUM_SENSORS)
#define SENSORS_LIST \
SENSOR_(ACCELERATION,"acceleration") \
+ SENSOR_(GYROSCOPE,"gyroscope") \
SENSOR_(MAGNETIC_FIELD,"magnetic-field") \
SENSOR_(ORIENTATION,"orientation") \
SENSOR_(TEMPERATURE,"temperature") \
SENSOR_(PROXIMITY,"proximity") \
SENSOR_(LIGHT, "light") \
SENSOR_(PRESSURE, "pressure") \
- SENSOR_(HUMIDITY, "humidity")
+ SENSOR_(HUMIDITY, "humidity") \
+ SENSOR_(MAGNETIC_FIELD_UNCALIBRATED,"magnetic-field-uncalibrated") \
static const struct {
const char* name;
@@ -317,6 +323,18 @@
continue;
}
+ /* "gyroscope:<x>:<y>:<z>" corresponds to a gyroscope event */
+ if (sscanf(buff, "gyroscope:%g:%g:%g", params+0, params+1, params+2)
+ == 3) {
+ new_sensors |= SENSORS_GYROSCOPE;
+ if (events[ID_GYROSCOPE].type == SENSOR_TYPE_META_DATA) continue;
+ events[ID_GYROSCOPE].gyro.x = params[0];
+ events[ID_GYROSCOPE].gyro.y = params[1];
+ events[ID_GYROSCOPE].gyro.z = params[2];
+ events[ID_GYROSCOPE].type = SENSOR_TYPE_GYROSCOPE;
+ continue;
+ }
+
/* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation
* changes */
if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2)
@@ -347,6 +365,19 @@
continue;
}
+ if (sscanf(buff, "magnetic-uncalibrated:%g:%g:%g", params+0, params+1, params+2)
+ == 3) {
+ new_sensors |= SENSORS_MAGNETIC_FIELD_UNCALIBRATED;
+ if (events[ID_MAGNETIC_FIELD_UNCALIBRATED].type == SENSOR_TYPE_META_DATA) continue;
+ events[ID_MAGNETIC_FIELD_UNCALIBRATED].magnetic.x = params[0];
+ events[ID_MAGNETIC_FIELD_UNCALIBRATED].magnetic.y = params[1];
+ events[ID_MAGNETIC_FIELD_UNCALIBRATED].magnetic.z = params[2];
+ events[ID_MAGNETIC_FIELD_UNCALIBRATED].magnetic.status =
+ SENSOR_STATUS_ACCURACY_HIGH;
+ events[ID_MAGNETIC_FIELD_UNCALIBRATED].type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
+ continue;
+ }
+
/* "temperature:<celsius>" */
if (sscanf(buff, "temperature:%g", params+0) == 1) {
new_sensors |= SENSORS_TEMPERATURE;
@@ -656,6 +687,19 @@
.reserved = {}
},
+ { .name = "Goldfish 3-axis Gyroscope",
+ .vendor = "The Android Open Source Project",
+ .version = 1,
+ .handle = ID_GYROSCOPE,
+ .type = SENSOR_TYPE_GYROSCOPE,
+ .maxRange = 11.1111111,
+ .resolution = 1.0f/1000.0f,
+ .power = 3.0f,
+ .minDelay = 10000,
+ .maxDelay = 60 * 1000 * 1000,
+ .reserved = {}
+ },
+
{ .name = "Goldfish 3-axis Magnetic field sensor",
.vendor = "The Android Open Source Project",
.version = 1,
@@ -780,7 +824,20 @@
.requiredPermission = 0,
.flags = SENSOR_FLAG_CONTINUOUS_MODE,
.reserved = {}
- }
+ },
+
+ { .name = "Goldfish 3-axis Magnetic field sensor (uncalibrated)",
+ .vendor = "The Android Open Source Project",
+ .version = 1,
+ .handle = ID_MAGNETIC_FIELD_UNCALIBRATED,
+ .type = SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+ .maxRange = 2000.0f,
+ .resolution = 1.0f,
+ .power = 6.7f,
+ .minDelay = 10000,
+ .maxDelay = 60 * 1000 * 1000,
+ .reserved = {}
+ },
};
static struct sensor_t sSensorList[MAX_NUM_SENSORS];
diff --git a/vndk/Android.mk b/vndk/Android.mk
new file mode 100644
index 0000000..a58aac5
--- /dev/null
+++ b/vndk/Android.mk
@@ -0,0 +1,58 @@
+ifneq ($(filter generic_x86 generic_x86_64 generic generic_arm64 generic_mips generic_mips64, $(TARGET_DEVICE)),)
+
+LOCAL_PATH := $(call my-dir)
+
+VNDK_SP_LIBRARIES := \
+ android.hardware.renderscript@1.0\
+ android.hardware.graphics.allocator@2.0\
+ android.hardware.graphics.mapper@2.0\
+ android.hardware.graphics.common@1.0\
+ libhwbinder\
+ libbase\
+ libcutils\
+ libhardware\
+ libhidlbase\
+ libhidltransport\
+ libutils\
+ libc++\
+ libRS_internal\
+ libRSDriver\
+ libRSCpuRef\
+ libbcinfo\
+ libblas\
+ libft2\
+ libpng\
+ libcompiler_rt\
+ libbacktrace\
+ libunwind\
+ libunwindstack\
+ liblzma\
+
+define add-vndk-sp-lib
+include $$(CLEAR_VARS)
+LOCAL_MODULE := $1.vndk-sp
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_PREBUILT_MODULE_FILE := $$(TARGET_OUT)/lib/$1.so
+LOCAL_MULTILIB := 32
+LOCAL_MODULE_TAGS := optional
+LOCAL_INSTALLED_MODULE_STEM := $1.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE_RELATIVE_PATH := vndk-sp
+include $$(BUILD_PREBUILT)
+
+include $$(CLEAR_VARS)
+LOCAL_MODULE := $1.vndk-sp
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_PREBUILT_MODULE_FILE := $$(TARGET_OUT)/lib64/$1.so
+LOCAL_MULTILIB := 64
+LOCAL_MODULE_TAGS := optional
+LOCAL_INSTALLED_MODULE_STEM := $1.so
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE_RELATIVE_PATH := vndk-sp
+include $$(BUILD_PREBUILT)
+endef
+
+$(foreach lib,$(VNDK_SP_LIBRARIES),\
+ $(eval $(call add-vndk-sp-lib,$(lib))))
+
+endif