OSDN Git Service

bootanimation: performance/speedup enhancements
authorMaria Yu <aiquny@codeaurora.org>
Tue, 14 Jan 2014 05:56:53 +0000 (13:56 +0800)
committerSteve Kondik <shade@chemlab.org>
Fri, 23 Sep 2016 16:20:18 +0000 (09:20 -0700)
Bootanimation: Fix the low memory device oom when run boot animation

Low memory device is easily to be oom when run boot animation. Here
we do optimize the boot animation GL Texture only one frame needed.
That is free timely and re-init it again. When in boot animation,
the fps=15, so it is ok to do the delete and re-init.

CRs-Fixed: 572325
Change-Id: I1e81c3d0f3600ac895f9bd7bd00a284f3d4b7d4c

bootanimation: Fix compilation warnings

Change-Id: Iaf7e66811f3cecf8b5b1fa690941489a7a07f7fd

bootanimation: performance/speedup enhancements (squashed from CM11)

bootanim: Don't cache textures if they're expected to use a lot of VRAM (rmcc)
https://github.com/CyanogenMod/android_frameworks_base/commit/14f9eecd3f543a25c4a2053d6155a9396a777a3a#cmds/bootanimation

bootanimation: performance enhancements (turl)
https://github.com/CyanogenMod/android_frameworks_base/commit/e6b54405aa70d7503a114d9c90ef7518abdd7133#cmds/bootanimation

bootanimation: fix usage of LOGW (intervigilium)
https://github.com/CyanogenMod/android_frameworks_base/commit/e45cf7d232490f44aecf8f2447220a8b5ace4c10#cmds/bootanimation

bootanimation: allow using RGB565 instead of ARGB8888 (tpruvot)
https://github.com/CyanogenMod/android_frameworks_base/commit/204282870a9c69b04ad5ddecd73fafbd7996cbc0#cmds/bootanimation

Change-Id: I203fa23f77d1349fb822a7662e2cd3998ba4c814

bootanimation: Do not free frame map

The frame map is reused when needSaveMem==true, resulting in a double
free and segfault.

The only side effect would seem to be failure to cleanup all resources
at exit.  That's acceptable, as the kernel will do it anyway.

Note that in 12.1, the frame map release commit was reverted by CAF in
commit I535330edb636f9457beed0849147168eaa6ae2ec, which results in the
same behavior.

Change-Id: I4ea66dccd1f5c9d784701242fba8700bce271579

bootanimation: Switch to readahead

Change-Id: I287132e311e96c0437df67c76b86bb47b8f8380e

[mikeioannina]: Adjust for cm-14.0

Change-Id: I203fa23f77d1349fb822a7662e2cd3998ba4c814

cmds/bootanimation/Android.mk
cmds/bootanimation/BootAnimation.cpp

index a215149..0e64811 100644 (file)
@@ -27,6 +27,22 @@ LOCAL_SHARED_LIBRARIES := \
     libregionalization \
     libmedia
 
+ifeq ($(TARGET_BOOTANIMATION_PRELOAD),true)
+    LOCAL_CFLAGS += -DPRELOAD_BOOTANIMATION
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_TEXTURE_CACHE),true)
+    LOCAL_CFLAGS += -DNO_TEXTURE_CACHE=0
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_TEXTURE_CACHE),false)
+    LOCAL_CFLAGS += -DNO_TEXTURE_CACHE=1
+endif
+
+ifeq ($(TARGET_BOOTANIMATION_USE_RGB565),true)
+    LOCAL_CFLAGS += -DUSE_565
+endif
+
 LOCAL_MODULE:= bootanimation
 
 LOCAL_INIT_RC := bootanim.rc
index ff4ab62..411df30 100644 (file)
@@ -27,6 +27,7 @@
 #include <time.h>
 #include <pthread.h>
 #include <sys/select.h>
+#include <sys/syscall.h>
 
 #include <cutils/properties.h>
 
@@ -118,6 +119,57 @@ class MPlayerListener : public MediaPlayerListener
     }
 };
 
+static unsigned long getFreeMemory(void)
+{
+    int fd = open("/proc/meminfo", O_RDONLY);
+    const char* const sums[] = { "MemFree:", "Cached:", NULL };
+    const size_t sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
+    unsigned int num = 2;
+
+    if (fd < 0) {
+        ALOGW("Unable to open /proc/meminfo");
+        return -1;
+    }
+
+    char buffer[256];
+    const int len = read(fd, buffer, sizeof(buffer)-1);
+    close(fd);
+
+    if (len < 0) {
+        ALOGW("Unable to read /proc/meminfo");
+        return -1;
+    }
+    buffer[len] = 0;
+
+    size_t numFound = 0;
+    unsigned long mem = 0;
+
+    char* p = buffer;
+    while (*p && numFound < num) {
+        int i = 0;
+        while (sums[i]) {
+            if (strncmp(p, sums[i], sumsLen[i]) == 0) {
+                p += sumsLen[i];
+                while (*p == ' ') p++;
+                char* num = p;
+                while (*p >= '0' && *p <= '9') p++;
+                if (*p != 0) {
+                    *p = 0;
+                    p++;
+                    if (*p == 0) p--;
+                }
+                mem += atoll(num);
+                numFound++;
+                break;
+            }
+            i++;
+        }
+        p++;
+    }
+
+    return numFound > 0 ? mem : -1;
+}
+
 BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true) {
     mSession = new SurfaceComposerClient();
 }
@@ -217,16 +269,15 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
     if (codec != NULL) {
         codec->setDitherImage(false);
         codec->decode(&stream, &bitmap,
+                #ifdef USE_565
+                kRGB_565_SkColorType,
+                #else
                 kN32_SkColorType,
+                #endif
                 SkImageDecoder::kDecodePixels_Mode);
         delete codec;
     }
 
-    // FileMap memory is never released until application exit.
-    // Release it now as the texture is already loaded and the memory used for
-    // the packed resource can be released.
-    delete frame.map;
-
     // ensure we can call getPixels(). No need to call unlock, since the
     // bitmap will go out of scope when we return from this method.
     bitmap.lockPixels();
@@ -482,6 +533,33 @@ status_t BootAnimation::readyToRun() {
     else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0) {
         mZipFileName = getAnimationFileName(IMG_SYS);
     }
+
+#ifdef PRELOAD_BOOTANIMATION
+    // Preload the bootanimation zip on memory, so we don't stutter
+    // when showing the animation
+    FILE* fd;
+    if (encryptedAnimation && access(getAnimationFileName(IMG_ENC), R_OK) == 0)
+        fd = fopen(getAnimationFileName(IMG_ENC), "r");
+    else if (access(getAnimationFileName(IMG_OEM), R_OK) == 0)
+        fd = fopen(getAnimationFileName(IMG_OEM), "r");
+    else if (access(getAnimationFileName(IMG_SYS), R_OK) == 0)
+        fd = fopen(getAnimationFileName(IMG_SYS), "r");
+    else
+        return NO_ERROR;
+
+    if (fd != NULL) {
+        // Since including fcntl.h doesn't give us the wrapper, use the syscall.
+        // 32 bits takes LO/HI offset (we don't care about endianness of 0).
+#if defined(__aarch64__) || defined(__x86_64__)
+        if (syscall(__NR_readahead, fd, 0, INT_MAX))
+#else
+        if (syscall(__NR_readahead, fd, 0, 0, INT_MAX))
+#endif
+            ALOGW("Unable to cache the animation");
+        fclose(fd);
+    }
+#endif
+
     return NO_ERROR;
 }
 
@@ -882,8 +960,34 @@ bool BootAnimation::playAnimation(const Animation& animation)
     for (size_t i=0 ; i<pcount ; i++) {
         const Animation::Part& part(animation.parts[i]);
         const size_t fcount = part.frames.size();
+
+        // can be 1, 0, or not set
+        #ifdef NO_TEXTURE_CACHE
+        const int noTextureCache = NO_TEXTURE_CACHE;
+        #else
+        const int noTextureCache =
+                ((animation.width * animation.height * fcount) > 48 * 1024 * 1024) ? 1 : 0;
+        #endif
+
         glBindTexture(GL_TEXTURE_2D, 0);
 
+        // Calculate if we need to save memory by disabling texture cache
+        // If free memory is less than the max texture size, cache will be disabled
+        GLint mMaxTextureSize;
+        bool needSaveMem = false;
+        GLuint mTextureid;
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+        ALOGD("Free memory: %ld, max texture size: %d", getFreeMemory(), mMaxTextureSize);
+        if (getFreeMemory() < mMaxTextureSize * mMaxTextureSize * fcount / 1024 ||
+                noTextureCache) {
+            ALOGD("Disabled bootanimation texture cache, FPS drops might occur.");
+            needSaveMem = true;
+            glGenTextures(1, &mTextureid);
+            glBindTexture(GL_TEXTURE_2D, mTextureid);
+            glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        }
+
         // Handle animation package
         if (part.animation != NULL) {
             playAnimation(*part.animation);
@@ -912,10 +1016,10 @@ bool BootAnimation::playAnimation(const Animation& animation)
                 const Animation::Frame& frame(part.frames[j]);
                 nsecs_t lastFrame = systemTime();
 
-                if (r > 0) {
+                if (r > 0 && !needSaveMem) {
                     glBindTexture(GL_TEXTURE_2D, frame.tid);
                 } else {
-                    if (part.count != 1) {
+                    if (!needSaveMem && part.count != 1) {
                         glGenTextures(1, &frame.tid);
                         glBindTexture(GL_TEXTURE_2D, frame.tid);
                         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -972,12 +1076,16 @@ bool BootAnimation::playAnimation(const Animation& animation)
         }
 
         // free the textures for this part
-        if (part.count != 1) {
+        if (!needSaveMem && part.count != 1) {
             for (size_t j=0 ; j<fcount ; j++) {
                 const Animation::Frame& frame(part.frames[j]);
                 glDeleteTextures(1, &frame.tid);
             }
         }
+
+        if (needSaveMem) {
+            glDeleteTextures(1, &mTextureid);
+        }
     }
 
     property_get("persist.sys.silent", value, "null");