diff options
25 files changed, 440 insertions, 87 deletions
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index fe716acfe2..dbf0877940 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -548,7 +548,7 @@ const char *dump_traces() { /* wait for the writable-close notification from inotify */ struct pollfd pfd = { ifd, POLLIN, 0 }; - int ret = poll(&pfd, 1, 200); /* 200 msec timeout */ + int ret = poll(&pfd, 1, 5000); /* 5 sec timeout */ if (ret < 0) { fprintf(stderr, "poll: %s\n", strerror(errno)); } else if (ret == 0) { diff --git a/data/etc/android.hardware.camera.external.xml b/data/etc/android.hardware.camera.external.xml new file mode 100644 index 0000000000..a138bcd388 --- /dev/null +++ b/data/etc/android.hardware.camera.external.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- This is the standard set of features for a Android device that can support +an external camera being connected to it. --> +<permissions> + <feature name="android.hardware.camera.any" /> + <feature name="android.hardware.camera.external" /> +</permissions> diff --git a/data/etc/android.hardware.screen.landscape.xml b/data/etc/android.hardware.screen.landscape.xml new file mode 100644 index 0000000000..07bcd0abe5 --- /dev/null +++ b/data/etc/android.hardware.screen.landscape.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Standard feature indicating that the device supports landscape mode. --> +<permissions> + <feature name="android.hardware.screen.landscape" /> +</permissions> diff --git a/data/etc/android.hardware.screen.portrait.xml b/data/etc/android.hardware.screen.portrait.xml new file mode 100644 index 0000000000..530c6c62af --- /dev/null +++ b/data/etc/android.hardware.screen.portrait.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Standard feature indicating that the device supports portrait mode. --> +<permissions> + <feature name="android.hardware.screen.portrait" /> +</permissions> diff --git a/data/etc/android.hardware.sensor.heartrate.xml b/data/etc/android.hardware.sensor.heartrate.xml new file mode 100644 index 0000000000..c49bfc0e30 --- /dev/null +++ b/data/etc/android.hardware.sensor.heartrate.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Feature for devices with a hardware heart rate monitor. --> +<permissions> + <feature name="android.hardware.sensor.heartrate" /> +</permissions> diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml index 215665f7d9..09a064a46f 100644 --- a/data/etc/wearable_core_hardware.xml +++ b/data/etc/wearable_core_hardware.xml @@ -21,24 +21,18 @@ Wearable devices include watches, glasses, backpacks, and sweaters. --> <permissions> - <feature name="android.hardware.camera" /> <feature name="android.hardware.location" /> - <feature name="android.hardware.location.network" /> <feature name="android.hardware.sensor.compass" /> <feature name="android.hardware.sensor.accelerometer" /> <feature name="android.hardware.bluetooth" /> <feature name="android.hardware.touchscreen" /> <feature name="android.hardware.microphone" /> - <feature name="android.hardware.screen.portrait" /> - <feature name="android.hardware.screen.landscape" /> <!-- basic system services --> <feature name="android.software.home_screen" /> - <feature name="android.software.input_methods" /> - - <!-- Feature to specify if the device supports adding device admins. --> - <feature name="android.software.device_admin" /> + <!-- devices that support a device administrator policy must include + android.software.device_admin.xml --> <!-- devices with GPS must include android.hardware.location.gps.xml --> <!-- devices with an autofocus camera and/or flash must include either android.hardware.camera.autofocus.xml or diff --git a/include/android/configuration.h b/include/android/configuration.h index 6d8784db02..97d4c42a3d 100644 --- a/include/android/configuration.h +++ b/include/android/configuration.h @@ -83,6 +83,7 @@ enum { ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03, ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04, ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05, + ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06, ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00, ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1, diff --git a/include/android/sensor.h b/include/android/sensor.h index 129ea3ebd1..b4e7ebee9c 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -281,6 +281,28 @@ float ASensor_getResolution(ASensor const* sensor); */ int ASensor_getMinDelay(ASensor const* sensor); +/* + * Returns the maximum size of batches for this sensor. Batches will often be + * smaller, as the hardware fifo might be used for other sensors. + */ +int ASensor_getFifoMaxEventCount(ASensor const* sensor); + +/* + * Returns the hardware batch fifo size reserved to this sensor. + */ +int ASensor_getFifoReservedEventCount(ASensor const* sensor); + +/* + * Returns this sensor's string type. + */ +const char* ASensor_getStringType(ASensor const* sensor); + +/* + * Returns the permission required to see or access this sensor, or the + * empty string if none is required. + */ +const char* ASensor_getRequiredPermission(ASensor const* sensor); + #ifdef __cplusplus }; diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index 0c81426815..033b262964 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -69,6 +69,8 @@ public: int32_t getVersion() const; int32_t getFifoReservedEventCount() const; int32_t getFifoMaxEventCount() const; + const String8& getStringType() const; + const String8& getRequiredPermission() const; // LightFlattenable protocol inline bool isFixedSize() const { return false; } @@ -89,6 +91,10 @@ private: int32_t mVersion; int32_t mFifoReservedEventCount; int32_t mFifoMaxEventCount; + String8 mStringType; + String8 mRequiredPermission; + static void flattenString8(void*& buffer, size_t& size, const String8& string8); + static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8); }; // ---------------------------------------------------------------------------- diff --git a/include/input/Input.h b/include/input/Input.h index bb5ceaf20b..077a03bf28 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -178,13 +178,9 @@ enum { /* These flags are set by the input reader policy as it intercepts each event. */ - // Indicates that the screen was off when the event was received and the event - // should wake the device. - POLICY_FLAG_WOKE_HERE = 0x10000000, - - // Indicates that the screen was dim when the event was received and the event - // should brighten the device. - POLICY_FLAG_BRIGHT_HERE = 0x20000000, + // Indicates that the device was in an interactive state when the + // event was intercepted. + POLICY_FLAG_INTERACTIVE = 0x20000000, // Indicates that the event should be dispatched to applications. // The input event should still be sent to the InputDispatcher so that it can see all diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 7ee3081c80..3215b2fdeb 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -350,20 +350,24 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) { status_t err = NO_ERROR; + int buf = item.mBuf; + if (!mAttached) { ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " "ES context"); + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return INVALID_OPERATION; } // Confirm state. err = checkAndUpdateEglStateLocked(); if (err != NO_ERROR) { + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return err; } - int buf = item.mBuf; - // If the mEglSlot entry is empty, create an EGLImage for the gralloc // buffer currently in the slot in ConsumerBase. // @@ -377,6 +381,12 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) if (image == EGL_NO_IMAGE_KHR) { ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, buf); + const sp<GraphicBuffer>& gb = mSlots[buf].mGraphicBuffer; + ST_LOGW("buffer size=%ux%u st=%u usage=0x%x fmt=%d", + gb->getWidth(), gb->getHeight(), gb->getStride(), + gb->getUsage(), gb->getPixelFormat()); + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); return UNKNOWN_ERROR; } mEglSlots[buf].mEglImage = image; diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index da6b0f97f9..8f63870b9e 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -48,6 +48,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mResolution = hwSensor->resolution; mPower = hwSensor->power; mMinDelay = hwSensor->minDelay; + // Set fifo event count zero for older devices which do not support batching. Fused // sensors also have their fifo counts set to zero. if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) { @@ -57,6 +58,84 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mFifoReservedEventCount = 0; mFifoMaxEventCount = 0; } + + // Ensure existing sensors have correct string type and required + // permissions. + switch (mType) { + case SENSOR_TYPE_ACCELEROMETER: + mStringType = SENSOR_STRING_TYPE_ACCELEROMETER; + break; + case SENSOR_TYPE_AMBIENT_TEMPERATURE: + mStringType = SENSOR_STRING_TYPE_AMBIENT_TEMPERATURE; + break; + case SENSOR_TYPE_GAME_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_GAME_ROTATION_VECTOR; + break; + case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR; + break; + case SENSOR_TYPE_GRAVITY: + mStringType = SENSOR_STRING_TYPE_GRAVITY; + break; + case SENSOR_TYPE_GYROSCOPE: + mStringType = SENSOR_STRING_TYPE_GYROSCOPE; + break; + case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_GYROSCOPE_UNCALIBRATED; + break; + case SENSOR_TYPE_HEART_RATE: + mStringType = SENSOR_STRING_TYPE_HEART_RATE; + mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS; + break; + case SENSOR_TYPE_LIGHT: + mStringType = SENSOR_STRING_TYPE_LIGHT; + break; + case SENSOR_TYPE_LINEAR_ACCELERATION: + mStringType = SENSOR_STRING_TYPE_LINEAR_ACCELERATION; + break; + case SENSOR_TYPE_MAGNETIC_FIELD: + mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD; + break; + case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED; + break; + case SENSOR_TYPE_ORIENTATION: + mStringType = SENSOR_STRING_TYPE_ORIENTATION; + break; + case SENSOR_TYPE_PRESSURE: + mStringType = SENSOR_STRING_TYPE_PRESSURE; + break; + case SENSOR_TYPE_PROXIMITY: + mStringType = SENSOR_STRING_TYPE_PROXIMITY; + break; + case SENSOR_TYPE_RELATIVE_HUMIDITY: + mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY; + break; + case SENSOR_TYPE_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_ROTATION_VECTOR; + break; + case SENSOR_TYPE_SIGNIFICANT_MOTION: + mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION; + break; + case SENSOR_TYPE_STEP_COUNTER: + mStringType = SENSOR_STRING_TYPE_STEP_COUNTER; + break; + case SENSOR_TYPE_STEP_DETECTOR: + mStringType = SENSOR_STRING_TYPE_STEP_DETECTOR; + break; + case SENSOR_TYPE_TEMPERATURE: + mStringType = SENSOR_STRING_TYPE_TEMPERATURE; + break; + default: + // Only pipe the stringType and requiredPermission for custom sensors. + if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) { + mStringType = hwSensor->stringType; + } + if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) { + mRequiredPermission = hwSensor->requiredPermission; + } + break; + } } Sensor::~Sensor() @@ -115,6 +194,14 @@ int32_t Sensor::getFifoMaxEventCount() const { return mFifoMaxEventCount; } +const String8& Sensor::getStringType() const { + return mStringType; +} + +const String8& Sensor::getRequiredPermission() const { + return mRequiredPermission; +} + size_t Sensor::getFlattenedSize() const { size_t fixedSize = @@ -123,8 +210,10 @@ size_t Sensor::getFlattenedSize() const sizeof(int32_t) * 3; size_t variableSize = - sizeof(int32_t) + FlattenableUtils::align<4>(mName.length()) + - sizeof(int32_t) + FlattenableUtils::align<4>(mVendor.length()); + sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mVendor.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mStringType.length()) + + sizeof(uint32_t) + FlattenableUtils::align<4>(mRequiredPermission.length()); return fixedSize + variableSize; } @@ -134,14 +223,8 @@ status_t Sensor::flatten(void* buffer, size_t size) const { return NO_MEMORY; } - FlattenableUtils::write(buffer, size, mName.length()); - memcpy(static_cast<char*>(buffer), mName.string(), mName.length()); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mName.length())); - - FlattenableUtils::write(buffer, size, mVendor.length()); - memcpy(static_cast<char*>(buffer), mVendor.string(), mVendor.length()); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(mVendor.length())); - + flattenString8(buffer, size, mName); + flattenString8(buffer, size, mVendor); FlattenableUtils::write(buffer, size, mVersion); FlattenableUtils::write(buffer, size, mHandle); FlattenableUtils::write(buffer, size, mType); @@ -152,38 +235,23 @@ status_t Sensor::flatten(void* buffer, size_t size) const { FlattenableUtils::write(buffer, size, mMinDelay); FlattenableUtils::write(buffer, size, mFifoReservedEventCount); FlattenableUtils::write(buffer, size, mFifoMaxEventCount); + flattenString8(buffer, size, mStringType); + flattenString8(buffer, size, mRequiredPermission); return NO_ERROR; } status_t Sensor::unflatten(void const* buffer, size_t size) { - size_t len; - - if (size < sizeof(size_t)) { - return NO_MEMORY; - } - FlattenableUtils::read(buffer, size, len); - if (size < len) { - return NO_MEMORY; - } - mName.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); - - - if (size < sizeof(size_t)) { + if (!unflattenString8(buffer, size, mName)) { return NO_MEMORY; } - FlattenableUtils::read(buffer, size, len); - if (size < len) { + if (!unflattenString8(buffer, size, mVendor)) { return NO_MEMORY; } - mVendor.setTo(static_cast<char const*>(buffer), len); - FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); size_t fixedSize = sizeof(int32_t) * 3 + sizeof(float) * 4 + sizeof(int32_t) * 3; - if (size < fixedSize) { return NO_MEMORY; } @@ -198,8 +266,37 @@ status_t Sensor::unflatten(void const* buffer, size_t size) { FlattenableUtils::read(buffer, size, mMinDelay); FlattenableUtils::read(buffer, size, mFifoReservedEventCount); FlattenableUtils::read(buffer, size, mFifoMaxEventCount); + + if (!unflattenString8(buffer, size, mStringType)) { + return NO_MEMORY; + } + if (!unflattenString8(buffer, size, mRequiredPermission)) { + return NO_MEMORY; + } return NO_ERROR; } +void Sensor::flattenString8(void*& buffer, size_t& size, + const String8& string8) { + uint32_t len = string8.length(); + FlattenableUtils::write(buffer, size, len); + memcpy(static_cast<char*>(buffer), string8.string(), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); +} + +bool Sensor::unflattenString8(void const*& buffer, size_t& size, String8& outputString8) { + uint32_t len; + if (size < sizeof(len)) { + return false; + } + FlattenableUtils::read(buffer, size, len); + if (size < len) { + return false; + } + outputString8.setTo(static_cast<char const*>(buffer), len); + FlattenableUtils::advance(buffer, size, FlattenableUtils::align<4>(len)); + return true; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index f6705f6be9..ca2fdf66d6 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -205,7 +205,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) String8 result; if (!PermissionCache::checkCallingPermission(sDump)) { result.appendFormat("Permission Denial: " - "can't dump SurfaceFlinger from pid=%d, uid=%d\n", + "can't dump SensorService from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); } else { @@ -215,21 +215,24 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); result.appendFormat( - "%-48s| %-32s | 0x%08x | ", + "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t", s.getName().string(), s.getVendor().string(), - s.getHandle()); + s.getStringType().string(), + s.getHandle(), + s.getRequiredPermission().string()); if (s.getMinDelay() > 0) { result.appendFormat( - "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); + "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); } else { result.append(s.getMinDelay() == 0 ? "on-demand | " : "one-shot | "); } if (s.getFifoMaxEventCount() > 0) { - result.appendFormat("getFifoMaxEventCount=%d events | ", s.getFifoMaxEventCount()); + result.appendFormat("FifoMax=%d events | ", + s.getFifoMaxEventCount()); } else { result.append("no batching support | "); } @@ -490,10 +493,23 @@ Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sensors", value, "0"); - if (atoi(value)) { - return mUserSensorListDebug; + const Vector<Sensor>& initialSensorList = (atoi(value)) ? + mUserSensorListDebug : mUserSensorList; + Vector<Sensor> accessibleSensorList; + for (size_t i = 0; i < initialSensorList.size(); i++) { + Sensor sensor = initialSensorList[i]; + if (canAccessSensor(sensor)) { + accessibleSensorList.add(sensor); + } else { + String8 infoMessage; + infoMessage.appendFormat( + "Skipped sensor %s because it requires permission %s", + sensor.getName().string(), + sensor.getRequiredPermission().string()); + ALOGI(infoMessage.string()); + } } - return mUserSensorList; + return accessibleSensorList; } sp<ISensorEventConnection> SensorService::createSensorEventConnection() @@ -539,6 +555,10 @@ void SensorService::cleanupConnection(SensorEventConnection* c) BatteryService::cleanup(c->getUid()); } +Sensor SensorService::getSensorFromHandle(int handle) const { + return mSensorMap.valueFor(handle)->getSensor(); +} + status_t SensorService::enable(const sp<SensorEventConnection>& connection, int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) { @@ -549,6 +569,11 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (sensor == NULL) { return BAD_VALUE; } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried enabling")) { + return BAD_VALUE; + } + Mutex::Autolock _l(mLock); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { @@ -670,6 +695,10 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection if (!sensor) return BAD_VALUE; + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried configuring")) { + return BAD_VALUE; + } + if (ns < 0) return BAD_VALUE; @@ -683,17 +712,44 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection, int handle) { - if (mInitCheck != NO_ERROR) return mInitCheck; - SensorInterface* sensor = mSensorMap.valueFor(handle); - if (sensor == NULL) { - return BAD_VALUE; - } - if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { - ALOGE("flush called on Significant Motion sensor"); - return INVALID_OPERATION; - } - return sensor->flush(connection.get(), handle); + if (mInitCheck != NO_ERROR) return mInitCheck; + SensorInterface* sensor = mSensorMap.valueFor(handle); + if (sensor == NULL) { + return BAD_VALUE; + } + + if (!verifyCanAccessSensor(sensor->getSensor(), "Tried flushing")) { + return BAD_VALUE; + } + + if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { + ALOGE("flush called on Significant Motion sensor"); + return INVALID_OPERATION; + } + return sensor->flush(connection.get(), handle); +} + + +bool SensorService::canAccessSensor(const Sensor& sensor) { + String16 permissionString(sensor.getRequiredPermission()); + return permissionString.size() == 0 || + PermissionCache::checkCallingPermission(permissionString); } + +bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* operation) { + if (canAccessSensor(sensor)) { + return true; + } else { + String8 errorMessage; + errorMessage.appendFormat( + "%s a sensor (%s) without holding its required permission: %s", + operation, + sensor.getName().string(), + sensor.getRequiredPermission().string()); + return false; + } +} + // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( @@ -761,6 +817,9 @@ void SensorService::SensorEventConnection::dump(String8& result) { bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); + if (!verifyCanAccessSensor(mService->getSensorFromHandle(handle), "Tried adding")) { + return false; + } if (mSensorInfo.indexOfKey(handle) < 0) { mSensorInfo.add(handle, FlushInfo()); return true; diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 1dc2dd36ae..e88ffc875b 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -131,6 +131,7 @@ class SensorService : String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; + Sensor getSensorFromHandle(int handle) const; void recordLastValue(const sensors_event_t* buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count); Sensor registerSensor(SensorInterface* sensor); @@ -141,7 +142,8 @@ class SensorService : const sp<SensorEventConnection>& connection, int handle); void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count); - + static bool canAccessSensor(const Sensor& sensor); + static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation); // constants Vector<Sensor> mSensorList; Vector<Sensor> mUserSensorListDebug; diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index ce07ab56c1..c51d207354 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -20,6 +20,7 @@ #define __STDC_LIMIT_MACROS #include <math.h> +#include <inttypes.h> #include <cutils/log.h> @@ -487,4 +488,49 @@ void DispSync::resetErrorLocked() { } } +void DispSync::dump(String8& result) const { + Mutex::Autolock lock(mMutex); + result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod); + result.appendFormat("mPhase: %"PRId64" ns\n", mPhase); + result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", + mError, sqrt(mError)); + result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n", + mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT); + result.appendFormat("mNumResyncSamples: %d (max %d)\n", + mNumResyncSamples, MAX_RESYNC_SAMPLES); + + result.appendFormat("mResyncSamples:\n"); + nsecs_t previous = -1; + for (size_t i = 0; i < mNumResyncSamples; i++) { + size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; + nsecs_t sampleTime = mResyncSamples[idx]; + if (i == 0) { + result.appendFormat(" %"PRId64"\n", sampleTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64")\n", + sampleTime, sampleTime - previous); + } + previous = sampleTime; + } + + result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", + NUM_PRESENT_SAMPLES); + previous = 0; + for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { + size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; + bool signaled = mPresentFences[idx] == NULL; + nsecs_t presentTime = mPresentTimes[idx]; + if (!signaled) { + result.appendFormat(" [unsignaled fence]\n"); + } else if (previous == 0) { + result.appendFormat(" %"PRId64"\n", presentTime); + } else { + result.appendFormat(" %"PRId64" (+%"PRId64" / %.3f)\n", + presentTime, presentTime - previous, + (presentTime - previous) / (double) mPeriod); + } + previous = presentTime; + } +} + } // namespace android diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index c4280aa0e8..19eb3e5963 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -99,6 +99,9 @@ public: // DispSync object. status_t removeEventListener(const sp<Callback>& callback); + // dump appends human-readable debug info to the result string. + void dump(String8& result) const; + private: void updateModelLocked(); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 0d0f98d899..e5ecf07780 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -199,8 +199,8 @@ void DisplayDevice::flip(const Region& dirty) const mPageFlipCount++; } -status_t DisplayDevice::beginFrame() const { - return mDisplaySurface->beginFrame(); +status_t DisplayDevice::beginFrame(bool mustRecompose) const { + return mDisplaySurface->beginFrame(mustRecompose); } status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const { diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 01a9d2efc3..f750c6c827 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -124,7 +124,9 @@ public: int32_t getHwcDisplayId() const { return mHwcDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } - status_t beginFrame() const; + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state + // machine happy without actually queueing a buffer if nothing has changed + status_t beginFrame(bool mustRecompose) const; status_t prepareFrame(const HWComposer& hwc) const; void swapBuffers(HWComposer& hwc) const; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index 48bf3f2868..1db3eb8a8c 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -33,7 +33,9 @@ public: // beginFrame is called at the beginning of the composition loop, before // the configuration is known. The DisplaySurface should do anything it // needs to do to enable HWComposer to decide how to compose the frame. - virtual status_t beginFrame() = 0; + // We pass in mustRecompose so we can keep VirtualDisplaySurface's state + // machine happy without actually queueing a buffer if nothing has changed. + virtual status_t beginFrame(bool mustRecompose) = 0; // prepareFrame is called after the composition configuration is known but // before composition takes place. The DisplaySurface can use the diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 8c634ed648..0f34764bd3 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -68,7 +68,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); } -status_t FramebufferSurface::beginFrame() { +status_t FramebufferSurface::beginFrame(bool mustRecompose) { return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 1d67446b94..ba72ce38b8 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -39,7 +39,7 @@ class FramebufferSurface : public ConsumerBase, public: FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer); - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index d7fef8c1e1..a1820abc63 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -56,7 +56,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), mProducerSlotSource(0), mDbgState(DBG_STATE_IDLE), - mDbgLastCompositionType(COMPOSITION_UNKNOWN) + mDbgLastCompositionType(COMPOSITION_UNKNOWN), + mMustRecompose(false) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bq; @@ -92,10 +93,12 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, VirtualDisplaySurface::~VirtualDisplaySurface() { } -status_t VirtualDisplaySurface::beginFrame() { +status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { if (mDisplayId < 0) return NO_ERROR; + mMustRecompose = mustRecompose; + VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, "Unexpected beginFrame() in %s state", dbgStateStr()); mDbgState = DBG_STATE_BEGUN; @@ -228,16 +231,24 @@ void VirtualDisplaySurface::onFrameCommitted() { QueueBufferOutput qbo; sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); - status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, - QueueBufferInput( - systemTime(), false /* isAutoTimestamp */, - Rect(mSinkBufferWidth, mSinkBufferHeight), - NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, - true /* async*/, - outFence), - &qbo); - if (result == NO_ERROR) { - updateQueueBufferOutput(qbo); + if (mMustRecompose) { + status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, + QueueBufferInput( + systemTime(), false /* isAutoTimestamp */, + Rect(mSinkBufferWidth, mSinkBufferHeight), + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, + true /* async*/, + outFence), + &qbo); + if (result == NO_ERROR) { + updateQueueBufferOutput(qbo); + } + } else { + // If the surface hadn't actually been updated, then we only went + // through the motions of updating the display to keep our state + // machine happy. We cancel the buffer to avoid triggering another + // re-composition and causing an infinite loop. + mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence); } } diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 1e85ac4bdb..68999049d0 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -79,7 +79,7 @@ public: // // DisplaySurface interface // - virtual status_t beginFrame(); + virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); virtual status_t compositionComplete(); virtual status_t advanceFrame(); @@ -222,6 +222,8 @@ private: const char* dbgStateStr() const; static const char* dbgSourceStr(Source s); + + bool mMustRecompose; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 86be6c3f5c..b1db8702d9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -881,7 +881,9 @@ void SurfaceFlinger::rebuildLayerStacks() { void SurfaceFlinger::setUpHWComposer() { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { - mDisplays[dpy]->beginFrame(); + bool mustRecompose = + !(mDisplays[dpy]->getDirtyRegion(false).isEmpty()); + mDisplays[dpy]->beginFrame(mustRecompose); } HWComposer& hwc(getHwComposer()); @@ -1499,6 +1501,15 @@ void SurfaceFlinger::invalidateHwcGeometry() void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, const Region& inDirtyRegion) { + // We only need to actually compose the display if: + // 1) It is being handled by hardware composer, which may need this to + // keep its virtual display state machine in sync, or + // 2) There is work to be done (the dirty region isn't empty) + bool isHwcDisplay = hw->getHwcDisplayId() >= 0; + if (!isHwcDisplay && inDirtyRegion.isEmpty()) { + return; + } + Region dirtyRegion(inDirtyRegion); // compute the invalid region @@ -2190,6 +2201,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) clearStatsLocked(args, index, result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--dispsync"))) { + index++; + mPrimaryDispSync.dump(result); + dumpAll = false; + } } if (dumpAll) { diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index b161480b3e..90e3f7de9e 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -27,7 +27,7 @@ using namespace android; -int main(int argc, char** argv) { +int main(int, char**) { // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); |