Merge tag 'android-security-11.0.0_r57' into int/11/fp3
Android security 11.0.0 release 57
* tag 'android-security-11.0.0_r57':
Only treat PNG_COLOR_TYPE_RGB as 565
Change-Id: I655ea2ee7aa739e46f49d3f9e612da0978185eb9
diff --git a/Android.bp b/Android.bp
index 122324c..a4fcc43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,8 +14,10 @@
"-Wno-implicit-fallthrough",
"-Wno-missing-field-initializers",
"-Wno-thread-safety-analysis",
+ "-Wno-unknown-warning-option",
"-Wno-unused-parameter",
"-Wno-unused-variable",
+ "-Wno-array-suspicious",
"-fvisibility=hidden",
],
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index a67d2e2..3826d94 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -12,6 +12,12 @@
#include "src/core/SkUtils.h"
#include "src/core/SkXfermodePriv.h"
+#include <semaphore.h>
+#include <assert.h>
+#include <pthread.h>
+#include <cutils/log.h>
+#include <sys/sysinfo.h>
+
static inline int upscale_31_to_32(int value) {
SkASSERT((unsigned)value <= 31);
return value + (value >> 4);
@@ -1015,14 +1021,77 @@
}
}
-void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
- SkASSERT(x >= 0 && y >= 0 &&
- x + width <= fDevice.width() && y + height <= fDevice.height());
+#define BUF_MAX 8192
+#define __ATOMIC_INLINE__ static __inline__ __attribute__((always_inline))
- uint32_t* device = fDevice.writable_addr32(x, y);
- size_t deviceRB = fDevice.rowBytes();
- auto* shaderContext = fShaderContext;
- SkPMColor* span = fBuffer;
+__ATOMIC_INLINE__ int __atomic_dec(volatile int *ptr) {
+ return __sync_fetch_and_sub (ptr, 1);
+}
+
+__ATOMIC_INLINE__ int __atomic_inc(volatile int *ptr) {
+ return __sync_fetch_and_add (ptr, 1);
+}
+
+static volatile int worker_thread_inited_ARGB32 = 0;
+static volatile int worker_thread_busy_ARGB32 = 0;
+
+#define MAX_WORKER_THREADS_NUM_ARGB32 3
+
+static pthread_t worker_threads_ARGB32[MAX_WORKER_THREADS_NUM_ARGB32];
+sem_t sem_todo_ARGB32[MAX_WORKER_THREADS_NUM_ARGB32];
+sem_t sem_done_ARGB32[MAX_WORKER_THREADS_NUM_ARGB32];
+static volatile void* work_ARGB32[MAX_WORKER_THREADS_NUM_ARGB32] = {0};
+static int worker_thread_num_ARGB32 = 0;
+
+extern const char* __progname;
+static int is_not_zygote_ARGB32(){
+ const char * buf = __progname;
+ const char * zygote = "zygote";
+ /*
+ * adb shell cat /proc/192/cmdline
+ * zygote/bin/app_process-Xzygote/system/bin--zygote--start-system-server
+ */
+ return strncmp(buf, zygote, 6);
+}
+
+struct shadeSpanArg {
+ SkShaderBase::Context* shaderContext;
+ int x;
+ int y;
+ int width;
+ int height;
+ uint32_t* device;
+ size_t deviceRB;
+ bool fShadeDirectlyIntoDevice;
+ bool fConstInY;
+ SkXfermode* fXfermode;
+ SkBlitRow::Proc32 fProc32;
+ SkPMColor* fBuffer;
+};
+
+
+void blitRect_core(
+ SkShaderBase::Context* shaderContext,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t* device,
+ size_t deviceRB,
+ bool fShadeDirectlyIntoDevice,
+ bool fConstInY,
+ SkXfermode* fXfermode,
+ SkBlitRow::Proc32 fProc32,
+ SkPMColor* fbuffer)
+{
+ SkPMColor* span = NULL;
+ if (fbuffer) {
+ span = fbuffer;
+ } else {
+ SkASSERT(width <= BUF_MAX);
+ uint32_t buffer[BUF_MAX];
+ span = (SkPMColor*)buffer;
+ }
if (fConstInY) {
if (fShadeDirectlyIntoDevice) {
@@ -1081,6 +1150,180 @@
}
}
+void* worker_blitRect_ARGB32(void * arg) {
+
+ long id=(long)arg;
+
+ //worker thread
+ while(1){
+ sem_wait(&sem_todo_ARGB32[id]);
+ if (work_ARGB32[id] != 0) {
+ struct shadeSpanArg* arg= (struct shadeSpanArg*)work_ARGB32[id];
+ SkShaderBase::Context* shaderContext =arg->shaderContext;
+ int x = arg->x;
+ int y = arg->y;
+ int width = arg->width;
+ int height = arg->height;
+ uint32_t* device = arg->device;
+ size_t deviceRB = arg->deviceRB;
+
+ bool fShadeDirectlyIntoDevice = arg->fShadeDirectlyIntoDevice;
+ bool fConstInY = arg->fConstInY;
+ SkXfermode* fXfermode = arg->fXfermode;
+ SkBlitRow::Proc32 fProc32 = arg->fProc32;
+ SkPMColor* fBuffer = arg->fBuffer;
+
+ blitRect_core(
+ shaderContext,
+ x,
+ y,
+ width,
+ height,
+ device,
+ deviceRB,
+ fShadeDirectlyIntoDevice,
+ fConstInY,
+ fXfermode,
+ fProc32,
+ fBuffer
+ );
+
+ work_ARGB32[id] = 0;
+ }
+ sem_post(&sem_done_ARGB32[id]);
+ }
+}
+
+
+void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
+ SkASSERT(x >= 0 && y >= 0 &&
+ x + width <= fDevice.width() && y + height <= fDevice.height());
+
+ uint32_t* device = fDevice.writable_addr32(x, y);
+ size_t deviceRB = fDevice.rowBytes();
+ auto* shaderContext = fShaderContext;
+
+ //Disable this since some issue found
+ if (false && ((height * width) > (750 * 400)) && (width <= BUF_MAX) && height >= 4) {
+ if (__atomic_inc(&worker_thread_busy_ARGB32) == 0) {
+ if (!worker_thread_inited_ARGB32) {
+ if (__atomic_inc(&worker_thread_inited_ARGB32) == 0) {
+ //Only start the other thread in non-zygote mode.
+ if (!is_not_zygote_ARGB32()){
+ __atomic_dec(&worker_thread_busy_ARGB32);
+ __atomic_dec(&worker_thread_inited_ARGB32);
+ goto fb;
+ }
+ long i;
+ worker_thread_num_ARGB32 = (get_nprocs_conf()/2 -1);
+ if (worker_thread_num_ARGB32 > MAX_WORKER_THREADS_NUM_ARGB32) {
+ worker_thread_num_ARGB32 = MAX_WORKER_THREADS_NUM_ARGB32;
+ } else if (worker_thread_num_ARGB32 <= 2) {
+ worker_thread_num_ARGB32 = 1;
+ }
+ for(i = 0; i < worker_thread_num_ARGB32; i++){
+ sem_init(&sem_todo_ARGB32[i], 0, 0);
+ sem_init(&sem_done_ARGB32[i], 0, 0);
+ pthread_create(&worker_threads_ARGB32[i], NULL, worker_blitRect_ARGB32, (void*)i);
+ }
+
+ }
+ }
+ if (worker_thread_num_ARGB32 > 0) {
+ struct shadeSpanArg msg[worker_thread_num_ARGB32];
+ if (worker_thread_num_ARGB32 == 1) {
+ msg[0].y = y + (height >>1);
+ msg[0].height = height - (height >> 1);
+ msg[0].device = (uint32_t*)((char*)device + (deviceRB * (height >> 1)));
+
+ height = (height >> 1);
+ } else if (worker_thread_num_ARGB32 == 3) {
+ msg[0].y = (y + (height >> 2));
+ msg[0].height = ((height >> 1) - (height >> 2));
+ msg[0].device = (uint32_t*)((char*)device + (deviceRB * (height >> 2)));
+
+ msg[1].y = (y + (height >> 1));
+ msg[1].height = ((height - (height >> 1)) >> 1);
+ msg[1].device = (uint32_t*)((char*)device + (deviceRB * (height >> 1)));
+
+ msg[2].y = (y + (height >> 1) + ((height - (height >> 1)) >> 1));
+ msg[2].height = ((height - (height >> 1)) - ((height - (height >> 1)) >> 1));
+ msg[2].device = (uint32_t*)((char*)device + (deviceRB * ((height >> 1) + ((height - (height >> 1)) >> 1))));
+
+ height = (height >> 2);
+ } else {
+ __atomic_dec(&worker_thread_busy_ARGB32);
+ goto fb;
+ }
+
+ for (int i = 0; i < worker_thread_num_ARGB32; i++) {
+ msg[i].shaderContext = shaderContext;
+ msg[i].x = x;
+ msg[i].width = width;
+ msg[i].deviceRB = (deviceRB);
+ msg[i].fShadeDirectlyIntoDevice = fShadeDirectlyIntoDevice;
+ msg[i].fConstInY = fConstInY;
+ msg[i].fXfermode = fXfermode;
+ msg[i].fProc32 = fProc32;
+ msg[i].fBuffer = NULL;
+
+ assert(work_ARGB32[i] == 0);
+ work_ARGB32[i] = &msg[i];
+
+ sem_post(&sem_todo_ARGB32[i]);
+ }
+
+ blitRect_core(
+ shaderContext,
+ x,
+ y,
+ width,
+ height,
+ device,
+ deviceRB,
+ fShadeDirectlyIntoDevice,
+ fConstInY,
+ fXfermode,
+ fProc32,
+ NULL
+ );
+
+ for (int i = 0; i < worker_thread_num_ARGB32; i++) {
+ sem_wait(&sem_done_ARGB32[i]);
+ /* Need to set to NULL value. No point in still storing addresso of local
+ * variable, after function returns
+ */
+ work_ARGB32[i] = NULL;
+ }
+ __atomic_dec(&worker_thread_busy_ARGB32);
+ }
+ else {
+ __atomic_dec(&worker_thread_busy_ARGB32);
+ goto fb;
+ }
+
+ return;
+ }
+ }
+
+
+fb:
+ blitRect_core(
+ shaderContext,
+ x,
+ y,
+ width,
+ height,
+ device,
+ deviceRB,
+ fShadeDirectlyIntoDevice,
+ fConstInY,
+ fXfermode,
+ fProc32,
+ fBuffer
+ );
+}
+
void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
SkPMColor* span = fBuffer;
diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp
index 3fd6366..08f5d2b 100644
--- a/src/core/SkRasterPipelineBlitter.cpp
+++ b/src/core/SkRasterPipelineBlitter.cpp
@@ -20,6 +20,12 @@
#include "src/core/SkUtils.h"
#include "src/shaders/SkShaderBase.h"
+#include <semaphore.h>
+#include <assert.h>
+#include <pthread.h>
+#include <cutils/log.h>
+#include <sys/sysinfo.h>
+
class SkRasterPipelineBlitter final : public SkBlitter {
public:
// This is our common entrypoint for creating the blitter once we've sorted out shaders.
@@ -77,6 +83,63 @@
typedef SkBlitter INHERITED;
};
+#define __ATOMIC_INLINE__ static __inline__ __attribute__((always_inline))
+__ATOMIC_INLINE__ int __atomic_dec(volatile int *ptr) {
+ return __sync_fetch_and_sub (ptr, 1);
+}
+__ATOMIC_INLINE__ int __atomic_inc(volatile int *ptr) {
+ return __sync_fetch_and_add (ptr, 1);
+}
+static volatile int worker_thread_inited = 0;
+static volatile int worker_thread_busy = 0;
+#define MAX_WORKER_THREADS_NUM 3
+
+static pthread_t worker_threads[MAX_WORKER_THREADS_NUM];
+sem_t sem_todo[MAX_WORKER_THREADS_NUM];
+sem_t sem_done[MAX_WORKER_THREADS_NUM];
+static volatile void* work[MAX_WORKER_THREADS_NUM] = {0};
+static int worker_thread_num = 0;
+
+extern const char* __progname;
+
+static int is_not_zygote(){
+
+ const char* buf = __progname;
+ const char* zygote = "zygote";
+ /*
+ * adb shell cat /proc/192/cmdline
+ * zygote/bin/app_process-Xzygote/system/bin--zygote--start-system-server
+ */
+ return strncmp(buf, zygote, 6);
+}
+
+struct shadeSpanArg {
+ int x;
+ int y;
+ int width;
+ int height;
+ std::function<void(size_t, size_t, size_t, size_t)> func;
+};
+
+void* worker_blitRect(void* arg) {
+ long id = (long)arg;
+ while(1) {
+ sem_wait(&sem_todo[id]);
+ if (work[id] != 0) {
+ struct shadeSpanArg* arg = (struct shadeSpanArg*)work[id];
+ int x = arg->x;
+ int y = arg->y;
+ int width = arg->width;
+ int height = arg->height;
+ if (arg->func) {
+ arg->func(x, y, width, height);
+ }
+ work[id] = 0;
+ }
+ sem_post(&sem_done[id]);
+ }
+}
+
SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
const SkPaint& paint,
const SkMatrix& ctm,
@@ -308,6 +371,85 @@
fBlitRect = p.compile();
}
+ //Disable this since some issue found
+ if (false && (w * h) > (750 * 400) && h >= 4) {
+ if (__atomic_inc(&worker_thread_busy) == 0) {
+ if (!worker_thread_inited) {
+ if (__atomic_inc(&worker_thread_inited) == 0) {
+ //Only start the other thread in non-zygote mode.
+ if (!is_not_zygote()) {
+ __atomic_dec(&worker_thread_busy);
+ __atomic_dec(&worker_thread_inited);
+ goto fb;
+ }
+ long i;
+ worker_thread_num = (get_nprocs_conf()/2 -1);
+ if (worker_thread_num > MAX_WORKER_THREADS_NUM) {
+ worker_thread_num = MAX_WORKER_THREADS_NUM;
+ } else if (worker_thread_num <= 2) {
+ worker_thread_num = 1;
+ }
+ for (i = 0; i < worker_thread_num; i++) {
+ sem_init(&sem_todo[i], 0, 0);
+ sem_init(&sem_done[i], 0, 0);
+ pthread_create(&worker_threads[i], NULL, worker_blitRect, (void *)i);
+ }
+ }
+ }
+ if (worker_thread_num > 0) {
+ struct shadeSpanArg msg[worker_thread_num];
+
+ if (worker_thread_num == 1) {
+ msg[0].y = y + (h >> 1);
+ msg[0].height = h - (h >> 1);
+
+ h = (h >> 1);
+ } else if (worker_thread_num == 3) {
+ msg[0].y = (y + (h >> 2));
+ msg[0].height = ((h >> 1) - (h >> 2));
+
+ msg[1].y = (y + (h >> 1));
+ msg[1].height = (h - (h >> 1)) >> 1;
+
+ msg[2].y = (y + (h >> 1) + ((h - (h >> 1)) >> 1));
+ msg[2].height = h - (h >> 1) - ((h - (h >> 1)) >> 1);
+
+ h = (h >> 2);
+ } else {
+ __atomic_dec(&worker_thread_busy);
+ goto fb;
+ }
+
+ for (int i = 0; i < worker_thread_num; i++) {
+ msg[i].x = x;
+ msg[i].width = w;
+ msg[i].func = fBlitRect;
+ assert( work[i] == 0);
+ work[i] = &msg[i];
+
+ sem_post(&sem_todo[i]);
+ }
+
+ fBlitRect(x,y,w,h);
+
+ for (int i = 0; i < worker_thread_num; i++) {
+ sem_wait(&sem_done[i]);
+
+ /* Need to set to NULL value. No point in still storing addresso of local
+ * variable, after function returns
+ */
+ work[i] = NULL;
+ }
+ __atomic_dec(&worker_thread_busy);
+ } else {
+ __atomic_dec(&worker_thread_busy);
+ goto fb;
+ }
+ return;
+ }
+ }
+
+fb:
fBlitRect(x,y,w,h);
}