OSDN Git Service

Merge tag 'android-8.1.0_r65' into oreo-x86 android-x86-8.1-r2
authorChih-Wei Huang <cwhuang@linux.org.tw>
Wed, 5 Jun 2019 09:28:50 +0000 (17:28 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Wed, 5 Jun 2019 09:28:50 +0000 (17:28 +0800)
Android 8.1.0 release 65

37 files changed:
Android.mk
cmds/input/input
cmds/input/src/com/android/commands/input/Input.java
core/java/android/app/Activity.java
core/java/android/hardware/Camera.java
core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
core/java/android/os/storage/DiskInfo.java
core/java/android/widget/AbsListView.java
core/java/com/android/internal/content/NativeLibraryHelper.java
core/java/com/android/internal/os/RuntimeInit.java
core/jni/Android.bp
core/jni/abipicker/ABIPicker.cpp [new file with mode: 0644]
core/jni/abipicker/ABIPicker.h [new file with mode: 0644]
core/jni/abipicker/ELFLite.h [new file with mode: 0644]
core/jni/android/graphics/YuvToJpegEncoder.cpp
core/jni/android_view_ThreadedRenderer.cpp
core/jni/com_android_internal_content_NativeLibraryHelper.cpp
core/jni/fd_utils.cpp
core/res/res/values-zh-rCN/strings.xml
core/res/res/values-zh-rHK/strings.xml
core/res/res/values-zh-rTW/strings.xml
core/res/res/values/strings.xml
core/res/res/values/symbols.xml
data/keyboards/Generic.kl
libs/hwui/renderthread/EglManager.cpp
media/java/android/media/MediaFile.java
opengl/java/android/opengl/GLSurfaceView.java
packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
services/core/java/com/android/server/WiredAccessoryManager.java
services/core/java/com/android/server/display/DisplayManagerService.java
services/core/java/com/android/server/input/InputManagerService.java
services/core/java/com/android/server/pm/PackageInstallerService.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/policy/PhoneWindowManager.java
services/core/java/com/android/server/wm/DisplayContent.java
services/core/jni/com_android_server_AlarmManagerService.cpp

index dfcfa2b..e3cc2b5 100644 (file)
@@ -623,6 +623,8 @@ LOCAL_PROTOC_OPTIMIZE_TYPE := stream
 LOCAL_PROTOC_FLAGS := \
     -Iexternal/protobuf/src
 
+LOCAL_STATIC_JAVA_LIBRARIES += analytics-utils
+
 LOCAL_MODULE := framework
 
 LOCAL_DX_FLAGS := --core-library --multi-dex
index 7f1a18e..54ab947 100755 (executable)
@@ -1,3 +1,4 @@
+#!/system/bin/sh
 # Script to start "input" on the device, which has a very rudimentary
 # shell.
 #
index 9ee11f8..a589903 100644 (file)
@@ -198,9 +198,12 @@ public class Input {
         injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
         if (longpress) {
-            injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
-                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
-                    inputSource));
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+            now = SystemClock.uptimeMillis();
         }
         injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
index 8dc558c..b3969cb 100644 (file)
@@ -126,6 +126,8 @@ import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.policy.DecorView;
 import com.android.internal.policy.PhoneWindow;
 
+import org.android_x86.analytics.AnalyticsHelper;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -759,6 +761,7 @@ public class Activity extends ContextThemeWrapper
     boolean mFinished;
     boolean mStartedActivity;
     private boolean mDestroyed;
+    private boolean mAppsStatistics;
     private boolean mDoReportFullyDrawn = true;
     private boolean mRestoredFromBundle;
 
@@ -1018,6 +1021,7 @@ public class Activity extends ContextThemeWrapper
         }
         mRestoredFromBundle = savedInstanceState != null;
         mCalled = true;
+        mAppsStatistics = SystemProperties.getBoolean("persist.sys.apps_statistics", false);
     }
 
     /**
@@ -1242,6 +1246,12 @@ public class Activity extends ContextThemeWrapper
 
         mFragments.doLoaderStart();
 
+        // region @android-x86-analytics
+        // screen view
+        if (mAppsStatistics) {
+            AnalyticsHelper.hitScreen(this);
+        }
+        // endregion
         getApplication().dispatchActivityStarted(this);
 
         if (mAutoFillResetNeeded) {
index 931b5c9..26b7d7f 100644 (file)
@@ -4180,6 +4180,8 @@ public class Camera {
                 return Float.parseFloat(mMap.get(key));
             } catch (NumberFormatException ex) {
                 return defaultValue;
+            } catch (NullPointerException ex) {
+                return defaultValue;
             }
         }
 
@@ -4189,6 +4191,8 @@ public class Camera {
                 return Integer.parseInt(mMap.get(key));
             } catch (NumberFormatException ex) {
                 return defaultValue;
+            } catch (NullPointerException ex) {
+                return defaultValue;
             }
         }
 
index 5423ca9..0063360 100644 (file)
@@ -405,7 +405,7 @@ public class LegacyMetadataMapper {
         /*
          * control.aeAvailableTargetFpsRanges
          */
-        {
+        try {
             List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
             if (fpsRanges == null) {
                 throw new AssertionError("Supported FPS ranges cannot be null.");
@@ -422,6 +422,8 @@ public class LegacyMetadataMapper {
                         (int) Math.ceil(r[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] / 1000.0));
             }
             m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
+        } catch (Exception e) {
+            Log.d(TAG, "ignore any error from getSupportedPreviewFpsRange: ", e);
         }
 
         /*
index 9114107..4497397 100644 (file)
@@ -47,6 +47,7 @@ public class DiskInfo implements Parcelable {
     public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
     public static final int FLAG_SD = 1 << 2;
     public static final int FLAG_USB = 1 << 3;
+    public static final int FLAG_CDROM = 1 << 6;
 
     public final String id;
     public final int flags;
@@ -107,6 +108,12 @@ public class DiskInfo implements Parcelable {
             } else {
                 return res.getString(com.android.internal.R.string.storage_usb_drive);
             }
+        } else if ((flags & FLAG_CDROM) != 0) {
+            if (isInteresting(label)) {
+                return res.getString(com.android.internal.R.string.storage_cdrom_label, label);
+            } else {
+                return res.getString(com.android.internal.R.string.storage_cdrom);
+            }
         } else {
             return null;
         }
index 91e2f7d..6c7455d 100644 (file)
@@ -3866,6 +3866,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
     private void onTouchDown(MotionEvent ev) {
         mHasPerformedLongPress = false;
         mActivePointerId = ev.getPointerId(0);
+        hideSelector();
 
         if (mTouchMode == TOUCH_MODE_OVERFLING) {
             // Stopped the fling. It is a scroll.
@@ -5226,17 +5227,21 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
         }
 
         mRecycler.fullyDetachScrapViews();
+        boolean selectorOnScreen = false;
         if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {
             final int childIndex = mSelectedPosition - mFirstPosition;
             if (childIndex >= 0 && childIndex < getChildCount()) {
                 positionSelector(mSelectedPosition, getChildAt(childIndex));
+                selectorOnScreen = true;
             }
         } else if (mSelectorPosition != INVALID_POSITION) {
             final int childIndex = mSelectorPosition - mFirstPosition;
             if (childIndex >= 0 && childIndex < getChildCount()) {
-                positionSelector(INVALID_POSITION, getChildAt(childIndex));
+                positionSelector(mSelectorPosition, getChildAt(childIndex));
+                selectorOnScreen = true;
             }
-        } else {
+        }
+        if (!selectorOnScreen) {
             mSelectorRect.setEmpty();
         }
 
index 83b7d2f..8fd0279 100644 (file)
@@ -77,6 +77,8 @@ public class NativeLibraryHelper {
         final boolean multiArch;
         final boolean extractNativeLibs;
         final boolean debuggable;
+        final String pkgName;
+        final String apkDir;
 
         public static Handle create(File packageFile) throws IOException {
             try {
@@ -88,19 +90,34 @@ public class NativeLibraryHelper {
         }
 
         public static Handle create(Package pkg) throws IOException {
+            String apkdir;
+            if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                apkdir = null;
+            } else {
+                apkdir = pkg.codePath;
+            }
             return create(pkg.getAllCodePaths(),
                     (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0,
                     (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0,
-                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+                    (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0, pkg.packageName, apkdir);
         }
 
         public static Handle create(PackageLite lite) throws IOException {
+            String apkdir;
+            if (lite.codePath == null ||
+                lite.codePath.startsWith("/system/") ||
+                lite.codePath.startsWith("/vendor/") ||
+                lite.codePath.startsWith("/oem/")) {
+                apkdir = null;
+            } else {
+                apkdir = lite.codePath;
+            }
             return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs,
-                    lite.debuggable);
+                    lite.debuggable, lite.packageName, apkdir);
         }
 
         private static Handle create(List<String> codePaths, boolean multiArch,
-                boolean extractNativeLibs, boolean debuggable) throws IOException {
+                boolean extractNativeLibs, boolean debuggable, String pkgName, String apkdir) throws IOException {
             final int size = codePaths.size();
             final long[] apkHandles = new long[size];
             for (int i = 0; i < size; i++) {
@@ -115,15 +132,17 @@ public class NativeLibraryHelper {
                 }
             }
 
-            return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable);
+            return new Handle(apkHandles, multiArch, extractNativeLibs, debuggable, pkgName, apkdir);
         }
 
         Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs,
-                boolean debuggable) {
+                boolean debuggable, String pkgName, String apkdir) {
             this.apkHandles = apkHandles;
             this.multiArch = multiArch;
             this.extractNativeLibs = extractNativeLibs;
             this.debuggable = debuggable;
+            this.pkgName = pkgName;
+            this.apkDir = apkdir;
             mGuard.open("close");
         }
 
@@ -198,7 +217,9 @@ public class NativeLibraryHelper {
     public static int findSupportedAbi(Handle handle, String[] supportedAbis) {
         int finalRes = NO_NATIVE_LIBRARIES;
         for (long apkHandle : handle.apkHandles) {
-            final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable);
+            final int res = nativeFindSupportedAbiReplace(apkHandle, supportedAbis,
+                    handle.debuggable, handle.pkgName, handle.apkDir);
+
             if (res == NO_NATIVE_LIBRARIES) {
                 // No native code, keep looking through all APKs.
             } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) {
@@ -220,8 +241,8 @@ public class NativeLibraryHelper {
         return finalRes;
     }
 
-    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis,
-            boolean debuggable);
+    private native static int nativeFindSupportedAbiReplace(long handle, String[] supportedAbis,
+            boolean debuggable, String pkgName, String apkdir);
 
     // Convenience method to call removeNativeBinariesFromDirLI(File)
     public static void removeNativeBinariesLI(String nativeLibraryPath) {
index 66475e4..d67c961 100644 (file)
@@ -38,6 +38,8 @@ import java.util.TimeZone;
 import java.util.logging.LogManager;
 import org.apache.harmony.luni.internal.util.TimezoneGetter;
 
+import org.android_x86.analytics.AnalyticsHelper;
+
 /**
  * Main entry point for runtime initialization.  Not for
  * public consumption.
@@ -61,6 +63,12 @@ public class RuntimeInit {
         return Log.printlns(Log.LOG_ID_CRASH, Log.ERROR, tag, msg, tr);
     }
 
+    // region @android-x86-analytics
+    // delay 120 seconds if Analytics failed to capture exception
+    private static final long ANDROID_X86_ANALYTICS_FAILED_DELAY = 120 * 1000;
+    private static long mAnalyticsEnableTime = 0;
+    // endregion
+
     /**
      * Logs a message when a thread encounters an uncaught exception. By
      * default, {@link KillApplicationHandler} will terminate this process later,
@@ -105,6 +113,23 @@ public class RuntimeInit {
                 if (mCrashing) return;
                 mCrashing = true;
 
+                // region @android-x86-analytics
+                if (System.currentTimeMillis() > mAnalyticsEnableTime &&
+                        SystemProperties.getBoolean("persist.sys.apps_statistics", false)) {
+                    try {
+                        AnalyticsHelper.captureException(
+                                ActivityThread.currentActivityThread().getSystemContext(),
+                                e,
+                                t.getName(),
+                                ActivityThread.currentPackageName());
+                    } catch (Throwable ex) {
+                        // delay some time to avoid endless loop exception
+                        mAnalyticsEnableTime =
+                                System.currentTimeMillis() + ANDROID_X86_ANALYTICS_FAILED_DELAY;
+                    }
+                }
+                // endregion
+
                 // Try to end profiling. If a profiler is running at this point, and we kill the
                 // process (below), the in-memory buffer will be lost. So try to stop, which will
                 // flush the buffer. (This makes method trace profiling useful to debug crashes.)
index c629341..f8a35df 100644 (file)
@@ -11,6 +11,7 @@ cc_library_shared {
         "-DEGL_EGLEXT_PROTOTYPES",
 
         "-DU_USING_ICU_NAMESPACE=0",
+        "-D_PRC_COMPATIBILITY_PACKAGE_",
 
         "-Wall",
         "-Werror",
@@ -34,6 +35,7 @@ cc_library_shared {
         "com_android_internal_content_NativeLibraryHelper.cpp",
         "com_google_android_gles_jni_EGLImpl.cpp",
         "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
+        "abipicker/ABIPicker.cpp",
         "android_app_Activity.cpp",
         "android_app_ApplicationLoaders.cpp",
         "android_app_NativeActivity.cpp",
diff --git a/core/jni/abipicker/ABIPicker.cpp b/core/jni/abipicker/ABIPicker.cpp
new file mode 100644 (file)
index 0000000..b20f4cd
--- /dev/null
@@ -0,0 +1,759 @@
+#define LOG_TAG "ABIPicker"
+
+#include "abipicker/ABIPicker.h"
+#include "abipicker/ELFLite.h"
+
+#include <androidfw/ZipFileRO.h>
+#include <androidfw/ZipUtils.h>
+#include <fnmatch.h>
+
+namespace android {
+#define ARR_SIZE(x)     (sizeof(x)/sizeof(x[0]))
+
+#define SO_NAME_MAX (4096)
+
+#define IMPOSSIBLE_LIB_NAME    "/mixed/"
+#define IMPOSSIBLE_LIB_LEN  (sizeof(IMPOSSIBLE_LIB_NAME)-1)
+
+#define ARMABI      "armeabi"
+#define ARMV7ABI    "armeabi-v7a"
+#define ARM64ABI    "arm64-v8a"
+#define X86ABI      "x86"
+#define X8664ABI    "x86_64"
+
+#define APK_LIB "lib/"
+#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
+//#define PICK_LOGGER //flag to debug
+#ifdef PICK_LOGGER
+#define P_LOG(...) ALOGI(__VA_ARGS__)
+#else
+#define P_LOG(...)
+#endif
+
+#define LISTPATH    "/vendor/etc/misc/"
+#define OEMWHITE    LISTPATH ".OEMWhiteList"
+#define OEMBLACK    LISTPATH ".OEMBlackList"
+#define THIRDPARTY  LISTPATH ".ThirdPartySO"
+
+// load once, hold until poweroff
+static Vector <char*> thirdPartySO;
+static Vector <char*> cfgWhite;
+static Vector <char*> cfgBlack;
+static bool thirdload = false;
+static bool whiteload = false;
+static bool blackload = false;
+
+static const char* iaRelated[] = {"intel", "intl", "atom", "x86", "x64"};
+
+void freeAllString(Vector<char*>& list) {
+    Vector<char*>::iterator it = list.begin();
+    while (it != list.end()) {
+        if (*it != NULL) {
+           P_LOG("freeAllSring  %p , %s", it, *it);
+           free(*it);
+           *it = NULL;
+        }
+        it++;
+    }
+}
+
+void getConfig(const char* cfgFile , Vector<char*>& cfgVec) {
+    int read = -1;
+    char *line = NULL;
+    size_t len = 0;
+
+    FILE* fp = fopen(cfgFile, "r");
+    if (fp == NULL) {
+        return;
+    }
+
+    freeAllString(cfgVec);
+    cfgVec.clear();
+
+    while ((read = getline(&line, &len, fp)) != -1) {
+        int i = 0 , j = 0;
+        char *cfgline = (char*)malloc(len);
+        if (cfgline == NULL) {
+           P_LOG("malloc error");
+           break;
+        }
+        for (i = 0; i < read; i++) {
+           if (!isspace(line[i])) {
+              cfgline[j++] = line[i];
+           }
+        }
+        cfgline[j] = '\0';
+        cfgVec.push_back(cfgline);
+        P_LOG("orignal %s , vec: %s ", line, cfgline);
+    }
+    free(line);
+    fclose(fp);
+}
+
+bool isInOEMWhiteList(const char* pkgName) {
+    bool result = false;
+    if (pkgName == NULL) {
+        return result;
+    }
+
+    if (!whiteload) {
+       getConfig(OEMWHITE, cfgWhite);
+       whiteload = true;
+    }
+
+    Vector<char*>::iterator it = cfgWhite.begin();
+    for (; it != cfgWhite.end(); it++) {
+       P_LOG("whitelist : %s", *it);
+       if (0 == fnmatch(*it, pkgName, 0)) {
+          ALOGI("whitelist %s by %s", pkgName, *it);
+          result = true;
+          break;
+       }
+    }
+    return result;
+}
+
+bool isInOEMBlackList(const char* pkgName) {
+    bool result = false;
+    if (pkgName == NULL) {
+        return result;
+    }
+
+    if (!blackload) {
+       getConfig(OEMBLACK,  cfgBlack);
+       blackload = true;
+    }
+
+    Vector<char*>::iterator it = cfgBlack.begin();
+    for (; it != cfgBlack.end(); it++) {
+       if (0 == fnmatch(*it, pkgName, 0)) {
+          ALOGI("blacklist %s by %s", pkgName, *it);
+          result = true;
+          break;
+       }
+    }
+    return result;
+}
+
+bool isReliableLib(Vector<char*>& libList) {
+    unsigned sz = libList.size();
+    int len = ARR_SIZE(iaRelated);
+    for (unsigned i = 0; i < sz; i++) {
+        for (int j=0; j < len; j++) {
+            char* p = NULL;
+            if (NULL != (p = strcasestr(libList[i], iaRelated[j]))) {
+                int lenIA = strlen(iaRelated[j]);
+                if (!isalpha(*(p+lenIA))) {
+                    if (!isalpha(*(p-1)) || (p == (libList[i] + 3))) {
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+static bool isValidELF(char* buffer) {
+    if (buffer[EI_MAG0] != ELFMAG0 &&
+        buffer[EI_MAG1] != ELFMAG1 &&
+        buffer[EI_MAG2] != ELFMAG2 &&
+        buffer[EI_MAG3] != ELFMAG3) {
+        return false;
+    }
+    return true;
+}
+
+// assume that x86 has the only machine-code 3, and x86_64 62
+static bool isMixedLib(char* libCur, char* buffer) {
+    bool isX86_64 = (0 == strcmp(libCur, X8664ABI)) ? true: false;
+    uint16_t machine_code = *((uint16_t*)(&buffer[ELF_MACHINE_OFFSET]));
+    bool mixed = false;
+    if (isX86_64) {
+        if (machine_code != EM_X86_64) {
+            mixed = true;
+        }
+    } else {
+        if (machine_code != EM_386) {
+            mixed = true;
+        }
+    }
+    return mixed;
+}
+
+// compare the given string with the length, igonre upper and lower
+// len must be less than the length of two string
+static bool ignoreCmp(const char* str1, const char* str2, int len){
+    assert (str1 != NULL && str2 != NULL);
+    assert ((len <= strlen(str1)) && (len <= strlen(str2)));
+    for (int i = 0 ; i < len; i++) {
+        if (str1[i] != str2[i]) {
+            if(isalpha(str1[i]) && isalpha(str2[i])
+                    && (abs((str1[i]-str2[i])) == 32)) {
+                continue;
+            }
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool isInThirdPartySOList(char* libName) {
+    assert (libName != NULL);
+    size_t libLen = strlen(libName);
+    size_t sz = thirdPartySO.size();
+    for (size_t i = 0; i < sz; i++) {
+        // thirdPartySO[i] won't be NULL
+        assert(thirdPartySO[i] != NULL);
+        size_t n = strlen(thirdPartySO[i]);
+        // three char for ".so"
+        int j = libLen - 4;
+        // now only '-' '-' and '.'found
+        while((j >= 0) && (isdigit(libName[j]) || (libName[j] == '-')
+              || (libName[j] == '_') || (libName[j] == '.'))) {
+            j--;
+        }
+        // three char for "lib" and include the name with no letters
+        if ((j == 2) || ((size_t)j == (n+2))) {
+            if (ignoreCmp(libName+3, thirdPartySO[i], n)) {
+                P_LOG("ABIpicker libName %s,In Third", libName);
+                return true;
+            }
+        }
+
+    }
+    return false;
+}
+
+static void insertionSort(Vector<char*>& list) {
+    P_LOG("in insertionSort, list size = %d\n", list.size());
+
+    for (size_t i = 1; i < list.size(); i++) {
+        int j = i - 1;
+        char* x = list[i];
+        P_LOG("sort 1. x=%s, i=%d, j=%d\n", x, i, j);
+        while (j >= 0 && (strcmp(list[j], x) > 0)) {
+            list.replaceAt(list[j], j + 1);
+            j--;
+        }
+        list.replaceAt(x, j + 1);
+    }
+}
+
+// Use armRef as a reference, compare all libraries of iaRef with all
+// libraries of armRef.If the two are match or iaRef is more, iaRef
+// will be returned with *result and true is return value. Or else,
+// *result is rawResult and false is return value
+bool ABIPicker::compare(char* armRef, char* iaRef,
+                        char* rawResult, char** result) {
+    bool ret = true;
+    *result = rawResult;
+
+    do {
+        assert(armRef != NULL);
+        if (0 == strlen(armRef)) {
+            *result = strlen(iaRef) > 0 ? iaRef : rawResult;
+            ret = strlen(iaRef) > 0 ? true : false;
+            break;
+        }
+        assert(iaRef != NULL);
+        if (0 == strlen(iaRef)) {
+            *result = armRef;
+            ret = false;
+            break;
+        }
+
+        Vector<char*>* iaRefList = getLibList(iaRef);
+        Vector<char*>* armRefList = getLibList(armRef);
+        if (iaRefList == NULL || armRefList == NULL) {
+            break;
+        }
+
+        if (isReliableLib(*iaRefList)) {
+            *result = iaRef;
+            break;
+        }
+
+        if (compareLibList(*iaRefList, *armRefList)) {
+            *result = iaRef;
+            break;
+        }
+
+        size_t iaIsvLibCount = 0;
+        size_t armIsvLibCount = 0;
+        if (!compare3rdPartyLibList(iaRef, armRef,
+                    &iaIsvLibCount, &armIsvLibCount)) {
+            *result = armRef;
+            ret = false;
+            break;
+        }
+
+        if (iaIsvLibCount > 0) {
+            *result = iaRef;
+            break;
+        }
+
+        *result = armRef;
+        ret = false;
+    } while (0);
+
+    ALOGV("%s Vs. %s, return %s\n",
+            iaRef ? iaRef : "NULL",
+            armRef ? armRef : "NULL", *result);
+    return ret;
+}
+
+bool ABIPicker::compareLibList(Vector<char*>& iaRefList,
+        Vector<char*>& armRefList) {
+
+    unsigned iaSize = iaRefList.size();
+    unsigned armSize = armRefList.size();
+    if (iaSize < armSize) {
+        return false;
+    } else if (iaSize == 0 && armSize == 0) {
+        return true;
+    }
+
+    int iaNum = 0;
+    int armNum = 0;
+    Vector<char*>::iterator itIa = iaRefList.begin();
+    Vector<char*>::iterator itArm = armRefList.begin();
+    bool isEqual = false;
+    while (itIa != iaRefList.end() && itArm != armRefList.end()) {
+        if ((iaSize-iaNum) < (armSize-armNum)) {
+            return false;
+        }
+        isEqual = false ;
+        char* armLibName = *itArm;
+        int armLen = strlen (armLibName);
+        armNum++;
+
+        while (itIa != iaRefList.end() && !isEqual) {
+            char* iaLibName = *itIa;
+            iaNum++;
+            int iaLen = strlen (iaLibName);
+            if (iaLen == armLen) {
+                if (ignoreCmp(iaLibName, armLibName, iaLen)) {
+                    isEqual = true;
+                }
+            }
+            itIa++;
+        }
+        itArm++;
+    }
+    // till the end, and the last result is equal
+    if (itArm == armRefList.end() && isEqual){
+        return true;
+    }
+
+    return false;
+}
+
+bool ABIPicker::compare3rdPartyLibList(
+                char* iaRef, char* armRef,
+                size_t* iaIsvLibCount, size_t* armIsvLibCount) {
+    bool result = true;
+
+    Vector<char*>* iaRefList = getLibList(iaRef);
+    Vector<char*>* armRefList = getLibList(armRef);
+    if (iaRefList == NULL || armRefList == NULL) {
+        return result;
+    }
+
+    if (!thirdload) {
+        getConfig(THIRDPARTY, thirdPartySO);
+        thirdload = true;
+    }
+
+    Vector<char*>* armRef3rdPartyLibList = new Vector<char*>();
+    Vector<char*>::iterator itArm = armRefList->begin();
+    while (itArm != armRefList->end()) {
+        char* armLibName = *itArm;
+        if (isInThirdPartySOList(armLibName)) {
+            armRef3rdPartyLibList->push_back(armLibName);
+        } else {
+            (*armIsvLibCount)++;
+        }
+
+        itArm++;
+    }
+
+    Vector<char*>::iterator itIa = iaRefList->begin();
+    Vector<char*>* iaRef3rdPartyLibList = new Vector<char*>();
+    while (itIa != iaRefList->end()) {
+        char* iaLibName = *itIa;
+        if (isInThirdPartySOList(iaLibName)) {
+            iaRef3rdPartyLibList->push_back(iaLibName);
+        } else {
+            (*iaIsvLibCount)++;
+        }
+
+        itIa++;
+    }
+    result = compareLibList(*iaRef3rdPartyLibList, *armRef3rdPartyLibList);
+
+    armRef3rdPartyLibList->clear();
+    delete armRef3rdPartyLibList;
+    iaRef3rdPartyLibList->clear();
+    delete iaRef3rdPartyLibList;
+    return result;
+}
+
+char* ABIPicker::getAbiName(int abi) {
+    if (abi <  0 || (unsigned)abi >= mLibList->size()) {
+        return NULL;
+    }
+
+    char* ret = NULL;
+    int index = 0;
+    Vector<struct libInfo*>::iterator it = mLibList->begin();
+    while (it != mLibList->end()) {
+        if (index == abi) {
+            ret = (*it)->abiName;
+            break;
+        }
+
+        index++;
+        it++;
+    }
+
+    return ret;
+}
+
+int ABIPicker::getAbiIndex(const char* abiName) {
+    int ret = -1;
+
+    int index = 0;
+    Vector<struct libInfo*>::iterator it = mLibList->begin();
+    while (it != mLibList->end()) {
+        if (0 == strcmp(abiName, (*it)->abiName)) {
+            ret = index;
+            break;
+        }
+
+        index++;
+        it++;
+    }
+
+    return ret;
+}
+
+Vector<char*>* ABIPicker::getLibList(const char* abiName) {
+    Vector<char*>* ret = NULL;
+    Vector<struct libInfo*>::iterator it = mLibList->begin();
+    while (it != mLibList->end()) {
+        if (0 == strcmp(abiName, (*it)->abiName)) {
+            ret = (*it)->libNameList;
+            break;
+        }
+        it++;
+    }
+    P_LOG("getLibList of %s return %p\n", abiName, ret);
+    return ret;
+}
+
+
+bool ABIPicker::isABILibValid(const char* abiName) {
+    Vector<char*>* specificAbiLibList = getLibList(abiName);
+    return ((specificAbiLibList && specificAbiLibList->size()) > 0);
+}
+
+bool ABIPicker::foundMixedELF(const char* abiName) {
+    Vector<char*>* libNameList = getLibList(abiName);
+    if (!libNameList) {
+        return false;
+    }
+    if (libNameList->size() == 0) {
+        return false;
+    }
+
+    if (0 != strcasecmp(*(libNameList->begin()), IMPOSSIBLE_LIB_NAME)) {
+        return false;
+    }
+
+    return true;
+}
+
+ABIPicker::ABIPicker(const char* pkgName, Vector<ScopedUtfChars*> abiList) {
+    mLibList = new Vector<struct libInfo*>();
+    mpkgName = strdup(pkgName);
+    if (mpkgName == NULL) {
+        P_LOG("ABIPicker Construct Allocated space fails");
+    }
+    Vector<ScopedUtfChars*>::iterator it = abiList.begin();
+    while (it != abiList.end()) {
+        if (!(*it)) {
+            break;
+        }
+
+        struct libInfo* tmp = (struct libInfo*)calloc(1,
+                sizeof(struct libInfo));
+        if (tmp == NULL) {
+           P_LOG("ABIPicker Construct Allocated space fail %s", (*it)->c_str());
+           break;
+        }
+
+        snprintf(tmp->abiName, (*it)->size() + 1, "%s", (*it)->c_str());
+        tmp->libNameList = new Vector<char*>();
+        P_LOG("ABIPicker Construct %s , libNameList: %p",
+             tmp->abiName, tmp->libNameList);
+        mLibList->push_back(tmp);
+        it++;
+    }
+}
+
+ABIPicker::~ABIPicker(void) {
+    free(mpkgName);
+    mpkgName = NULL;
+    Vector<struct libInfo*>::iterator it = mLibList->begin();
+    while (it != mLibList->end()) {
+        freeAllString(*((*it)->libNameList));
+        (*it)->libNameList->clear();
+        delete (*it)->libNameList;
+        (*it)->libNameList = NULL;
+
+        free(*it);
+        *it = NULL;
+        it++;
+    }
+    mLibList->clear();
+    delete mLibList;
+}
+
+bool ABIPicker::buildNativeLibList(void* apkHandle) {
+    bool ret = false;
+
+    if (apkHandle == NULL) {
+        ALOGE("apkHandle is NULL\n");
+        return ret;
+    }
+
+    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+    void* cookie = NULL;
+    if (!zipFile->startIteration(&cookie)) {
+        ALOGE("apk file is broken\n");
+        return ret;
+    }
+
+    ZipEntryRO next = NULL;
+    char* unCompBuff = NULL;
+    char fileName[SO_NAME_MAX + 1];
+    while ((next = zipFile->nextEntry(cookie))) {
+        if (zipFile->getEntryFileName(next, fileName, SO_NAME_MAX)) {
+            ALOGE("apk file is broken, can not get entry name\n");
+            ret = false;
+            break;
+        }
+        fileName[SO_NAME_MAX] = '\0';
+
+        // Make sure we're in the lib directory of the ZIP.
+        // find out entries with such names: "lib/xxxxxxx" or "lib/"
+        if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
+            continue;
+        }
+
+        // find out any invalid ELF file
+        uint32_t unCompLen = 0;
+        if (!zipFile->getEntryInfo(next, NULL, &unCompLen, NULL, NULL, NULL,
+                                    NULL)) {
+            ALOGE("apk file is broken, can not get entry info\n");
+            ret = false;
+            break;
+        }
+
+        if (unCompLen == 0) {
+            ALOGV("skip a empty file(%s)\n", fileName);
+            continue;
+        }
+
+        free(unCompBuff);
+        unCompBuff = NULL;
+
+        unCompBuff = (char*)malloc(unCompLen);
+        if (unCompBuff == NULL) {
+            ALOGE("malloc failed size %d\n", unCompLen);
+            ret = false;
+            break;
+        }
+        memset(unCompBuff, 0, unCompLen);
+        // THE MOST TIME COST OPERATION
+        if (!zipFile->uncompressEntry(next, unCompBuff, unCompLen)) {
+            ALOGE("%s: uncompress failed\n", fileName);
+            ret = false;
+            break;
+        }
+
+        if (!isValidELF(unCompBuff)) {
+            ALOGI("skip a fake .ELF file(%s)\n", fileName);
+            continue;
+        }
+
+        // It is a real .so file, prepare to record
+        // find abi name and focus on what we care: arm(s) and x86(s)
+        // at least lastSlash points to the end of "lib/"
+        const char* lastSlash = strrchr(fileName, '/');
+        const char* cpuAbiOffset = fileName + APK_LIB_LEN;
+        // just in case if fileName is in an abnormal format, like lib/libname,
+        // lib//libname
+        if (lastSlash <= cpuAbiOffset) {
+            ALOGI("skip a invalid lib file(%s)\n", fileName);
+            continue;
+        }
+
+        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
+        char curAbiName[ABI_NAME_MAX_LENGTH];
+        if (cpuAbiRegionSize >= ABI_NAME_MAX_LENGTH) {
+            continue;
+        }
+        snprintf(curAbiName, cpuAbiRegionSize + 1, "%s", cpuAbiOffset);
+
+        Vector<char*>* libListOfCurAbi = getLibList(curAbiName);
+        if (!libListOfCurAbi) {
+            P_LOG("getLibList of %s return NULL\n", curAbiName);
+            continue;
+        }
+
+        // mixed arm elf in lib/x86 or lib/x86_64
+        // but we don't consider a compareable scenario in lib/arm*
+        if (0 == strcmp(curAbiName, X86ABI) ||
+                0 == strcmp(curAbiName, X8664ABI)) {
+            if (!libListOfCurAbi->empty()) {
+                char* firstElement = libListOfCurAbi->itemAt(0);
+                if (0 == strcmp(firstElement, IMPOSSIBLE_LIB_NAME)) {
+                    // won't add any new into the list if found mixed
+                    // lib before
+                    P_LOG("won't count count if found mixed lib before");
+                    continue;
+                }
+            }
+
+            if (isMixedLib(curAbiName, unCompBuff)) {
+                P_LOG("found mixed lib(%s) in lib/%s/", curAbiName, fileName);
+                freeAllString(*libListOfCurAbi);
+                libListOfCurAbi->clear();
+                char* mixedLib = (char*)malloc(IMPOSSIBLE_LIB_LEN+1);
+                if (!mixedLib) {
+                    ALOGE("malloc failed size %zu", IMPOSSIBLE_LIB_LEN + 1);
+                    ret = false;
+                    break;
+                }
+                snprintf(mixedLib, (IMPOSSIBLE_LIB_LEN+1), "%s", IMPOSSIBLE_LIB_NAME);
+                mixedLib[IMPOSSIBLE_LIB_LEN] ='\0';
+                libListOfCurAbi->push_back(mixedLib);
+                continue;
+            }
+        }
+
+        // now, lastSlash should point to lib name
+        lastSlash++;
+        const size_t libNameSize = strlen(lastSlash);
+        char* curLibName = (char*)malloc(libNameSize+1);
+        if (!curLibName) {
+            ALOGE("malloc failed size %zu\n", libNameSize+1);
+            ret = false;
+            break;
+        }
+        snprintf(curLibName,libNameSize+1, "%s", lastSlash);
+        curLibName[libNameSize] = '\0';
+
+        libListOfCurAbi->push_back(curLibName);
+
+        ret = true;
+    }
+
+    free(unCompBuff);
+    unCompBuff = NULL;
+
+    zipFile->endIteration(cookie);
+
+    for (unsigned i = 0; i < mLibList->size(); i++) {
+        struct libInfo* tmp = mLibList->itemAt(i);
+        insertionSort(*(tmp->libNameList));
+    }
+    return ret;
+}
+
+int ABIPicker::pickupRightABI(int sysPrefer) {
+    char* sysPreferAbiName = getAbiName(sysPrefer);
+    if (!sysPreferAbiName) {
+        return sysPrefer;
+    }
+
+    bool is64BitPrefer = (0 == strcmp(sysPreferAbiName, X8664ABI));
+    bool x8664HasMixedELF = foundMixedELF(X8664ABI);
+    bool x86HasMixedELF = foundMixedELF(X86ABI);
+
+    bool armv7LibValid = isABILibValid(ARMV7ABI);
+    bool armv5LibValid = isABILibValid(ARMABI);
+    bool armv8LibValid = isABILibValid(ARM64ABI);
+    bool x86LibValid = x86HasMixedELF ? 0 : isABILibValid(X86ABI);
+    bool x8664LibValid = x8664HasMixedELF ? 0 : isABILibValid(X8664ABI);
+
+    // in OEMBlackList, need to be supported by bt
+    // but in case of armlib doesn't exist, we choose x86 or x86_64
+    if (isInOEMBlackList(mpkgName)) {
+        if (armv7LibValid) {
+            return getAbiIndex(ARMV7ABI);
+        } else if (armv5LibValid) {
+            return getAbiIndex(ARMABI);
+        } else if (armv8LibValid) {
+            return getAbiIndex(ARM64ABI);
+        }
+    }
+
+    char arm64Ref[ABI_NAME_MAX_LENGTH];
+    if (armv8LibValid) {
+        snprintf(arm64Ref, sizeof(ARM64ABI), "%s", ARM64ABI);
+    } else {
+        arm64Ref[0] = '\0';
+    }
+
+    char arm32Ref[ABI_NAME_MAX_LENGTH];
+    if (armv7LibValid) {
+        snprintf(arm32Ref, sizeof(ARMV7ABI), "%s", ARMV7ABI);
+    } else if (armv5LibValid) {
+        snprintf(arm32Ref, sizeof(ARMABI), "%s", ARMABI);
+    } else {
+        arm32Ref[0] = '\0';
+    }
+
+    char ia32Ref[ABI_NAME_MAX_LENGTH];
+    if (x86LibValid) {
+        snprintf(ia32Ref, sizeof(X86ABI), "%s", X86ABI);
+    } else {
+        ia32Ref[0] = '\0';
+    }
+
+    char ia64Ref[ABI_NAME_MAX_LENGTH];
+    if (x8664LibValid) {
+        snprintf(ia64Ref, ABI_NAME_MAX_LENGTH, "%s", X8664ABI);
+    } else {
+        ia64Ref[0] = '\0';
+    }
+
+    char* retAbiName = sysPreferAbiName;
+    do {
+        // # The basic rule is:
+        // - on 32 bit system, compare ia32Ref native libraries with
+        // arm32Ref native libraries. If pass, return ia32Ref .
+        // If fail, return arm32Ref.
+        // - on 64 bit system, IA has two chances. if ia64Ref native
+        // libraries can't pass the comparation with arm64Ref, we should
+        // run the comparation again with ia32Ref
+        if (is64BitPrefer) {
+            if (!compare(arm64Ref, ia64Ref, sysPreferAbiName, &retAbiName)) {
+                char rawRes[ABI_NAME_MAX_LENGTH];
+                snprintf(rawRes, ABI_NAME_MAX_LENGTH, "%s", retAbiName);
+                compare(arm32Ref, ia32Ref, rawRes, &retAbiName);
+            }
+        } else {
+            compare(arm32Ref, ia32Ref, sysPreferAbiName, &retAbiName);
+        }
+    } while (0);
+    int ret = getAbiIndex(retAbiName);
+    ALOGI("selected abi %s(%d) for %s", retAbiName, ret, mpkgName);
+    return ret;
+}
+
+}  // namespace android
diff --git a/core/jni/abipicker/ABIPicker.h b/core/jni/abipicker/ABIPicker.h
new file mode 100644 (file)
index 0000000..0b4a79f
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _ABIPICKER_H_
+#define _ABIPICKER_H_
+
+#include <jni.h>
+#include <stdlib.h>
+#include <utils/Vector.h>
+#include <sys/types.h>
+
+#include <ScopedUtfChars.h>
+
+namespace android {
+//  assumption: the length of name of any abi type in abi list,
+//  like armeabi-v7a, armeabi, x86, is not longer than 64
+#define ABI_NAME_MAX_LENGTH     (64)
+
+class ABIPicker {
+ public:
+    explicit ABIPicker(const char* pkgName,Vector<ScopedUtfChars*> abiList);
+    ~ABIPicker(void);
+
+    bool buildNativeLibList(void* apkHandle);
+    int  pickupRightABI(int sysPrefer);
+ private:
+    struct libInfo{
+        char abiName[ABI_NAME_MAX_LENGTH];
+        Vector<char*>* libNameList;
+    };
+    Vector<struct libInfo*>* mLibList;
+    char* mpkgName;
+
+    bool foundMixedELF(const char* abiName);
+    bool compare(char* armRef, char* iaRef, char* rawResult, char** result);
+    bool compareLibList(Vector<char*>& iaRefList, Vector<char*>& armRefList);
+    bool compare3rdPartyLibList( char* iaRef, char* armRef,
+            size_t* iaIsvLibCount, size_t* armIsvLibCount);
+    char*  getAbiName(int abi);
+    int    getAbiIndex(const char* abiName);
+    bool isABILibValid(const char* abiName);
+    Vector<char*>* getLibList(const char* abiName);
+};
+
+bool isInOEMWhiteList(const char* pkgName);
+}  // namespace android
+#endif  // _ABIPICKER_H_
diff --git a/core/jni/abipicker/ELFLite.h b/core/jni/abipicker/ELFLite.h
new file mode 100644 (file)
index 0000000..e609e8a
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _ELFLITE_H__
+#define _ELFLITE_H__
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+namespace android {
+#define EI_NIDENT   16   /* Size of e_ident[] */
+
+/*
+ * Fields in e_ident[]
+ */
+#define EI_MAG0     0    /* File identification byte 0 index */
+#define ELFMAG0     0x7F /* Magic number byte 0 */
+#define EI_MAG1     1    /* File identification byte 1 index */
+#define ELFMAG1     'E'  /* Magic number byte 1 */
+#define EI_MAG2     2    /* File identification byte 2 index */
+#define ELFMAG2     'L'  /* Magic number byte 2 */
+#define EI_MAG3     3    /* File identification byte 3 index */
+#define ELFMAG3     'F'  /* Magic number byte 3 */
+
+/*
+ * according to implementations of ELF Header
+ *     unsigned char e_ident[16];        // ELF "magic number"
+ *     unsigned char e_type[2];          // Identifies object file type
+ *     unsigned char e_machine[2];       // Specifies required architecture
+ */
+#define ELF_MACHINE_OFFSET  18
+
+/*
+ * Values for e_machine, which identifies the architecture.  These numbers
+ * are officially assigned by registry@sco.com.  See below for a list of
+ * ad-hoc numbers used during initial development.
+ * Please always sync them.
+ */
+#define EM_386        3 /* Intel 80386 */
+#define EM_486        6 /* Intel 80486 */
+#define EM_860        7 /* Intel 80860 */
+#define EM_960       19 /* Intel 80960 */
+#define EM_ARM       40 /* ARM */
+#define EM_IA_64     50 /* Intel IA-64 Processor */
+#define EM_X86_64    62 /* AMD x86-64 architecture */
+#define EM_8051     165 /* Intel 8051 and variants */
+#define EM_L1OM     180 /* Intel L1OM */
+#define EM_K1OM     181 /* Intel K1OM */
+#define EM_INTEL182 182 /* Reserved by Intel */
+#define EM_AARCH64  183 /* ARM 64-bit architecture */
+#define EM_ARM184   184 /* Reserved by ARM */
+#define EM_INTEL205 205 /* Reserved by Intel */
+#define EM_INTEL206 206 /* Reserved by Intel */
+#define EM_INTEL207 207 /* Reserved by Intel */
+#define EM_INTEL208 208 /* Reserved by Intel */
+#define EM_INTEL209 209 /* Reserved by Intel */
+}  // namespace android
+#endif  // _ELFLITE_H__
index 31567f7..c1430d6 100644 (file)
@@ -45,6 +45,7 @@ bool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width,
     compress(&cinfo, (uint8_t*) inYuv, offsets);
 
     jpeg_finish_compress(&cinfo);
+    jpeg_destroy_compress(&cinfo);
 
     return true;
 }
@@ -81,13 +82,19 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo,
     planes[1] = cb;
     planes[2] = cr;
 
-    int width = cinfo->image_width;
-    int height = cinfo->image_height;
+    JDIMENSION width = cinfo->image_width;
+    JDIMENSION height = cinfo->image_height;
     uint8_t* yPlanar = yuv + offsets[0];
     uint8_t* vuPlanar = yuv + offsets[1]; //width * height;
-    uint8_t* uRows = new uint8_t [8 * (width >> 1)];
-    uint8_t* vRows = new uint8_t [8 * (width >> 1)];
-
+    uint8_t* uRows = new uint8_t [8 * (((width + 15) & ~15) >> 1)];
+    uint8_t* vRows = new uint8_t [8 * (((width + 15) & ~15) >> 1)];
+    uint8_t* yRows;
+    int lastLines;
+
+    if ((height & 0xf) != 0) {
+        lastLines = height & 0xf;
+        yRows = new uint8_t [16 * ((width + 15) & ~15)];
+    }
 
     // process 16 lines of Y and 8 lines of U/V each time.
     while (cinfo->next_scanline < cinfo->image_height) {
@@ -96,8 +103,11 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo,
 
         // Jpeg library ignores the rows whose indices are greater than height.
         for (int i = 0; i < 16; i++) {
-            // y row
-            y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0];
+            // y row. Add padding if height isn't aligned to 16 pixels.
+            if ((height & 0xf) != 0 && (cinfo->next_scanline + i) > height)
+                y[i] = &yRows[(i - lastLines) * ((width + 15) & ~15)];
+            else
+                y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0];
 
             // construct u row and v row
             if ((i & 1) == 0) {
@@ -109,6 +119,8 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo,
           }
         jpeg_write_raw_data(cinfo, planes, 16);
     }
+    if ((height & 0xf) != 0)
+        delete [] yRows;
     delete [] uRows;
     delete [] vRows;
 
@@ -116,9 +128,12 @@ void Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo,
 
 void Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows,
         uint8_t* vRows, int rowIndex, int width, int height) {
-    int numRows = (height - rowIndex) / 2;
-    if (numRows > 8) numRows = 8;
-    for (int row = 0; row < numRows; ++row) {
+    int lines = 16;
+    //In case there isn't enough lines to process
+    if ((rowIndex + lines) > height)
+        lines = (height - rowIndex);
+
+    for (int row = 0; row < (lines >> 1); ++row) {
         int offset = ((rowIndex >> 1) + row) * fStrides[1];
         uint8_t* vu = vuPlanar + offset;
         for (int i = 0; i < (width >> 1); ++i) {
index e757ddd..29226c3 100644 (file)
@@ -923,6 +923,10 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(
         // Continue I guess?
     }
     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
+    if (!bitmap.get()) {
+        ALOGW("Failed to create hardware bitmap from graphic buffer");
+        return nullptr;
+    }
     return createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Mutable);
 }
 
index fce5dd5..8f6c159 100644 (file)
 
 #include <memory>
 
+#ifdef _PRC_COMPATIBILITY_PACKAGE_
+#include "abipicker/ABIPicker.h"
+#endif
+
 #define APK_LIB "lib/"
 #define APK_LIB_LEN (sizeof(APK_LIB) - 1)
 
 #define TMP_FILE_PATTERN "/tmp.XXXXXX"
 #define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1)
 
+#ifdef _PRC_COMPATIBILITY_PACKAGE_
+#define X86ABI     "x86"
+#define X8664ABI   "x86_64"
+#endif
+
 namespace android {
 
 // These match PackageManager.java install codes
@@ -509,10 +518,102 @@ com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env,
 }
 
 static jint
-com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
-        jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable)
+com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace(
+        JNIEnv *env,
+        jclass clazz,
+        jlong apkHandle,
+        jobjectArray javaCpuAbisToSearch,
+        jboolean debuggable,
+        jstring apkPkgName,
+        jstring apkDir)
 {
-    return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
+#ifdef _PRC_COMPATIBILITY_PACKAGE_
+
+    int abiType = findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
+    if (apkDir == NULL) {
+        return (jint)abiType;
+    }
+
+    char abiFlag[256] = {'\0'};
+    ScopedUtfChars apkdir(env, apkDir);
+    size_t apkdir_size = apkdir.size();
+    const int numAbis = env->GetArrayLength(javaCpuAbisToSearch);
+    Vector<ScopedUtfChars*> supportedAbis;
+
+    assert(apkdir_size < 256 - 15);
+    if (strlcpy(abiFlag, apkdir.c_str(), 256) != apkdir.size()) {
+        return (jint)abiType;
+    }
+
+    int abiIndex = 0;
+    abiFlag[apkdir_size] = '/';
+    abiFlag[apkdir_size + 1] = '.';
+    for (abiIndex = 0; abiIndex < numAbis; abiIndex++) {
+        ScopedUtfChars* abiName = new ScopedUtfChars(env,
+                 (jstring)env->GetObjectArrayElement(javaCpuAbisToSearch, abiIndex));
+        supportedAbis.push_back(abiName);
+        if (abiName == NULL || abiName->c_str() == NULL || abiName->size() <= 0) {
+            break;
+        }
+        if ((strlcpy(abiFlag + apkdir_size + 2, abiName->c_str(), 256 - apkdir_size - 2)
+                    == abiName->size()) && (access(abiFlag, F_OK) == 0)) {
+            abiType = abiIndex;
+            break;
+        }
+    }
+
+    if (abiIndex < numAbis) {
+        for (int j = 0; j < abiIndex; ++j) {
+            if (supportedAbis[j] != NULL) {
+                delete supportedAbis[j];
+            }
+        }
+        return (jint)abiType;
+    }
+
+    do {
+        if (abiType < 0 || abiType >= numAbis) {
+            break;
+        }
+
+        if (0 != strcmp(supportedAbis[abiType]->c_str(), X86ABI) &&
+                0 != strcmp(supportedAbis[abiType]->c_str(), X8664ABI)) {
+            break;
+        }
+
+        ScopedUtfChars name(env, apkPkgName);
+        if (NULL == name.c_str()) {
+            break;
+        }
+
+        if (isInOEMWhiteList(name.c_str())) {
+            break;
+        }
+
+        ABIPicker picker(name.c_str(),supportedAbis);
+        if (!picker.buildNativeLibList((void*)apkHandle)) {
+            break;
+        }
+
+        abiType = picker.pickupRightABI(abiType);
+        if (abiType >= 0 && abiType < numAbis &&
+                (strlcpy(abiFlag + apkdir_size + 2, supportedAbis[abiType]->c_str(),
+                         256 - apkdir_size - 2) == supportedAbis[abiType]->size())) {
+            int flagFp = creat(abiFlag, 0644);
+            if (flagFp != -1) {
+                close(flagFp);
+            }
+        }
+
+    } while(0);
+
+    for (int i = 0; i < numAbis; ++i) {
+        delete supportedAbis[i];
+    }
+    return (jint)abiType;
+#else
+    return (jint)findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable);
+#endif
 }
 
 enum bitcode_scan_result_t {
@@ -576,9 +677,9 @@ static const JNINativeMethod gMethods[] = {
     {"nativeSumNativeBinaries",
             "(JLjava/lang/String;Z)J",
             (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
-    {"nativeFindSupportedAbi",
-            "(J[Ljava/lang/String;Z)I",
-            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
+    {"nativeFindSupportedAbiReplace",
+            "(J[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)I",
+            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi_replace},
     {"hasRenderscriptBitcode", "(J)I",
             (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},
 };
index 956b724..5bddda7 100644 (file)
@@ -165,6 +165,8 @@ FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
   const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
   if (!android::base::Readlink(fd_path, &file_path)) {
     return NULL;
+  } else if (!strncmp(file_path.c_str(), "/android/", 9)) {
+    file_path = file_path.substr(8);
   }
 
   if (!whitelist->IsAllowed(file_path)) {
index 0c43523..78e1c46 100644 (file)
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"U 盘"</string>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> U 盘"</string>
+    <string name="storage_cdrom">"CD/DVD 光盘"</string>
+    <string name="storage_cdrom_label">"<xliff:g id="MANUFACTURER">%s</xliff:g> CD/DVD 光盘"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB存储器"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"修改"</string>
     <string name="data_usage_warning_title" msgid="3620440638180218181">"流量消耗提醒"</string>
index 2b2ea49..0373ec6 100644 (file)
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB 驅動器"</string>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB 驅動器"</string>
+    <string name="storage_cdrom">"CD/DVD 光碟機"</string>
+    <string name="storage_cdrom_label">"<xliff:g id="MANUFACTURER">%s</xliff:g> CD/DVD 光碟機"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
     <string name="data_usage_warning_title" msgid="3620440638180218181">"數據用量警告"</string>
index 4ff84e7..feb4901 100644 (file)
     <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"請先卸載「<xliff:g id="NAME">%s</xliff:g>」,再將其移除,以免資料遺失。"</string>
     <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"已移除「<xliff:g id="NAME">%s</xliff:g>」"</string>
     <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"已移除「<xliff:g id="NAME">%s</xliff:g>」;請插入新的媒體"</string>
-    <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"依然退出「<xliff:g id="NAME">%s</xliff:g>」..."</string>
+    <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"正在退出「<xliff:g id="NAME">%s</xliff:g>」..."</string>
     <string name="ext_media_unmounting_notification_message" msgid="4182843895023357756">"請勿移除"</string>
     <string name="ext_media_init_action" msgid="7952885510091978278">"設定"</string>
     <string name="ext_media_unmount_action" msgid="1121883233103278199">"退出"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB 隨身碟"</string>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB 隨身碟"</string>
+    <string name="storage_cdrom">"CD/DVD 光碟機"</string>
+    <string name="storage_cdrom_label">"<xliff:g id="MANUFACTURER">%s</xliff:g> CD/DVD 光碟機"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"編輯"</string>
     <string name="data_usage_warning_title" msgid="3620440638180218181">"數據用量警告"</string>
index ce6815f..a59b432 100644 (file)
     <!-- Storage description for a USB drive from a specific manufacturer. [CHAR LIMIT=NONE] -->
     <string name="storage_usb_drive_label"><xliff:g id="manufacturer" example="Seagate">%s</xliff:g> USB drive</string>
 
+    <!-- Storage description for a generic CDROM drive. [CHAR LIMIT=NONE] -->
+    <string name="storage_cdrom">CD/DVD drive</string>
+    <!-- Storage description for a CDROM drive from a specific manufacturer. [CHAR LIMIT=NONE] -->
+    <string name="storage_cdrom_label"><xliff:g id="manufacturer" example="ASUS">%s</xliff:g> CD/DVD drive</string>
+
     <!-- Storage description for USB storage. [CHAR LIMIT=NONE] -->
     <string name="storage_usb">USB storage</string>
 
index 15a353b..58bb175 100644 (file)
   <java-symbol type="string" name="storage_sd_card_label" />
   <java-symbol type="string" name="storage_usb_drive" />
   <java-symbol type="string" name="storage_usb_drive_label" />
+  <java-symbol type="string" name="storage_cdrom" />
+  <java-symbol type="string" name="storage_cdrom_label" />
   <java-symbol type="string" name="storage_usb" />
 
   <java-symbol type="drawable" name="ic_eject_24dp" />
index 2a10bdd..79b6c85 100644 (file)
@@ -139,13 +139,13 @@ key 116   POWER
 key 117   NUMPAD_EQUALS
 # key 118 "KEY_KPPLUSMINUS"
 key 119   BREAK
-# key 120 (undefined)
+key 120   APP_SWITCH
 key 121   NUMPAD_COMMA
 key 122   KANA
 key 123   EISU
 key 124   YEN
-key 125   META_LEFT
-key 126   META_RIGHT
+key 125   HOME
+key 126   HOME
 key 127   MENU
 key 128   MEDIA_STOP
 # key 129 "KEY_AGAIN"
index 16d7736..bd4708d 100644 (file)
@@ -223,9 +223,9 @@ void EglManager::loadConfigs() {
         numConfigs = 1;
         if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs, &numConfigs)
                 || numConfigs != 1) {
-            LOG_ALWAYS_FATAL(
-                    "Device claims wide gamut support, cannot find matching config, error = %s",
+            ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
                     eglErrorString());
+            EglExtensions.pixelFormatFloat = false;
         }
     }
 }
index fc4d15f..f2a7110 100644 (file)
@@ -43,13 +43,19 @@ public class MediaFile {
     public static final int FILE_TYPE_AAC     = 8;
     public static final int FILE_TYPE_MKA     = 9;
     public static final int FILE_TYPE_FLAC    = 10;
+    public static final int FILE_TYPE_3GPA    = 11;
+    public static final int FILE_TYPE_AC3     = 12;
+    public static final int FILE_TYPE_APE     = 13;
+    public static final int FILE_TYPE_WEBMA   = 14;
+    public static final int FILE_TYPE_PCM     = 15;
+    public static final int FILE_TYPE_DTS     = 16;
     private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
-    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC;
+    private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_DTS;
 
     // MIDI file types
-    public static final int FILE_TYPE_MID     = 11;
-    public static final int FILE_TYPE_SMF     = 12;
-    public static final int FILE_TYPE_IMY     = 13;
+    public static final int FILE_TYPE_MID     = 18;
+    public static final int FILE_TYPE_SMF     = 19;
+    public static final int FILE_TYPE_IMY     = 20;
     private static final int FIRST_MIDI_FILE_TYPE = FILE_TYPE_MID;
     private static final int LAST_MIDI_FILE_TYPE = FILE_TYPE_IMY;
 
@@ -64,8 +70,12 @@ public class MediaFile {
     public static final int FILE_TYPE_MP2TS   = 28;
     public static final int FILE_TYPE_AVI     = 29;
     public static final int FILE_TYPE_WEBM    = 30;
+    public static final int FILE_TYPE_DIVX    = 31;
+    public static final int FILE_TYPE_FLV     = 32;
+    public static final int FILE_TYPE_RV      = 33;
+    public static final int FILE_TYPE_VC1     = 34;
     private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
-    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WEBM;
+    private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_VC1;
 
     // More video file types
     public static final int FILE_TYPE_MP2PS   = 200;
@@ -74,13 +84,13 @@ public class MediaFile {
     private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_QT;
 
     // Image file types
-    public static final int FILE_TYPE_JPEG    = 31;
-    public static final int FILE_TYPE_GIF     = 32;
-    public static final int FILE_TYPE_PNG     = 33;
-    public static final int FILE_TYPE_BMP     = 34;
-    public static final int FILE_TYPE_WBMP    = 35;
-    public static final int FILE_TYPE_WEBP    = 36;
-    public static final int FILE_TYPE_HEIF    = 37;
+    public static final int FILE_TYPE_JPEG    = 61;
+    public static final int FILE_TYPE_GIF     = 62;
+    public static final int FILE_TYPE_PNG     = 63;
+    public static final int FILE_TYPE_BMP     = 64;
+    public static final int FILE_TYPE_WBMP    = 65;
+    public static final int FILE_TYPE_WEBP    = 66;
+    public static final int FILE_TYPE_HEIF    = 67;
     private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG;
     private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_HEIF;
 
@@ -191,6 +201,7 @@ public class MediaFile {
         addFileType("MPGA", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3, false);
         addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", MtpConstants.FORMAT_MPEG, false);
         addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav", MtpConstants.FORMAT_WAV, true);
+        addFileType("WAV", FILE_TYPE_PCM, "audio/wav");
         addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
         addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
         if (isWMAEnabled()) {
@@ -198,10 +209,13 @@ public class MediaFile {
         }
         addFileType("OGG", FILE_TYPE_OGG, "audio/ogg", MtpConstants.FORMAT_OGG, false);
         addFileType("OGG", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG, true);
+        addFileType("OGA", FILE_TYPE_OGG, "audio/ogg", MtpConstants.FORMAT_OGG, false);
         addFileType("OGA", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG, false);
         addFileType("AAC", FILE_TYPE_AAC, "audio/aac", MtpConstants.FORMAT_AAC, true);
         addFileType("AAC", FILE_TYPE_AAC, "audio/aac-adts", MtpConstants.FORMAT_AAC, false);
         addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska");
+        addFileType("AC3", FILE_TYPE_AC3, "audio/ac3");
+        addFileType("APE", FILE_TYPE_APE, "audio/x-ape");
 
         addFileType("MID", FILE_TYPE_MID, "audio/midi");
         addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
@@ -226,7 +240,13 @@ public class MediaFile {
         addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska");
         addFileType("WEBM", FILE_TYPE_WEBM, "video/webm");
         addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts");
+        addFileType("MPG", FILE_TYPE_MP2TS, "video/mp2ts");
         addFileType("AVI", FILE_TYPE_AVI, "video/avi");
+        addFileType("DIVX", FILE_TYPE_DIVX, "video/divx");
+        addFileType("FLV", FILE_TYPE_FLV, "video/x-flv");
+        addFileType("RM", FILE_TYPE_RV, "video/vnd.rn-realvideo");
+        addFileType("RMVB", FILE_TYPE_RV, "video/vnd.rn-realvideo");
+        addFileType("VC1", FILE_TYPE_VC1, "video/vc1");
 
         if (isWMVEnabled()) {
             addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", MtpConstants.FORMAT_WMV, true);
index 0f0a7e9..d9bdf42 100644 (file)
@@ -969,7 +969,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                     int a = findConfigAttrib(egl, display, config,
                             EGL10.EGL_ALPHA_SIZE, 0);
                     if ((r == mRedSize) && (g == mGreenSize)
-                            && (b == mBlueSize) && (a == mAlphaSize)) {
+                            && (b == mBlueSize) && (a >= mAlphaSize)) {
                         return config;
                     }
                 }
index 907a79e..104321a 100644 (file)
@@ -188,7 +188,10 @@ public class ImageWallpaper extends WallpaperService {
         @Override
         public void onDestroy() {
             super.onDestroy();
-            mBackground = null;
+            if (mBackground != null) {
+                mBackground.recycle();
+                mBackground = null;
+            }
             unloadWallpaper(true /* forgetSize */);
         }
 
@@ -778,7 +781,7 @@ public class ImageWallpaper extends WallpaperService {
 
             mEglConfig = chooseEglConfig();
             if (mEglConfig == null) {
-                throw new RuntimeException("eglConfig not initialized");
+                return false;
             }
 
             mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
index c81a876..f97d767 100644 (file)
@@ -50,10 +50,10 @@ class DisplayAdjustmentUtils {
      * for full implementation details.
      */
     private static final float[] MATRIX_INVERT_COLOR = new float[] {
-        0.402f, -0.598f, -0.599f, 0,
-       -1.174f, -0.174f, -1.175f, 0,
-       -0.228f, -0.228f,  0.772f, 0,
-             1,       1,       1, 1
+       0.0f, 0.0f, 1.0f, 0,
+       0.0f, 1.0f, 0.0f, 0,
+       1.0f, 0.0f, 0.0f, 0,
+          0,    0,    0, 1
     };
 
     public static void applyDaltonizerSetting(Context context, int userId) {
index fcda83d..3980bc6 100644 (file)
@@ -34,9 +34,11 @@ import com.android.server.input.InputManagerService.WiredAccessoryCallbacks;
 import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT;
 import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT;
 import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT;
+import static com.android.server.input.InputManagerService.SW_VIDEOOUT_INSERT;
 import static com.android.server.input.InputManagerService.SW_HEADPHONE_INSERT_BIT;
 import static com.android.server.input.InputManagerService.SW_MICROPHONE_INSERT_BIT;
 import static com.android.server.input.InputManagerService.SW_LINEOUT_INSERT_BIT;
+import static com.android.server.input.InputManagerService.SW_VIDEOOUT_INSERT_BIT;
 
 import java.io.File;
 import java.io.FileReader;
@@ -111,8 +113,11 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
             if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LINEOUT_INSERT) == 1) {
                 switchValues |= SW_LINEOUT_INSERT_BIT;
             }
+            if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_VIDEOOUT_INSERT) == 1) {
+                switchValues |= SW_VIDEOOUT_INSERT_BIT;
+            }
             notifyWiredAccessoryChanged(0, switchValues,
-                    SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT);
+                    SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT | SW_VIDEOOUT_INSERT_BIT);
         }
 
         mObserver.init();
@@ -120,7 +125,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
 
     @Override
     public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
-        if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
+        if (LOG) Slog.i(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
                 + " bits=" + switchCodeToString(switchValues, switchMask)
                 + " mask=" + Integer.toHexString(switchMask));
 
@@ -128,7 +133,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
             int headset;
             mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
             switch (mSwitchValues &
-                (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {
+                (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT | SW_VIDEOOUT_INSERT_BIT)) {
                 case 0:
                     headset = 0;
                     break;
@@ -141,6 +146,11 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
                     headset = BIT_LINEOUT;
                     break;
 
+                case SW_VIDEOOUT_INSERT_BIT:
+                case SW_VIDEOOUT_INSERT_BIT | SW_LINEOUT_INSERT_BIT:
+                    headset = BIT_HDMI_AUDIO;
+                    break;
+
                 case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:
                     headset = BIT_HEADSET;
                     break;
@@ -155,7 +165,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
             }
 
             updateLocked(NAME_H2W,
-                (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
+                (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT | BIT_HDMI_AUDIO)) | headset);
         }
     }
 
@@ -285,7 +295,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
             }
 
             if (LOG) {
-                Slog.v(TAG, "headsetName: " + headsetName +
+                Slog.i(TAG, "headsetName: " + headsetName +
                         (state == 1 ? " connected" : " disconnected"));
             }
 
@@ -308,6 +318,14 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
                 (switchValues & SW_MICROPHONE_INSERT_BIT) != 0) {
             sb.append("SW_MICROPHONE_INSERT");
         }
+        if ((switchMask & SW_LINEOUT_INSERT_BIT) != 0 &&
+                (switchValues & SW_LINEOUT_INSERT_BIT) != 0) {
+            sb.append("SW_LINEOUT_INSERT ");
+        }
+        if ((switchMask & SW_VIDEOOUT_INSERT_BIT) != 0 &&
+                (switchValues & SW_VIDEOOUT_INSERT_BIT) != 0) {
+            sb.append("SW_VIDEOOUT_INSERT ");
+        }
         return sb.toString();
     }
 
index d0a1d9e..093b4c4 100644 (file)
@@ -467,7 +467,9 @@ public final class DisplayManagerService extends SystemService {
                             + ", brightness=" + brightness + ")");
                     mGlobalDisplayState = state;
                     mGlobalDisplayBrightness = brightness;
-                    applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
+                    if (state != Display.STATE_OFF) {
+                        applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
+                    }
                 }
 
                 // Setting the display power state can take hundreds of milliseconds
index fa9b107..af96ad3 100644 (file)
@@ -71,6 +71,7 @@ import android.hardware.input.TouchCalibration;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.FileObserver;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -294,6 +295,9 @@ public class InputManagerService extends IInputManager.Stub
     /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
     public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
 
+    /** Switch code: Video out jack.  When set, something is inserted. */
+    public static final int SW_VIDEOOUT_INSERT = 0x08;
+
     /** Switch code: Camera lens cover. When set the lens is covered. */
     public static final int SW_CAMERA_LENS_COVER = 0x09;
 
@@ -309,13 +313,27 @@ public class InputManagerService extends IInputManager.Stub
     public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
     public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
     public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
+    public static final int SW_VIDEOOUT_INSERT_BIT = 1 << SW_VIDEOOUT_INSERT;
     public static final int SW_JACK_BITS =
-            SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
+            SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT | SW_VIDEOOUT_INSERT_BIT;
     public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
 
     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
     final boolean mUseDevInputEventForAudioJack;
 
+    private class TscalObserver extends FileObserver {
+        public TscalObserver() {
+            super("/data/misc/tscal/pointercal", CLOSE_WRITE);
+        }
+
+        @Override
+        public void onEvent(int event, String path) {
+            Slog.i(TAG, "detect pointercal changed");
+            reloadDeviceAliases();
+        }
+    }
+    private final TscalObserver mTscalObserver = new TscalObserver();
+
     public InputManagerService(Context context) {
         this.mContext = context;
         this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
@@ -332,6 +350,7 @@ public class InputManagerService extends IInputManager.Stub
             new File(doubleTouchGestureEnablePath);
 
         LocalServices.addService(InputManagerInternal.class, new LocalService());
+        mTscalObserver.startWatching();
     }
 
     public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
index 1fa37b9..ee246ec 100644 (file)
@@ -663,7 +663,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
         }
 
         if (!SELinux.restorecon(stageDir)) {
-            throw new IOException("Failed to restorecon session dir: " + stageDir);
+            Slog.e(TAG, "Failed to restorecon session dir: " + stageDir);
         }
     }
 
index d6b5728..b37f56a 100644 (file)
@@ -16996,7 +16996,6 @@ public class PackageManagerService extends IPackageManager.Stub
 
             if (!SELinux.restoreconRecursive(afterCodeFile)) {
                 Slog.w(TAG, "Failed to restorecon");
-                return false;
             }
 
             // Reflect the rename internally
index d3469c2..247cc68 100644 (file)
@@ -2266,7 +2266,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
         // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
         // http://developer.android.com/guide/practices/screens_support.html#range
-        mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
+        mForceDefaultOrientation = /* longSizeDp >= 960 && shortSizeDp >= 720 && */
                 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
                 // For debug purposes the next line turns this feature off with:
                 // $ adb shell setprop config.override_forced_orient true
index ba99f38..73187d5 100644 (file)
@@ -1622,12 +1622,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
         final int orientation = mDisplayInfo.rotation;
         boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+        boolean forcedOrientation = mService.mPolicy.isDefaultOrientationForced();
         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
         int width = mDisplayInfo.logicalWidth;
-        int left = (physWidth - width) / 2;
+        int left = forcedOrientation ? 0 : (physWidth - width) / 2;
         int height = mDisplayInfo.logicalHeight;
-        int top = (physHeight - height) / 2;
+        int top = forcedOrientation ? 0 : (physHeight - height) / 2;
         out.set(left, top, left + width, top + height);
     }
 
index bcb0b4f..fdb62e9 100644 (file)
@@ -38,6 +38,7 @@
 #include <unistd.h>
 #include <linux/ioctl.h>
 #include <linux/rtc.h>
+#include <cutils/properties.h>
 
 #include <array>
 #include <memory>
@@ -121,7 +122,7 @@ int AlarmImpl::set(int type, struct timespec *ts)
 int AlarmImpl::setTime(struct timeval *tv)
 {
     struct rtc_time rtc;
-    struct tm tm, *gmtime_res;
+    struct tm tm, *localtime_res, *gmtime_res;
     int fd;
     int res;
 
@@ -144,11 +145,23 @@ int AlarmImpl::setTime(struct timeval *tv)
         return res;
     }
 
-    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
-    if (!gmtime_res) {
-        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
-        res = -1;
-        goto done;
+    // @jide when persist.rtc_local_time is set to 1, we store the localtime to rtc
+    //
+    bool rtc_local_time = property_get_bool("persist.rtc_local_time", false);
+    if (rtc_local_time) {
+        localtime_res = localtime_r(&tv->tv_sec, &tm);
+        if (!localtime_res) {
+            ALOGV("localtime_r() failed: %s\n", strerror(errno));
+            res = -1;
+            goto done;
+        }
+    } else {
+        gmtime_res = gmtime_r(&tv->tv_sec, &tm);
+        if (!gmtime_res) {
+            ALOGV("gmtime_r() failed: %s\n", strerror(errno));
+            res = -1;
+            goto done;
+        }
     }
 
     memset(&rtc, 0, sizeof(rtc));