Merge "Cancel touches as well as pointer gestures." into mnc-dev
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index f2c76d5..0c3ae02 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -177,7 +177,7 @@
return 0;
}
-int move_complete_app(const char *from_uuid, const char *to_uuid,
+int copy_complete_app(const char *from_uuid, const char *to_uuid,
const char *package_name, const char *data_app_name, appid_t appid,
const char* seinfo) {
std::vector<userid_t> users = get_known_users(from_uuid);
@@ -264,19 +264,9 @@
}
}
- // Delete old app and data
- {
- std::string from(create_data_app_package_path(from_uuid, data_app_name));
- if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
- LOG(WARNING) << "Failed to delete " << from;
- }
- }
- for (auto user : users) {
- std::string from(create_data_user_package_path(from_uuid, user, package_name));
- if (delete_dir_contents(from.c_str(), 1, NULL) != 0) {
- LOG(WARNING) << "Failed to delete " << from;
- }
- }
+ // We let the framework scan the new location and persist that before
+ // deleting the data in the old location; this ordering ensures that
+ // we can recover from things like battery pulls.
return 0;
fail:
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 297b3a1..13e3168 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -124,10 +124,10 @@
return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
}
-static int do_mv_complete_app(char **arg, char reply[REPLY_MAX] __unused)
+static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] __unused)
{
// from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
- return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
+ return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
}
static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
@@ -206,7 +206,7 @@
{ "rmcodecache", 3, do_rm_code_cache },
{ "getsize", 8, do_get_size },
{ "rmuserdata", 3, do_rm_user_data },
- { "mvcompleteapp", 6, do_mv_complete_app },
+ { "cpcompleteapp", 6, do_cp_complete_app },
{ "movefiles", 0, do_movefiles },
{ "linklib", 4, do_linklib },
{ "mkuserdata", 5, do_mk_user_data },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 744ed3a..7ec5793 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -225,7 +225,7 @@
int delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
userid_t userid, const char* seinfo);
-int move_complete_app(const char* from_uuid, const char *to_uuid,
+int copy_complete_app(const char* from_uuid, const char *to_uuid,
const char *package_name, const char *data_app_name, appid_t appid,
const char* seinfo);
int make_user_config(userid_t userid);
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 4feb6db..3dca2a3 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -40,7 +40,7 @@
virtual Vector<Sensor> getSensorList(const String16& opPackageName) = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int mode, const String16& opPackageName) = 0;
- virtual status_t enableDataInjection(int enable) = 0;
+ virtual int32_t isDataInjectionEnabled() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 4c34e12..3796067 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -107,7 +107,7 @@
ssize_t getSensorList(Sensor const* const** list) const;
Sensor const* getDefaultSensor(int type);
sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
- status_t enableDataInjection(bool enable);
+ bool isDataInjectionEnabled();
private:
// DeathRecipient interface
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 38fb757..87e5b4d 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -922,8 +922,8 @@
mCore->mSidebandStream.clear();
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
- } else {
- BQ_LOGE("disconnect(P): connected to another API "
+ } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("disconnect(P): still connected to another API "
"(cur=%d req=%d)", mCore->mConnectedApi, api);
status = BAD_VALUE;
}
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 5dde9f9..f581b5c 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -77,10 +77,9 @@
return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
}
- virtual status_t enableDataInjection(int enable) {
+ virtual int isDataInjectionEnabled() {
Parcel data, reply;
data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
- data.writeInt32(enable);
remote()->transact(ENABLE_DATA_INJECTION, data, &reply);
return reply.readInt32();
}
@@ -121,8 +120,7 @@
}
case ENABLE_DATA_INJECTION: {
CHECK_INTERFACE(ISensorServer, data, reply);
- int32_t enable = data.readInt32();
- status_t ret = enableDataInjection(enable);
+ int32_t ret = isDataInjectionEnabled();
reply->writeInt32(static_cast<int32_t>(ret));
return NO_ERROR;
}
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 8b2018f..4b7986e 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <linux/errno.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -150,13 +151,20 @@
}
status_t SensorEventQueue::injectSensorEvent(const ASensorEvent& event) {
- // Blocking call.
- ssize_t size = ::send(mSensorChannel->getFd(), &event, sizeof(event), MSG_NOSIGNAL);
- if (size < 0) {
- ALOGE("injectSensorEvent failure %zd %d", size, mSensorChannel->getFd());
- return INVALID_OPERATION;
- }
- return NO_ERROR;
+ do {
+ // Blocking call.
+ ssize_t size = ::send(mSensorChannel->getFd(), &event, sizeof(event), MSG_NOSIGNAL);
+ if (size >= 0) {
+ return NO_ERROR;
+ } else if (size < 0 && errno == EAGAIN) {
+ // If send is returning a "Try again" error, sleep for 100ms and try again. In all
+ // other cases log a failure and exit.
+ usleep(100000);
+ } else {
+ ALOGE("injectSensorEvent failure %s %zd", strerror(errno), size);
+ return INVALID_OPERATION;
+ }
+ } while (true);
}
void SensorEventQueue::sendAck(const ASensorEvent* events, int count) {
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 8c9f95b..dd37781 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -153,12 +153,12 @@
return queue;
}
-status_t SensorManager::enableDataInjection(bool enable) {
+bool SensorManager::isDataInjectionEnabled() {
Mutex::Autolock _l(mLock);
if (assertStateLocked() == NO_ERROR) {
- return mSensorServer->enableDataInjection(enable);
+ return mSensorServer->isDataInjectionEnabled();
}
- return INVALID_OPERATION;
+ return false;
}
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 5444631..8378907 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -91,11 +91,19 @@
"EGL_KHR_gl_colorspace "
#endif
"EGL_KHR_gl_texture_2D_image "
+ "EGL_KHR_gl_texture_3D_image "
"EGL_KHR_gl_texture_cubemap_image "
"EGL_KHR_gl_renderbuffer_image "
"EGL_KHR_reusable_sync "
"EGL_KHR_fence_sync "
"EGL_KHR_create_context "
+ "EGL_KHR_config_attribs "
+ "EGL_KHR_surfaceless_context "
+ "EGL_KHR_stream "
+ "EGL_KHR_stream_fifo "
+ "EGL_KHR_stream_producer_eglsurface "
+ "EGL_KHR_stream_consumer_gltexture "
+ "EGL_KHR_stream_cross_process_fd "
"EGL_EXT_create_context_robustness "
"EGL_NV_system_time "
"EGL_ANDROID_image_native_buffer " // mandatory
@@ -164,6 +172,31 @@
// EGL_KHR_partial_update
{ "eglSetDamageRegionKHR",
(__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
+
+ { "eglCreateStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
+ { "eglDestroyStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
+ { "eglStreamAttribKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
+ { "eglQueryStreamKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
+ { "eglQueryStreamu64KHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
+ { "eglQueryStreamTimeKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
+ { "eglCreateStreamProducerSurfaceKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
+ { "eglStreamConsumerGLTextureExternalKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
+ { "eglStreamConsumerAcquireKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
+ { "eglStreamConsumerReleaseKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
+ { "eglGetStreamFileDescriptorKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
+ { "eglCreateStreamFromFileDescriptorKHR",
+ (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
};
/*
@@ -562,6 +595,15 @@
return setError(EGL_BAD_SURFACE, EGL_FALSE);
egl_surface_t * const s = get_surface(surface);
+ ANativeWindow* window = s->win.get();
+ if (window) {
+ int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ if (result != OK) {
+ ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) "
+ "failed (%#x)",
+ window, result);
+ }
+ }
EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
if (result == EGL_TRUE) {
_s.terminate();
@@ -1518,6 +1560,212 @@
return result;
}
+EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_STREAM_KHR;
+
+ EGLStreamKHR result = EGL_NO_STREAM_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
+ result = cnx->egl.eglCreateStreamKHR(
+ dp->disp.dpy, attrib_list);
+ }
+ return result;
+}
+
+EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
+ result = cnx->egl.eglDestroyStreamKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
+ result = cnx->egl.eglStreamAttribKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
+ result = cnx->egl.eglQueryStreamKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLuint64KHR *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
+ result = cnx->egl.eglQueryStreamu64KHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLTimeKHR *value)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
+ result = cnx->egl.eglQueryStreamTimeKHR(
+ dp->disp.dpy, stream, attribute, value);
+ }
+ return result;
+}
+
+EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
+ EGLStreamKHR stream, const EGLint *attrib_list)
+{
+ clearError();
+
+ egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_SURFACE;
+
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
+ EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
+ dp->disp.dpy, config, stream, attrib_list);
+ if (surface != EGL_NO_SURFACE) {
+ egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
+ surface, cnx);
+ return s;
+ }
+ }
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
+ result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
+ result = cnx->egl.eglStreamConsumerAcquireKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
+ EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ EGLBoolean result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
+ result = cnx->egl.eglStreamConsumerReleaseKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
+ EGLDisplay dpy, EGLStreamKHR stream)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
+
+ EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
+ result = cnx->egl.eglGetStreamFileDescriptorKHR(
+ dp->disp.dpy, stream);
+ }
+ return result;
+}
+
+EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
+ EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_NO_STREAM_KHR;
+
+ EGLStreamKHR result = EGL_NO_STREAM_KHR;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
+ result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
+ dp->disp.dpy, file_descriptor);
+ }
+ return result;
+}
+
// ----------------------------------------------------------------------------
// EGL_EGLEXT_VERSION 15
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 1e27cb6..498b2fc 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -61,18 +61,18 @@
/* EGL_EGLEXT_VERSION 15 */
-// EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint *)
-// EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint *)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR *)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint *)
-// EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*)
-// EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR)
-// EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamKHR, EGLDisplay, const EGLint *)
+EGL_ENTRY(EGLBoolean, eglDestroyStreamKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamAttribKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint)
+EGL_ENTRY(EGLBoolean, eglQueryStreamKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLint *)
+EGL_ENTRY(EGLBoolean, eglQueryStreamu64KHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLuint64KHR *)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerGLTextureExternalKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerAcquireKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLBoolean, eglStreamConsumerReleaseKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLSurface, eglCreateStreamProducerSurfaceKHR, EGLDisplay, EGLConfig, EGLStreamKHR, const EGLint *)
+EGL_ENTRY(EGLBoolean, eglQueryStreamTimeKHR, EGLDisplay, EGLStreamKHR, EGLenum, EGLTimeKHR*)
+EGL_ENTRY(EGLNativeFileDescriptorKHR, eglGetStreamFileDescriptorKHR, EGLDisplay, EGLStreamKHR)
+EGL_ENTRY(EGLStreamKHR, eglCreateStreamFromFileDescriptorKHR, EGLDisplay, EGLNativeFileDescriptorKHR)
EGL_ENTRY(EGLint, eglWaitSyncKHR, EGLDisplay, EGLSyncKHR, EGLint)
/* ANDROID extensions */
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 550107c..71aa160 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -66,7 +66,6 @@
const char* SensorService::WAKE_LOCK_NAME = "SensorService";
// Permissions.
-static const String16 sDataInjectionPermission("android.permission.LOCATION_HARDWARE");
static const String16 sDump("android.permission.DUMP");
SensorService::SensorService()
@@ -246,12 +245,12 @@
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
} else {
- if (args.size() > 1) {
+ if (args.size() > 2) {
return INVALID_OPERATION;
}
Mutex::Autolock _l(mLock);
SensorDevice& dev(SensorDevice::getInstance());
- if (args.size() == 1 && args[0] == String16("restrict")) {
+ if (args.size() == 2 && args[0] == String16("restrict")) {
// If already in restricted mode. Ignore.
if (mCurrentOperatingMode == RESTRICTED) {
return status_t(NO_ERROR);
@@ -268,6 +267,7 @@
for (size_t i=0 ; i< mActiveSensors.size(); ++i) {
mActiveSensors.valueAt(i)->clearAllPendingFlushConnections();
}
+ mWhiteListedPackage.setTo(String8(args[1]));
return status_t(NO_ERROR);
} else if (args.size() == 1 && args[0] == String16("enable")) {
// If currently in restricted mode, reset back to NORMAL mode else ignore.
@@ -275,7 +275,30 @@
mCurrentOperatingMode = NORMAL;
dev.enableAllSensors();
}
+ if (mCurrentOperatingMode == DATA_INJECTION) {
+ resetToNormalModeLocked();
+ }
+ mWhiteListedPackage.clear();
return status_t(NO_ERROR);
+ } else if (args.size() == 2 && args[0] == String16("data_injection")) {
+ if (mCurrentOperatingMode == NORMAL) {
+ dev.disableAllSensors();
+ status_t err = dev.setMode(DATA_INJECTION);
+ if (err == NO_ERROR) {
+ mCurrentOperatingMode = DATA_INJECTION;
+ } else {
+ // Re-enable sensors.
+ dev.enableAllSensors();
+ }
+ mWhiteListedPackage.setTo(String8(args[1]));
+ return NO_ERROR;
+ } else if (mCurrentOperatingMode == DATA_INJECTION) {
+ // Already in DATA_INJECTION mode. Treat this as a no_op.
+ return NO_ERROR;
+ } else {
+ // Transition to data injection mode supported only from NORMAL mode.
+ return INVALID_OPERATION;
+ }
} else if (mSensorList.size() == 0) {
result.append("No Sensors on the device\n");
} else {
@@ -362,10 +385,10 @@
result.appendFormat(" NORMAL\n");
break;
case RESTRICTED:
- result.appendFormat(" RESTRICTED\n");
+ result.appendFormat(" RESTRICTED : %s\n", mWhiteListedPackage.string());
break;
case DATA_INJECTION:
- result.appendFormat(" DATA_INJECTION\n");
+ result.appendFormat(" DATA_INJECTION : %s\n", mWhiteListedPackage.string());
}
result.appendFormat("%zd active connections\n", mActiveConnections.size());
@@ -712,12 +735,15 @@
if (requestedMode != NORMAL && requestedMode != DATA_INJECTION) {
return NULL;
}
- // DATA_INJECTION mode needs to have the required permissions set.
- if (requestedMode == DATA_INJECTION && !hasDataInjectionPermissions()) {
- return NULL;
- }
Mutex::Autolock _l(mLock);
+ // To create a client in DATA_INJECTION mode to inject data, SensorService should already be
+ // operating in DI mode.
+ if (requestedMode == DATA_INJECTION) {
+ if (mCurrentOperatingMode != DATA_INJECTION) return NULL;
+ if (!isWhiteListedPackage(packageName)) return NULL;
+ }
+
uid_t uid = IPCThreadState::self()->getCallingUid();
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, packageName,
requestedMode == DATA_INJECTION, opPackageName));
@@ -732,35 +758,9 @@
return result;
}
-status_t SensorService::enableDataInjection(int requestedMode) {
- if (!hasDataInjectionPermissions()) {
- return INVALID_OPERATION;
- }
+int SensorService::isDataInjectionEnabled() {
Mutex::Autolock _l(mLock);
- ALOGD_IF(DEBUG_CONNECTIONS, "SensorService::enableDataInjection %d", requestedMode);
- SensorDevice& dev(SensorDevice::getInstance());
- status_t err(NO_ERROR);
- if (requestedMode == DATA_INJECTION) {
- if (mCurrentOperatingMode == NORMAL) {
- dev.disableAllSensors();
- err = dev.setMode(requestedMode);
- if (err == NO_ERROR) {
- mCurrentOperatingMode = DATA_INJECTION;
- } else {
- // Re-enable sensors.
- dev.enableAllSensors();
- }
- } else if (mCurrentOperatingMode == DATA_INJECTION) {
- // Already in DATA_INJECTION mode. Treat this as a no_op.
- return NO_ERROR;
- } else {
- // Transition to data injection mode supported only from NORMAL mode.
- return INVALID_OPERATION;
- }
- } else if (requestedMode == NORMAL && mCurrentOperatingMode != NORMAL) {
- err = resetToNormalModeLocked();
- }
- return err;
+ return (mCurrentOperatingMode == DATA_INJECTION);
}
status_t SensorService::resetToNormalMode() {
@@ -838,7 +838,8 @@
}
Mutex::Autolock _l(mLock);
- if (mCurrentOperatingMode == RESTRICTED && !isWhiteListedPackage(connection->getPackageName())) {
+ if ((mCurrentOperatingMode == RESTRICTED || mCurrentOperatingMode == DATA_INJECTION)
+ && !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
}
@@ -1106,15 +1107,6 @@
return true;
}
-bool SensorService::hasDataInjectionPermissions() {
- if (!PermissionCache::checkCallingPermission(sDataInjectionPermission)) {
- ALOGE("Permission Denial trying to activate data injection without"
- " the required permission");
- return false;
- }
- return true;
-}
-
void SensorService::checkWakeLockState() {
Mutex::Autolock _l(mLock);
checkWakeLockStateLocked();
@@ -1159,8 +1151,7 @@
}
bool SensorService::isWhiteListedPackage(const String8& packageName) {
- // TODO: Come up with a list of packages.
- return (packageName.find(".cts.") != -1);
+ return (packageName.contains(mWhiteListedPackage.string()));
}
int SensorService::getNumEventsForSensorType(int sensor_event_type) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 0a7abe8..9a573ae 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -100,6 +100,18 @@
// State Transitions supported.
// RESTRICTED <--- NORMAL ---> DATA_INJECTION
// ---> <---
+
+ // Shell commands to switch modes in SensorService.
+ // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
+ // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
+ // $ adb shell dumpsys sensorservice restrict .cts.
+ //
+ // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
+ // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
+ // $ adb shell dumpsys sensorservice data_injection .xts.
+ //
+ // 3) Reset sensorservice back to NORMAL mode.
+ // $ adb shell dumpsys sensorservice enable
};
static const char* WAKE_LOCK_NAME;
@@ -117,7 +129,7 @@
virtual Vector<Sensor> getSensorList(const String16& opPackageName);
virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
int requestedMode, const String16& opPackageName);
- virtual status_t enableDataInjection(int enable);
+ virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
@@ -334,7 +346,6 @@
sensors_event_t const* buffer, const int count);
static bool canAccessSensor(const Sensor& sensor, const char* operation,
const String16& opPackageName);
- static bool hasDataInjectionPermissions();
// SensorService acquires a partial wakelock for delivering events from wake up sensors. This
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
@@ -394,6 +405,11 @@
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
Mode mCurrentOperatingMode;
+ // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
+ // applications with this packageName are allowed to activate/deactivate or call flush on
+ // sensors. To run CTS this is can be set to ".cts." and only CTS tests will get access to
+ // sensors.
+ String8 mWhiteListedPackage;
// The size of this vector is constant, only the items are mutable
KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 91f80b6..e2418cc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1102,10 +1102,21 @@
bool Layer::shouldPresentNow(const DispSync& dispSync) const {
Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return false;
+ }
+ auto timestamp = mQueueItems[0].mTimestamp;
nsecs_t expectedPresent =
mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
- return mQueueItems.empty() ?
- false : mQueueItems[0].mTimestamp < expectedPresent;
+
+ // Ignore timestamps more than a second in the future
+ bool isPlausible = timestamp < (expectedPresent + s2ns(1));
+ ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
+ "relative to expectedPresent %" PRId64, mName.string(), timestamp,
+ expectedPresent);
+
+ bool isDue = timestamp < expectedPresent;
+ return isDue || !isPlausible;
}
bool Layer::onPreComposition() {