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);
}
/*
}
/**
+ * Whether a UID belongs to a system core component or not.
+ * @hide
+ */
+ public static boolean isCore(int uid) {
+ if (uid >= 0) {
+ final int appId = getAppId(uid);
+ return appId < Process.FIRST_APPLICATION_UID;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Returns the user for a given uid.
* @param uid A uid for an application running in a particular user.
* @return A {@link UserHandle} for that user.
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;
}
public static final int FEATURES_WIFI = 0x8;
/**
+ * Indicates the call underwent Assisted Dialing.
+ * @hide
+ */
+ public static final Integer FEATURES_ASSISTED_DIALING_USED = 0x10;
+
+ /**
* The phone number as the user entered it.
* <P>Type: TEXT</P>
*/
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();
}
private static final boolean DEBUG = true;
+ public static final int THRESHOLD_COLOR_LIGHT = 0xffe0e0e0;
public static final int MAIN_COLOR_LIGHT = 0xffe0e0e0;
public static final int SECONDARY_COLOR_LIGHT = 0xff9e9e9e;
- public static final int MAIN_COLOR_DARK = 0xff212121;
+ public static final int THRESHOLD_COLOR_DARK = 0xff212121;
+ public static final int MAIN_COLOR_DARK = 0xff000000;
public static final int SECONDARY_COLOR_DARK = 0xff000000;
private final TonalPalette mGreyPalette;
// light fallback or darker than our dark fallback.
ColorUtils.colorToHSL(mainColor, mTmpHSL);
final float mainLuminosity = mTmpHSL[2];
- ColorUtils.colorToHSL(MAIN_COLOR_LIGHT, mTmpHSL);
+ ColorUtils.colorToHSL(THRESHOLD_COLOR_LIGHT, mTmpHSL);
final float lightLuminosity = mTmpHSL[2];
if (mainLuminosity > lightLuminosity) {
return false;
}
- ColorUtils.colorToHSL(MAIN_COLOR_DARK, mTmpHSL);
+ ColorUtils.colorToHSL(THRESHOLD_COLOR_DARK, mTmpHSL);
final float darkLuminosity = mTmpHSL[2];
if (mainLuminosity < darkLuminosity) {
return false;
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)) {
}
message DiskStatsCachedValuesProto {
- // Total app data size, in kilobytes
+ // Total app code size, in kilobytes
int64 agg_apps_size = 1;
// Total app cache size, in kilobytes
int64 agg_apps_cache_size = 2;
int64 other_size = 8;
// Sizes of individual packages
repeated DiskStatsAppSizesProto app_sizes = 9;
+ // Total app data size, in kilobytes
+ int64 agg_apps_data_size = 10;
}
message DiskStatsAppSizesProto {
// Name of the package
string package_name = 1;
- // App's data size in kilobytes
+ // App's code size in kilobytes
int64 app_size = 2;
// App's cache size in kilobytes
int64 cache_size = 3;
+ // App's data size in kilobytes
+ int64 app_data_size = 4;
}
message DiskStatsFreeSpaceProto {
<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"
lastErrorName = "UNKNOWN";
}
}
- LOG_ALWAYS_FATAL_IF(lastError != GL_NO_ERROR,
+ ALOGE_IF(lastError != GL_NO_ERROR,
"%s error! %s (0x%x)", apicall, lastErrorName, lastError);
}
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;
}
}
}
private List<String> getSettingsNamesLocked(int settingsType, int userId) {
- boolean instantApp;
- if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
- instantApp = false;
- } else {
- ApplicationInfo ai = getCallingApplicationInfoOrThrow();
- instantApp = ai.isInstantApp();
- }
- if (instantApp) {
- return new ArrayList<String>(getInstantAppAccessibleSettings(settingsType));
- } else {
- return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
- }
+ // Don't enforce the instant app whitelist for now -- its too prone to unintended breakage
+ // in the current form.
+ return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
}
private void enforceSettingReadable(String settingName, int settingsType, int userId) {
}
if (!getInstantAppAccessibleSettings(settingsType).contains(settingName)
&& !getOverlayInstantAppAccessibleSettings(settingsType).contains(settingName)) {
- throw new SecurityException("Setting " + settingName + " is not accessible from"
- + " ephemeral package " + getCallingPackage());
+ // Don't enforce the instant app whitelist for now -- its too prone to unintended
+ // breakage in the current form.
+ Slog.w(LOG_TAG, "Instant App " + ai.packageName
+ + " trying to access unexposed setting, this will be an error in the future.");
}
}
@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);
@Override
protected boolean isLightsOut(int mode) {
- return super.isLightsOut(mode) || (mAutoDim && !mWallpaperVisible);
+ return super.isLightsOut(mode) || (mAutoDim && !mWallpaperVisible
+ && mode != MODE_WARNING);
}
public LightBarTransitionsController getLightTransitionsController() {
// ok, everyone, stop it right there
navButtons.animate().cancel();
- final float navButtonsAlpha = lightsOut ? 0.6f : 1f;
+ // Bump percentage by 10% if dark.
+ float darkBump = mLightTransitionsController.getCurrentDarkIntensity() / 10;
+ final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f;
if (!animate) {
navButtons.setAlpha(navButtonsAlpha);
for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
+ if (mAutoDim) {
+ applyLightsOut(false, true);
+ }
}
private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() {
// OS: O MR
AUTOFILL_SERVICE_DISABLED_SELF = 1135;
- // Counter showing how long it took (in ms) to show the autofill UI after a field was focused
+ // Reports how long it took to show the autofill UI after a field was focused
+ // Tag FIELD_AUTOFILL_DURATION: Duration in ms
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Package: Package of the autofill service
// OS: O MR
// OS: O MR
COLOR_MODE_SETTINGS = 1143;
+ // Enclosing category for group of APP_TRANSITION_FOO events,
+ // logged when we cancel an app transition.
+ APP_TRANSITION_CANCELLED = 1144;
+
+ // Tag of a field representing a duration on autofill-related metrics.
+ FIELD_AUTOFILL_DURATION = 1145;
+
// ---- End O-MR1 Constants, all O-MR1 constants go above this line ----
+ // ACTION: Stop an app and turn on background check
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_APP_STOP_AND_BACKGROUND_CHECK = 1233;
+
+ // FIELD: The action type for each anomaly
+ // CATEGORY: SETTINGS
+ // OS: P
+ FIELD_ANOMALY_ACTION_TYPE = 1234;
+
+ // OPEN: Settings -> Battery -> Wakelock anomaly
+ // CATEGORY: SETTINGS
+ // OS: P
+ ANOMALY_TYPE_WAKELOCK = 1235;
+
+ // OPEN: Settings -> Battery -> Wakeup alarm anomaly
+ // CATEGORY: SETTINGS
+ // OS: P
+ ANOMALY_TYPE_WAKEUP_ALARM = 1236;
+
+ // OPEN: Settings -> Battery -> Unoptimized bt anomaly
+ // CATEGORY: SETTINGS
+ // OS: P
+ ANOMALY_TYPE_UNOPTIMIZED_BT = 1237;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
// Count of connection attempts that were initiated unsuccessfully
optional int32 num_open_network_connect_message_failed_to_send = 82;
+
+ // Histogram counting instances of scans with N many HotSpot 2.0 R1 APs
+ repeated NumConnectableNetworksBucket observed_hotspot_r1_aps_in_scan_histogram = 83;
+
+ // Histogram counting instances of scans with N many HotSpot 2.0 R2 APs
+ repeated NumConnectableNetworksBucket observed_hotspot_r2_aps_in_scan_histogram = 84;
+
+ // Histogram counting instances of scans with N many unique HotSpot 2.0 R1 ESS.
+ // Where ESS is defined as the (HESSID, ANQP Domain ID), (SSID, ANQP Domain ID) or
+ // (SSID, BSSID) tuple depending on AP configuration (in the above priority
+ // order).
+ repeated NumConnectableNetworksBucket observed_hotspot_r1_ess_in_scan_histogram = 85;
+
+ // Histogram counting instances of scans with N many unique HotSpot 2.0 R2 ESS.
+ // Where ESS is defined as the (HESSID, ANQP Domain ID), (SSID, ANQP Domain ID) or
+ // (SSID, BSSID) tuple depending on AP configuration (in the above priority
+ // order).
+ repeated NumConnectableNetworksBucket observed_hotspot_r2_ess_in_scan_histogram = 86;
+
+ // Histogram counting number of HotSpot 2.0 R1 APs per observed ESS in a scan
+ // (one value added per unique ESS - potentially multiple counts per single
+ // scan!)
+ repeated NumConnectableNetworksBucket observed_hotspot_r1_aps_per_ess_in_scan_histogram = 87;
+
+ // Histogram counting number of HotSpot 2.0 R2 APs per observed ESS in a scan
+ // (one value added per unique ESS - potentially multiple counts per single
+ // scan!)
+ repeated NumConnectableNetworksBucket observed_hotspot_r2_aps_per_ess_in_scan_histogram = 88;
}
// Information that gets logged for every WiFi connection.
// Framework initiated disconnect. Sometimes generated to give an extra reason for a disconnect
// Should typically be followed by a NETWORK_DISCONNECTION_EVENT with a local_gen = true
TYPE_FRAMEWORK_DISCONNECT = 15;
+
+ // The NetworkAgent score for wifi has changed in a way that may impact
+ // connectivity
+ TYPE_SCORE_BREACH = 16;
}
enum FrameworkDisconnectReason {
// Authentication failure reason, as reported by WifiManager (calculated from state & deauth code)
optional AuthFailureReason auth_failure_reason = 13 [default = AUTH_FAILURE_UNKNOWN];
+
+ // NetworkAgent score of connected wifi
+ optional int32 last_score = 14 [default = -1];
}
// Wi-Fi Aware metrics
* 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) {
mUiLatencyHistory.log(historyLog.toString());
final LogMaker metricsLog = newLogMaker(MetricsEvent.AUTOFILL_UI_LATENCY)
- .setCounterValue((int) duration);
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, duration);
mMetricsLogger.write(metricsLog);
}
}
JSONObject json = new JSONObject(jsonString);
pw.print("App Size: ");
pw.println(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY));
+ pw.print("App Data Size: ");
+ pw.println(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY));
pw.print("App Cache Size: ");
pw.println(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY));
pw.print("Photos Size: ");
pw.println(json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY));
pw.print("App Sizes: ");
pw.println(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY));
+ pw.print("App Data Sizes: ");
+ pw.println(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY));
pw.print("Cache Sizes: ");
pw.println(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY));
} catch (IOException | JSONException e) {
proto.write(DiskStatsCachedValuesProto.AGG_APPS_SIZE,
json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY));
+ proto.write(DiskStatsCachedValuesProto.AGG_APPS_DATA_SIZE,
+ json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY));
proto.write(DiskStatsCachedValuesProto.AGG_APPS_CACHE_SIZE,
json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY));
proto.write(DiskStatsCachedValuesProto.PHOTOS_SIZE,
JSONArray packageNamesArray = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
JSONArray appSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
+ JSONArray appDataSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY);
JSONArray cacheSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
final int len = packageNamesArray.length();
- if (len == appSizesArray.length() && len == cacheSizesArray.length()) {
+ if (len == appSizesArray.length()
+ && len == appDataSizesArray.length()
+ && len == cacheSizesArray.length()) {
for (int i = 0; i < len; i++) {
long packageToken = proto.start(DiskStatsCachedValuesProto.APP_SIZES);
proto.write(DiskStatsAppSizesProto.PACKAGE_NAME,
packageNamesArray.getString(i));
proto.write(DiskStatsAppSizesProto.APP_SIZE, appSizesArray.getLong(i));
+ proto.write(DiskStatsAppSizesProto.APP_DATA_SIZE, appDataSizesArray.getLong(i));
proto.write(DiskStatsAppSizesProto.CACHE_SIZE, cacheSizesArray.getLong(i));
proto.end(packageToken);
}
} else {
- Slog.wtf(TAG, "Sizes of packageNamesArray, appSizesArray and cacheSizesArray "
- + "are not the same");
+ Slog.wtf(TAG, "Sizes of packageNamesArray, appSizesArray, appDataSizesArray "
+ + " and cacheSizesArray are not the same");
}
proto.end(cachedValuesToken);
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();
}
try {
if (AppGlobals.getPackageManager().checkPermission(
android.Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
- r.appInfo.packageName,
- r.appInfo.uid) != PackageManager.PERMISSION_GRANTED) {
+ r.appInfo.packageName, UserHandle.getUserId(r.appInfo.uid))
+ != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Instant app " + r.appInfo.packageName
+ " does not have permission to create foreground"
+ "services");
static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
static final boolean DEBUG_WHITELISTS = DEBUG_ALL || false;
+ static final boolean DEBUG_METRICS = DEBUG_ALL || false;
static final String POSTFIX_ADD_REMOVE = (APPEND_CATEGORY_NAME) ? "_AddRemove" : "";
static final String POSTFIX_APP = (APPEND_CATEGORY_NAME) ? "_App" : "";
@Override
public boolean isAppForeground(int uid) throws RemoteException {
+ int callerUid = Binder.getCallingUid();
+ if (UserHandle.isCore(callerUid) || callerUid == uid) {
+ return isAppForegroundInternal(uid);
+ }
+ return false;
+ }
+
+ private boolean isAppForegroundInternal(int uid) {
synchronized (this) {
UidRecord uidRec = mActiveUids.get(uid);
if (uidRec == null || uidRec.idle) {
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CANCELLED;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_METRICS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.metrics.LogMaker;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
private static final long INVALID_START_TIME = -1;
+ private static final int MSG_CHECK_VISIBILITY = 0;
+
// Preallocated strings we are sending to tron, so we don't have to allocate a new one every
// time we log.
private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>();
private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>();
+ private final H mHandler;
+ private final class H extends Handler {
+
+ public H(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_CHECK_VISIBILITY:
+ final SomeArgs args = (SomeArgs) msg.obj;
+ checkVisibility((TaskRecord) args.arg1, (ActivityRecord) args.arg2);
+ break;
+ }
+ }
+ };
private final class StackTransitionInfo {
private ActivityRecord launchedActivity;
private boolean loggedStartingWindowDrawn;
}
- ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
+ ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context, Looper looper) {
mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
mSupervisor = supervisor;
mContext = context;
+ mHandler = new H(looper);
}
void logWindowState() {
*/
void notifyActivityLaunching() {
if (!isAnyTransitionActive()) {
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunching");
mCurrentTransitionStartTime = SystemClock.uptimeMillis();
mLastTransitionStartTime = mCurrentTransitionStartTime;
}
private void notifyActivityLaunched(int resultCode, ActivityRecord launchedActivity,
boolean processRunning, boolean processSwitch) {
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched"
+ + " resultCode=" + resultCode
+ + " launchedActivity=" + launchedActivity
+ + " processRunning=" + processRunning
+ + " processSwitch=" + processSwitch);
+
// If we are already in an existing transition, only update the activity name, but not the
// other attributes.
final int stackId = launchedActivity != null && launchedActivity.getStack() != null
return;
}
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched successful");
+
final StackTransitionInfo newInfo = new StackTransitionInfo();
newInfo.launchedActivity = launchedActivity;
newInfo.currentTransitionProcessRunning = processRunning;
* Notifies the tracker that all windows of the app have been drawn.
*/
void notifyWindowsDrawn(int stackId, long timestamp) {
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn stackId=" + stackId);
+
final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
if (info == null || info.loggedWindowsDrawn) {
return;
if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
return;
}
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
mCurrentTransitionDelayMs = calculateDelay(timestamp);
mLoggedTransitionStarting = true;
for (int index = stackIdReasons.size() - 1; index >= 0; index--) {
* Notifies the tracker that the visibility of an app is changing.
*
* @param activityRecord the app that is changing its visibility
- * @param visible whether it's going to be visible or not
*/
- void notifyVisibilityChanged(ActivityRecord activityRecord, boolean visible) {
+ void notifyVisibilityChanged(ActivityRecord activityRecord) {
final StackTransitionInfo info = mStackTransitionInfo.get(activityRecord.getStackId());
+ if (info == null) {
+ return;
+ }
+ if (info.launchedActivity != activityRecord) {
+ return;
+ }
+ final TaskRecord t = activityRecord.getTask();
+ final SomeArgs args = SomeArgs.obtain();
+ args.arg1 = t;
+ args.arg2 = activityRecord;
+ mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
+ }
- // If we have an active transition that's waiting on a certain activity that will be
- // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
- if (info != null && !visible && info.launchedActivity == activityRecord) {
- mStackTransitionInfo.remove(activityRecord.getStackId());
- if (mStackTransitionInfo.size() == 0) {
- reset(true /* abort */);
+ private void checkVisibility(TaskRecord t, ActivityRecord r) {
+ synchronized (mSupervisor.mService) {
+
+ final StackTransitionInfo info = mStackTransitionInfo.get(r.getStackId());
+
+ // If we have an active transition that's waiting on a certain activity that will be
+ // invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
+ if (info != null && !t.isVisible()) {
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible"
+ + " activity=" + r);
+ logAppTransitionCancel(info);
+ mStackTransitionInfo.remove(r.getStackId());
+ if (mStackTransitionInfo.size() == 0) {
+ reset(true /* abort */);
+ }
}
}
}
}
private void reset(boolean abort) {
+ if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
if (!abort && isAnyTransitionActive()) {
logAppTransitionMultiEvents();
}
return (int) (timestamp - mCurrentTransitionStartTime);
}
+ private void logAppTransitionCancel(StackTransitionInfo info) {
+ final int type = getTransitionType(info);
+ if (type == -1) {
+ return;
+ }
+ final LogMaker builder = new LogMaker(APP_TRANSITION_CANCELLED);
+ builder.setPackageName(info.launchedActivity.packageName);
+ builder.setType(type);
+ builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
+ mMetricsLogger.write(builder);
+ }
+
private void logAppTransitionMultiEvents() {
+ if (DEBUG_METRICS) Slog.i(TAG, "logging transition events");
for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
final StackTransitionInfo info = mStackTransitionInfo.valueAt(index);
final int type = getTransitionType(info);
void setVisibility(boolean visible) {
mWindowContainerController.setVisibility(visible, mDeferHidingClient);
- mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
+ mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this);
}
// TODO: Look into merging with #setVisibility()
public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
mService = service;
mHandler = new ActivityStackSupervisorHandler(looper);
- mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
+ mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, looper);
mKeyguardController = new KeyguardController(service, this);
}
mService.mActivityStarter.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */,
targetActivity);
mActivityMetricsLogger.notifyActivityLaunching();
- mService.moveTaskToFrontLocked(task.taskId, 0, bOptions, true /* fromRecents */);
- mActivityMetricsLogger.notifyActivityLaunched(ActivityManager.START_TASK_TO_FRONT,
- targetActivity);
+ try {
+ mService.moveTaskToFrontLocked(task.taskId, 0, bOptions,
+ true /* fromRecents */);
+ } finally {
+ mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
+ targetActivity);
+ }
// If we are launching the task in the docked stack, put it into resizing mode so
// the window renders full-screen with the background filling the void. Also only
return null;
}
+ boolean isVisible() {
+ for (int i = mActivities.size() - 1; i >= 0; --i) {
+ final ActivityRecord r = mActivities.get(i);
+ if (r.visible) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
if (mStack != null) {
for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
+ ", 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) {
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Build;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
protected final String TAG = getClass().getSimpleName();
protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
protected static final String ENABLED_SERVICES_SEPARATOR = ":";
/**
private final IPackageManager mPm;
private final UserManager mUm;
private final Config mConfig;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
// contains connections to all connected services, including app services
// and system services
private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
// things that will be put into mServices as soon as they're ready
private final ArrayList<String> mServicesBinding = new ArrayList<>();
+ private final ArraySet<String> mServicesRebinding = new ArraySet<>();
+
// lists the component names of all enabled (and therefore potentially connected)
// app services for current profiles.
private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
final String servicesBindingTag = name.toString() + "/" + userid;
if (mServicesBinding.contains(servicesBindingTag)) {
+ Slog.v(TAG, "Not registering " + name + " as bind is already in progress");
// stop registering this thing already! we're working on it
return;
}
boolean added = false;
ManagedServiceInfo info = null;
synchronized (mMutex) {
+ mServicesRebinding.remove(servicesBindingTag);
mServicesBinding.remove(servicesBindingTag);
try {
mService = asInterface(binder);
mServicesBinding.remove(servicesBindingTag);
Slog.v(TAG, getCaption() + " connection lost: " + name);
}
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ Slog.w(TAG, getCaption() + " binding died: " + name);
+ synchronized (mMutex) {
+ mServicesBinding.remove(servicesBindingTag);
+ mContext.unbindService(this);
+ if (!mServicesRebinding.contains(servicesBindingTag)) {
+ mServicesRebinding.add(servicesBindingTag);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ registerService(name, userid);
+ }
+ }, ON_BINDING_DIED_REBIND_DELAY_MS);
+ } else {
+ Slog.v(TAG, getCaption() + " not rebinding as "
+ + "a previous rebind attempt was made: " + name);
+ }
+ }
+ }
};
if (!mContext.bindServiceAsUser(intent,
serviceConnection,
}
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
PackageStats packageStats = new PackageStats(app.packageName,
user.id);
packageStats.cacheSize = storageStats.getCacheBytes();
- packageStats.codeSize = storageStats.getCodeBytes();
+ packageStats.codeSize = storageStats.getAppBytes();
packageStats.dataSize = storageStats.getDataBytes();
stats.add(packageStats);
} catch (NameNotFoundException | IOException e) {
public static final String SYSTEM_KEY = "systemSize";
public static final String MISC_KEY = "otherSize";
public static final String APP_SIZE_AGG_KEY = "appSize";
+ public static final String APP_DATA_SIZE_AGG_KEY = "appDataSize";
public static final String APP_CACHE_AGG_KEY = "cacheSize";
public static final String PACKAGE_NAMES_KEY = "packageNames";
public static final String APP_SIZES_KEY = "appSizes";
public static final String APP_CACHES_KEY = "cacheSizes";
+ public static final String APP_DATA_KEY = "appDataSizes";
public static final String LAST_QUERY_TIMESTAMP_KEY = "queryTime";
private MeasurementResult mResult;
private void addAppsToJson(JSONObject json) throws JSONException {
JSONArray names = new JSONArray();
JSONArray appSizeList = new JSONArray();
+ JSONArray appDataSizeList = new JSONArray();
JSONArray cacheSizeList = new JSONArray();
long appSizeSum = 0L;
+ long appDataSizeSum = 0L;
long cacheSizeSum = 0L;
boolean isExternal = Environment.isExternalStorageEmulated();
for (Map.Entry<String, PackageStats> entry : filterOnlyPrimaryUser().entrySet()) {
PackageStats stat = entry.getValue();
- long appSize = stat.codeSize + stat.dataSize;
+ long appSize = stat.codeSize;
+ long appDataSize = stat.dataSize;
long cacheSize = stat.cacheSize;
if (isExternal) {
- appSize += stat.externalCodeSize + stat.externalDataSize;
+ appSize += stat.externalCodeSize;
+ appDataSize += stat.externalDataSize;
cacheSize += stat.externalCacheSize;
}
appSizeSum += appSize;
+ appDataSizeSum += appDataSize;
cacheSizeSum += cacheSize;
names.put(stat.packageName);
appSizeList.put(appSize);
+ appDataSizeList.put(appDataSize);
cacheSizeList.put(cacheSize);
}
json.put(PACKAGE_NAMES_KEY, names);
json.put(APP_SIZES_KEY, appSizeList);
json.put(APP_CACHES_KEY, cacheSizeList);
+ json.put(APP_DATA_KEY, appDataSizeList);
json.put(APP_SIZE_AGG_KEY, appSizeSum);
json.put(APP_CACHE_AGG_KEY, cacheSizeSum);
+ json.put(APP_DATA_SIZE_AGG_KEY, appDataSizeSum);
}
/**
// 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));
assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(3L);
assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(10L);
assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(7L);
- assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(15L);
+ assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(10L);
+ assertThat(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)).isEqualTo(5L);
assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(55L);
assertThat(
json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(1L);
assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(1L);
+ assertThat(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY).length()).isEqualTo(1L);
assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(1L);
}
*/
public static final int PROPERTY_SELF_MANAGED = 0x00000100;
+ /**
+ * Indicates the call used Assisted Dialing.
+ * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
+ * @hide
+ */
+ public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00000200
+ // Next PROPERTY value: 0x00000400
//******************************************************************************************
private final String mTelecomCallId;
if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
}
+ if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
+ builder.append(" PROPERTY_ASSISTED_DIALING_USED");
+ }
builder.append("]");
return builder.toString();
}
@TestApi
public static final int PROPERTY_IS_RTT = 1 << 8;
+ /**
+ * Set by the framework to indicate that a connection is using assisted dialing.
+ * @hide
+ */
+ public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9;
+
//**********************************************************************************************
- // Next PROPERTY value: 1<<9
+ // Next PROPERTY value: 1<<10
//**********************************************************************************************
/**
"android.telecom.extra.CALL_BACK_INTENT";
/**
+ * The boolean indicated by this extra controls whether or not a call is eligible to undergo
+ * assisted dialing. This extra is stored under {@link #EXTRA_OUTGOING_CALL_EXTRAS}.
+ * @hide
+ */
+ public static final String EXTRA_USE_ASSISTED_DIALING =
+ "android.telecom.extra.USE_ASSISTED_DIALING";
+
+ /**
* The following 4 constants define how properties such as phone numbers and names are
* displayed to the user.
*/
"notify_handover_video_from_wifi_to_lte_bool";
/**
+ * Flag specifying whether the carrier wants to notify the user when a VT call has been handed
+ * over from LTE to WIFI.
+ * <p>
+ * The handover notification is sent as a
+ * {@link TelephonyManager#EVENT_HANDOVER_VIDEO_FROM_LTE_TO_WIFI}
+ * {@link android.telecom.Connection} event, which an {@link android.telecom.InCallService}
+ * should use to trigger the display of a user-facing message.
+ * @hide
+ */
+ public static final String KEY_NOTIFY_HANDOVER_VIDEO_FROM_LTE_TO_WIFI_BOOL =
+ "notify_handover_video_from_lte_to_wifi_bool";
+
+ /**
* Flag specifying whether the carrier supports downgrading a video call (tx, rx or tx/rx)
* directly to an audio call.
* @hide
sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VT_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
+ sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_LTE_TO_WIFI_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
"android.telephony.event.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE";
/**
+ * {@link android.telecom.Connection} event used to indicate that an IMS call has be
+ * successfully handed over from LTE to WIFI.
+ * <p>
+ * Sent via {@link android.telecom.Connection#sendConnectionEvent(String, Bundle)}.
+ * The {@link Bundle} parameter is expected to be null when this connection event is used.
+ * @hide
+ */
+ public static final String EVENT_HANDOVER_VIDEO_FROM_LTE_TO_WIFI =
+ "android.telephony.event.EVENT_HANDOVER_VIDEO_FROM_LTE_TO_WIFI";
+
+ /**
* {@link android.telecom.Connection} event used to indicate that an IMS call failed to be
* handed over from LTE to WIFI.
* <p>
/** @hide */
public int peerId;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof PeerHandle)) {
+ return false;
+ }
+
+ return peerId == ((PeerHandle) o).peerId;
+ }
+
+ @Override
+ public int hashCode() {
+ return peerId;
+ }
}