LOCAL_PROTOC_FLAGS := \
-Iexternal/protobuf/src
+LOCAL_STATIC_JAVA_LIBRARIES += analytics-utils
+
LOCAL_MODULE := framework
LOCAL_DX_FLAGS := --core-library --multi-dex
+#!/system/bin/sh
# Script to start "input" on the device, which has a very rudimentary
# shell.
#
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));
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;
boolean mFinished;
boolean mStartedActivity;
private boolean mDestroyed;
+ private boolean mAppsStatistics;
private boolean mDoReportFullyDrawn = true;
private boolean mRestoredFromBundle;
}
mRestoredFromBundle = savedInstanceState != null;
mCalled = true;
+ mAppsStatistics = SystemProperties.getBoolean("persist.sys.apps_statistics", false);
}
/**
mFragments.doLoaderStart();
+ // region @android-x86-analytics
+ // screen view
+ if (mAppsStatistics) {
+ AnalyticsHelper.hitScreen(this);
+ }
+ // endregion
getApplication().dispatchActivityStarted(this);
if (mAutoFillResetNeeded) {
return Float.parseFloat(mMap.get(key));
} catch (NumberFormatException ex) {
return defaultValue;
+ } catch (NullPointerException ex) {
+ return defaultValue;
}
}
return Integer.parseInt(mMap.get(key));
} catch (NumberFormatException ex) {
return defaultValue;
+ } catch (NullPointerException ex) {
+ return defaultValue;
}
}
/*
* control.aeAvailableTargetFpsRanges
*/
- {
+ try {
List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
if (fpsRanges == null) {
throw new AssertionError("Supported FPS ranges cannot be null.");
(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);
}
/*
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;
} 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;
}
private void onTouchDown(MotionEvent ev) {
mHasPerformedLongPress = false;
mActivePointerId = ev.getPointerId(0);
+ hideSelector();
if (mTouchMode == TOUCH_MODE_OVERFLING) {
// Stopped the fling. It is a scroll.
}
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();
}
final boolean multiArch;
final boolean extractNativeLibs;
final boolean debuggable;
+ final String pkgName;
+ final String apkDir;
public static Handle create(File packageFile) throws IOException {
try {
}
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++) {
}
}
- 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");
}
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) {
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) {
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.
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,
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.)
"-DEGL_EGLEXT_PROTOTYPES",
"-DU_USING_ICU_NAMESPACE=0",
+ "-D_PRC_COMPATIBILITY_PACKAGE_",
"-Wall",
"-Werror",
"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",
--- /dev/null
+#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
--- /dev/null
+#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_
--- /dev/null
+#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__
compress(&cinfo, (uint8_t*) inYuv, offsets);
jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
return true;
}
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) {
// 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) {
}
jpeg_write_raw_data(cinfo, planes, 16);
}
+ if ((height & 0xf) != 0)
+ delete [] yRows;
delete [] uRows;
delete [] vRows;
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) {
// 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);
}
#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
}
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 {
{"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},
};
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)) {
<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>
<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>
<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>
<!-- 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>
<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" />
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"
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;
}
}
}
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;
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;
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;
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()) {
}
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");
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);
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;
}
}
@Override
public void onDestroy() {
super.onDestroy();
- mBackground = null;
+ if (mBackground != null) {
+ mBackground.recycle();
+ mBackground = null;
+ }
unloadWallpaper(true /* forgetSize */);
}
mEglConfig = chooseEglConfig();
if (mEglConfig == null) {
- throw new RuntimeException("eglConfig not initialized");
+ return false;
}
mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
* 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) {
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;
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();
@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));
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;
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;
}
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);
}
}
}
if (LOG) {
- Slog.v(TAG, "headsetName: " + headsetName +
+ Slog.i(TAG, "headsetName: " + headsetName +
(state == 1 ? " connected" : " disconnected"));
}
(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();
}
+ ", 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
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;
/** 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;
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());
new File(doubleTouchGestureEnablePath);
LocalServices.addService(InputManagerInternal.class, new LocalService());
+ mTscalObserver.startWatching();
}
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
}
if (!SELinux.restorecon(stageDir)) {
- throw new IOException("Failed to restorecon session dir: " + stageDir);
+ Slog.e(TAG, "Failed to restorecon session dir: " + stageDir);
}
}
if (!SELinux.restoreconRecursive(afterCodeFile)) {
Slog.w(TAG, "Failed to restorecon");
- return false;
}
// Reflect the rename internally
// 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
// 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);
}
#include <unistd.h>
#include <linux/ioctl.h>
#include <linux/rtc.h>
+#include <cutils/properties.h>
#include <array>
#include <memory>
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;
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));