Merge "Memory leak in parsePackage"
diff --git a/Android.mk b/Android.mk
index 1db4365..614e76d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -283,7 +283,7 @@
$(framework_res_source_path)/com/android/internal/R.java
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt core core-junit ext okhttp
+LOCAL_JAVA_LIBRARIES := core-libart conscrypt okhttp core-junit bouncycastle ext
LOCAL_MODULE := framework-base
@@ -489,9 +489,9 @@
$(framework_res_source_path)/com/android/internal/R.java
framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \
- bouncycastle \
+ core-libart \
conscrypt \
- core \
+ bouncycastle \
okhttp \
ext \
framework \
@@ -529,7 +529,7 @@
-since $(SRC_API_DIR)/17.txt 17 \
-since $(SRC_API_DIR)/18.txt 18 \
-since $(SRC_API_DIR)/19.txt 19 \
- -werror -hide 113 \
+ -werror -hide 111 -hide 113 \
-overview $(LOCAL_PATH)/core/java/overview.html
framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \
@@ -796,7 +796,7 @@
LOCAL_SRC_FILES := $(ext_src_files)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core
+LOCAL_JAVA_LIBRARIES := core-libart
LOCAL_JAVA_RESOURCE_DIRS := $(ext_res_dirs)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := ext
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index cb453e2..badaec3 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -1188,6 +1188,7 @@
data.writeInt(level);
mRemote.transact(SCHEDULE_TRIM_MEMORY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
+ data.recycle();
}
public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3d9daca..3db9ddb 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1569,7 +1569,7 @@
String locale = null;
if (mConfiguration.locale != null) {
- locale = mConfiguration.locale.toLanguageTag();
+ locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
}
int width, height;
if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1650,6 +1650,47 @@
}
}
+ // Locale.toLanguageTag() is not available in Java6. LayoutLib overrides
+ // this method to enable users to use Java6.
+ private String localeToLanguageTag(Locale locale) {
+ return locale.toLanguageTag();
+ }
+
+ /**
+ * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+ * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+ *
+ * All released versions of android prior to "L" used the deprecated language
+ * tags, so we will need to support them for backwards compatibility.
+ *
+ * Note that this conversion needs to take place *after* the call to
+ * {@code toLanguageTag} because that will convert all the deprecated codes to
+ * the new ones, even if they're set manually.
+ */
+ private static String adjustLanguageTag(String languageTag) {
+ final int separator = languageTag.indexOf('-');
+ final String language;
+ final String remainder;
+
+ if (separator == -1) {
+ language = languageTag;
+ remainder = "";
+ } else {
+ language = languageTag.substring(0, separator);
+ remainder = languageTag.substring(separator);
+ }
+
+ if ("id".equals(language)) {
+ return "in" + remainder;
+ } else if ("yi".equals(language)) {
+ return "ji" + remainder;
+ } else if ("he".equals(language)) {
+ return "iw" + remainder;
+ } else {
+ return languageTag;
+ }
+ }
+
/**
* Update the system resources configuration if they have previously
* been initialized.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 70c8750..2aff5f2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -929,6 +929,23 @@
}
/**
+ * Get the set of tethered dhcp ranges.
+ *
+ * @return an array of 0 or more Strings of tethered dhcp ranges.
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ * {@hide}
+ */
+ public String[] getTetheredDhcpRanges() {
+ try {
+ return mService.getTetheredDhcpRanges();
+ } catch (RemoteException e) {
+ return new String[0];
+ }
+ }
+
+ /**
* Get the set of tethered interfaces.
*
* @return an array of 0 or more String of currently tethered interface names.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 4bca7fe..3bfd88e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -91,6 +91,8 @@
String[] getTetherableIfaces();
+ String[] getTetheredDhcpRanges();
+
String[] getTetheredIfaces();
String[] getTetheringErroredIfaces();
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index af57507..fd1df92 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -1127,10 +1127,12 @@
/**
* Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
+ * no mapping of the desired type exists for the given key or if a null
+ * value is explicitly associated with the given key.
*
* @param key a String, or null
- * @param defaultValue Value to return if key does not exist
+ * @param defaultValue Value to return if key does not exist or if a null
+ * value is associated with the given key.
* @return the String value associated with the given key, or defaultValue
* if no valid String object is currently mapped to that key.
*/
@@ -1160,10 +1162,12 @@
/**
* Returns the value associated with the given key, or defaultValue if
- * no mapping of the desired type exists for the given key.
+ * no mapping of the desired type exists for the given key or if a null
+ * value is explicitly associatd with the given key.
*
* @param key a String, or null
- * @param defaultValue Value to return if key does not exist
+ * @param defaultValue Value to return if key does not exist or if a null
+ * value is associated with the given key.
* @return the CharSequence value associated with the given key, or defaultValue
* if no valid CharSequence object is currently mapped to that key.
*/
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index f69cad0..87e61b9 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
/**
* The Media provider contains meta data for all available media on both internal
@@ -655,6 +656,7 @@
if (sThumbBuf == null) {
sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
}
+ Arrays.fill(sThumbBuf, (byte)0);
if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
if (bitmap == null) {
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index d1f35dd..9fec9a1 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -195,7 +195,7 @@
* @return a string pattern suitable for use with {@link java.text.SimpleDateFormat}.
*/
public static String getBestDateTimePattern(Locale locale, String skeleton) {
- return ICU.getBestDateTimePattern(skeleton, locale.toString());
+ return ICU.getBestDateTimePattern(skeleton, locale);
}
/**
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 33964a0..707edef 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -62,10 +62,7 @@
*/
public static TimeZone getTimeZone(int offset, boolean dst, long when, String country) {
TimeZone best = null;
-
- Resources r = Resources.getSystem();
- XmlResourceParser parser = r.getXml(com.android.internal.R.xml.time_zones_by_country);
- Date d = new Date(when);
+ final Date d = new Date(when);
TimeZone current = TimeZone.getDefault();
String currentName = current.getID();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0d3df51..b290744 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1709,7 +1709,9 @@
Parcel p = Parcel.obtain();
writeToParcel(p, 0);
p.setDataPosition(0);
- return new RemoteViews(p);
+ RemoteViews rv = new RemoteViews(p);
+ p.recycle();
+ return rv;
}
public String getPackage() {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1f6f4cd..a61901b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -488,8 +488,8 @@
char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
- char profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold") + PROPERTY_VALUE_MAX];
- char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold") + PROPERTY_VALUE_MAX];
+ char profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold:") + PROPERTY_VALUE_MAX];
+ char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold:") + PROPERTY_VALUE_MAX];
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a19d111..42feab4 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -129,6 +129,8 @@
env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
"errorCallbackFromNative","(I)V"),
check_AudioSystem_Command(err));
+
+ env->DeleteLocalRef(clazz);
}
static jint
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 86207f0..87ee618 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -174,21 +174,21 @@
ssize_t pss = memtrack_proc_graphics_pss(p);
if (pss < 0) {
- ALOGW("failed to get graphics pss: %d", pss);
+ ALOGW("failed to get graphics pss: %zd", pss);
return pss;
}
graphics_mem->graphics = pss / 1024;
pss = memtrack_proc_gl_pss(p);
if (pss < 0) {
- ALOGW("failed to get gl pss: %d", pss);
+ ALOGW("failed to get gl pss: %zd", pss);
return pss;
}
graphics_mem->gl = pss / 1024;
pss = memtrack_proc_other_pss(p);
if (pss < 0) {
- ALOGW("failed to get other pss: %d", pss);
+ ALOGW("failed to get other pss: %zd", pss);
return pss;
}
graphics_mem->other = pss / 1024;
@@ -231,9 +231,9 @@
unsigned referenced = 0;
unsigned temp;
- unsigned long int start;
- unsigned long int end = 0;
- unsigned long int prevEnd = 0;
+ uint64_t start;
+ uint64_t end = 0;
+ uint64_t prevEnd = 0;
char* name;
int name_pos;
@@ -255,7 +255,7 @@
if (len < 1) return;
line[--len] = 0;
- if (sscanf(line, "%lx-%lx %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
+ if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
skip = true;
} else {
while (isspace(line[name_pos])) {
@@ -371,7 +371,7 @@
referenced = temp;
} else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
swapped_out = temp;
- } else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
+ } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
// looks like a new mapping
// example: "10000000-10001000 ---p 10000000 00:00 0"
break;
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 8cb897e..1722138 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -327,6 +327,7 @@
// Exception: If we find the gdbserver binary, return it.
if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+ mLastSlash = lastSlash;
break;
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index c58bf04..0cdddba 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -14,46 +14,40 @@
* limitations under the License.
*/
-#include "android_runtime/AndroidRuntime.h"
+#define LOG_TAG "Zygote"
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
#include <sys/mount.h>
#include <linux/fs.h>
#include <grp.h>
+#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
#include <unistd.h>
-#include <fcntl.h>
+#include <sys/capability.h>
+#include <sys/personality.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
-#include "cutils/fs.h"
-#include "cutils/multiuser.h"
-#include "cutils/sched_policy.h"
-#include "utils/String8.h"
+
+#include <cutils/fs.h>
+#include <cutils/multiuser.h>
+#include <cutils/sched_policy.h>
+#include <utils/String8.h>
+#include <selinux/android.h>
+
+#include "android_runtime/AndroidRuntime.h"
#include "JNIHelp.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
-#if defined(HAVE_PRCTL)
-#include <sys/prctl.h>
-#endif
-
-#include <selinux/android.h>
-
-#if defined(__linux__)
-#include <sys/personality.h>
-#include <sys/utsname.h>
-#if defined(HAVE_ANDROID_OS)
-#include <sys/capability.h>
-#endif
-#endif
-
namespace {
using android::String8;
@@ -97,11 +91,9 @@
if (WTERMSIG(status) != SIGKILL) {
ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
}
-#ifdef WCOREDUMP
if (WCOREDUMP(status)) {
ALOGI("Process %d dumped core.", pid);
}
-#endif /* ifdef WCOREDUMP */
}
// If the just-crashed process is the system_server, bring down zygote
@@ -199,8 +191,6 @@
}
}
-#if defined(HAVE_ANDROID_OS)
-
// The debug malloc library needs to know whether it's the zygote or a child.
extern "C" int gMallocLeakZygoteChild;
@@ -254,17 +244,6 @@
}
}
-#else
-
-static int gMallocLeakZygoteChild = 0;
-
-static void EnableKeepCapabilities(JNIEnv*) {}
-static void DropCapabilitiesBoundingSet(JNIEnv*) {}
-static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
-static void SetSchedulerPolicy(JNIEnv*) {}
-
-#endif
-
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
@@ -337,7 +316,6 @@
return true;
}
-#if defined(__linux__)
static bool NeedsNoRandomizeWorkaround() {
#if !defined(__arm__)
return false;
@@ -357,7 +335,6 @@
return (major < 3) || ((major == 3) && (minor < 4));
#endif
}
-#endif
// Utility to close down the Zygote socket file descriptors while
// the child is still running as root with Zygote's privileges. Each
@@ -474,7 +451,6 @@
RuntimeAbort(env);
}
-#if defined(__linux__)
if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff);
@@ -483,58 +459,49 @@
ALOGW("personality(%d) failed", new_personality);
}
}
-#endif
SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
SetSchedulerPolicy(env);
-#if defined(HAVE_ANDROID_OS)
- { // NOLINT(whitespace/braces)
- const char* se_info_c_str = NULL;
- ScopedUtfChars* se_info = NULL;
- if (java_se_info != NULL) {
- se_info = new ScopedUtfChars(env, java_se_info);
- se_info_c_str = se_info->c_str();
- if (se_info_c_str == NULL) {
- ALOGE("se_info_c_str == NULL");
- RuntimeAbort(env);
- }
- }
- const char* se_name_c_str = NULL;
- ScopedUtfChars* se_name = NULL;
- if (java_se_name != NULL) {
- se_name = new ScopedUtfChars(env, java_se_name);
- se_name_c_str = se_name->c_str();
- if (se_name_c_str == NULL) {
- ALOGE("se_name_c_str == NULL");
- RuntimeAbort(env);
- }
- }
- rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
- if (rc == -1) {
- ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
- is_system_server, se_info_c_str, se_name_c_str);
- RuntimeAbort(env);
- }
-
- // Make it easier to debug audit logs by setting the main thread's name to the
- // nice name rather than "app_process".
- if (se_info_c_str == NULL && is_system_server) {
- se_name_c_str = "system_server";
- }
- if (se_info_c_str != NULL) {
- SetThreadName(se_name_c_str);
- }
-
- delete se_info;
- delete se_name;
+ const char* se_info_c_str = NULL;
+ ScopedUtfChars* se_info = NULL;
+ if (java_se_info != NULL) {
+ se_info = new ScopedUtfChars(env, java_se_info);
+ se_info_c_str = se_info->c_str();
+ if (se_info_c_str == NULL) {
+ ALOGE("se_info_c_str == NULL");
+ RuntimeAbort(env);
+ }
}
-#else
- UNUSED(is_system_server);
- UNUSED(java_se_info);
- UNUSED(java_se_name);
-#endif
+ const char* se_name_c_str = NULL;
+ ScopedUtfChars* se_name = NULL;
+ if (java_se_name != NULL) {
+ se_name = new ScopedUtfChars(env, java_se_name);
+ se_name_c_str = se_name->c_str();
+ if (se_name_c_str == NULL) {
+ ALOGE("se_name_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+ if (rc == -1) {
+ ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+ is_system_server, se_info_c_str, se_name_c_str);
+ RuntimeAbort(env);
+ }
+
+ // Make it easier to debug audit logs by setting the main thread's name to the
+ // nice name rather than "app_process".
+ if (se_info_c_str == NULL && is_system_server) {
+ se_name_c_str = "system_server";
+ }
+ if (se_info_c_str != NULL) {
+ SetThreadName(se_name_c_str);
+ }
+
+ delete se_info;
+ delete se_name;
UnsetSigChldHandler();
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index b4d482a..87164ca 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -1747,6 +1747,7 @@
}
mergeInfoLocked(pMergedInfo, pContents);
+ delete pContents;
return true;
}
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f8d3589..b0f4c2c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -554,11 +554,8 @@
// call, any texture operation will be performed on the default
// texture (name=0)
- for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
- if (mBoundTextures[i] == texture) {
- mBoundTextures[i] = 0;
- }
- }
+ unbindTexture(texture);
+
glDeleteTextures(1, &texture);
}
@@ -566,6 +563,14 @@
memset(mBoundTextures, 0, REQUIRED_TEXTURE_UNITS_COUNT * sizeof(GLuint));
}
+void Caches::unbindTexture(GLuint texture) {
+ for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
+ if (mBoundTextures[i] == texture) {
+ mBoundTextures[i] = 0;
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Scissor
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 282aee9..544757a 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -264,6 +264,11 @@
void resetBoundTextures();
/**
+ * Clear the cache of bound textures.
+ */
+ void unbindTexture(GLuint texture);
+
+ /**
* Sets the scissor for the current surface.
*/
bool setScissor(GLint x, GLint y, GLint width, GLint height);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index bd371a3..987bf03 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -171,6 +171,7 @@
}
void Layer::clearTexture() {
+ caches.unbindTexture(texture.id);
texture.id = 0;
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index f8076cc..006d145 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -339,8 +339,10 @@
void LayerRenderer::flushLayer(Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
+ if (!layer) return;
+
GLuint fbo = layer->getFbo();
- if (layer && fbo) {
+ if (fbo) {
// If possible, discard any enqueud operations on deferred
// rendering architectures
if (Extensions::getInstance().hasDiscardFramebuffer()) {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index d5ba8c3..2f102e0 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -242,19 +242,19 @@
switch (bitmap->getConfig()) {
case SkBitmap::kA8_Config:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(),
+ uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
texture->blend = true;
break;
case SkBitmap::kRGB_565_Config:
glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
- uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(),
+ uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
texture->width, texture->height, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
texture->blend = false;
break;
case SkBitmap::kARGB_8888_Config:
glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
- uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(),
+ uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), bitmap->bytesPerPixel(),
texture->width, texture->height, GL_UNSIGNED_BYTE, bitmap->getPixels());
// Do this after calling getPixels() to make sure Skia's deferred
// decoding happened
@@ -294,27 +294,49 @@
SkCanvas canvas(rgbaBitmap);
canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL);
- uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), width, height,
- GL_UNSIGNED_BYTE, rgbaBitmap.getPixels());
+ uploadToTexture(resize, GL_RGBA, rgbaBitmap.rowBytesAsPixels(), rgbaBitmap.bytesPerPixel(),
+ width, height, GL_UNSIGNED_BYTE, rgbaBitmap.getPixels());
}
-void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride,
+void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
GLsizei width, GLsizei height, GLenum type, const GLvoid * data) {
- // TODO: With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
- // if the stride doesn't match the width
const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength();
- if (useStride) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
- }
+ if ((stride == width) || useStride) {
+ if (useStride) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
+ }
- if (resize) {
- glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+ if (resize) {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
+ }
+
+ if (useStride) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ }
} else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
- }
+ // With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
+ // if the stride doesn't match the width
- if (useStride) {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
+ if (!temp) return;
+
+ uint8_t * pDst = (uint8_t *)temp;
+ uint8_t * pSrc = (uint8_t *)data;
+ for (GLsizei i = 0; i < height; i++) {
+ memcpy(pDst, pSrc, width * bpp);
+ pDst += width * bpp;
+ pSrc += stride * bpp;
+ }
+
+ if (resize) {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp);
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
+ }
+
+ free(temp);
}
}
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 57fc19a..909d762 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -125,7 +125,7 @@
void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
void uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
- void uploadToTexture(bool resize, GLenum format, GLsizei stride,
+ void uploadToTexture(bool resize, GLenum format, GLsizei stride, GLsizei bpp,
GLsizei width, GLsizei height, GLenum type, const GLvoid * data);
void init();
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 63b149c..6364300 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -249,7 +249,8 @@
long magic = mBuffer.getLong();
int length = mBuffer.getInt();
- if (size >= 1 + 8 + 4 + length && data.length >= length) {
+ if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
+ data.length >= length) {
mBuffer.get(data, 0, length);
return data;
}
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index c2bab91..20b7ee7 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -776,10 +776,11 @@
mRS.validate();
int eSize = mType.mElement.getBytesSize();
final byte[] data = fp.getData();
+ int data_length = fp.getPos();
- int count = data.length / eSize;
- if ((eSize * count) != data.length) {
- throw new RSIllegalArgumentException("Field packer length " + data.length +
+ int count = data_length / eSize;
+ if ((eSize * count) != data_length) {
+ throw new RSIllegalArgumentException("Field packer length " + data_length +
" not divisible by element size " + eSize + ".");
}
copy1DRangeFromUnchecked(xoff, count, data);
@@ -803,16 +804,17 @@
}
final byte[] data = fp.getData();
+ int data_length = fp.getPos();
int eSize = mType.mElement.mElements[component_number].getBytesSize();
eSize *= mType.mElement.mArraySizes[component_number];
- if (data.length != eSize) {
- throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
+ if (data_length != eSize) {
+ throw new RSIllegalArgumentException("Field packer sizelength " + data_length +
" does not match component size " + eSize + ".");
}
mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
- component_number, data, data.length);
+ component_number, data, data_length);
}
private void data1DChecks(int off, int count, int len, int dataSize) {
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index aa5d687..f2f1c86 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -143,17 +143,17 @@
MATRIX_3X3 (17, 36),
MATRIX_2X2 (18, 16),
- RS_ELEMENT (1000, 4),
- RS_TYPE (1001, 4),
- RS_ALLOCATION (1002, 4),
- RS_SAMPLER (1003, 4),
- RS_SCRIPT (1004, 4),
- RS_MESH (1005, 4),
- RS_PROGRAM_FRAGMENT (1006, 4),
- RS_PROGRAM_VERTEX (1007, 4),
- RS_PROGRAM_RASTER (1008, 4),
- RS_PROGRAM_STORE (1009, 4),
- RS_FONT (1010, 4);
+ RS_ELEMENT (1000),
+ RS_TYPE (1001),
+ RS_ALLOCATION (1002),
+ RS_SAMPLER (1003),
+ RS_SCRIPT (1004),
+ RS_MESH (1005),
+ RS_PROGRAM_FRAGMENT (1006),
+ RS_PROGRAM_VERTEX (1007),
+ RS_PROGRAM_RASTER (1008),
+ RS_PROGRAM_STORE (1009),
+ RS_FONT (1010);
int mID;
int mSize;
@@ -161,6 +161,14 @@
mID = id;
mSize = size;
}
+
+ DataType(int id) {
+ mID = id;
+ mSize = 4;
+ if (RenderScript.sPointerSize == 8) {
+ mSize = 32;
+ }
+ }
}
/**
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 2ff1c28..9048c31 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -37,10 +37,15 @@
}
public FieldPacker(byte[] data) {
- mPos = 0;
+ // Advance mPos to the end of the buffer, since we are copying in the
+ // full data input.
+ mPos = data.length;
mLen = data.length;
mData = data;
mAlignment = new BitSet();
+ // TODO: We should either have an actual FieldPacker copy constructor
+ // or drop support for computing alignment like this. As it stands,
+ // subAlign() can never work correctly for copied FieldPacker objects.
}
public void align(int v) {
@@ -76,7 +81,7 @@
mPos = 0;
}
public void reset(int i) {
- if ((i < 0) || (i >= mLen)) {
+ if ((i < 0) || (i > mLen)) {
throw new RSIllegalArgumentException("out of range argument: " + i);
}
mPos = i;
@@ -234,6 +239,9 @@
if (obj != null) {
if (RenderScript.sPointerSize == 8) {
addI64(obj.getID(null));
+ addI64(0);
+ addI64(0);
+ addI64(0);
}
else {
addI32((int)obj.getID(null));
@@ -241,6 +249,9 @@
} else {
if (RenderScript.sPointerSize == 8) {
addI64(0);
+ addI64(0);
+ addI64(0);
+ addI64(0);
} else {
addI32(0);
}
@@ -600,6 +611,15 @@
return mData;
}
+ /**
+ * Get the actual length used for the FieldPacker.
+ *
+ * @hide
+ */
+ public int getPos() {
+ return mPos;
+ }
+
private final byte mData[];
private int mPos;
private int mLen;
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index a350154..7026597 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -249,6 +249,9 @@
for(int i = 0; i < 16; i ++) {
mIOBuffer.addF32(m.mMat[i]);
}
+ // Reset the buffer back to the end, since we want to flush all of
+ // the contents back (and not just what we wrote now).
+ mIOBuffer.reset(mIOBuffer.getData().length);
mAlloc.setFromFieldPacker(0, mIOBuffer);
}
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 6e944ef..09ecd3a 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -37,10 +37,12 @@
libskia \
libgui \
libui \
- libinput
+ libinput \
+ libcrypto \
LOCAL_C_INCLUDES := \
- external/skia/include/core
+ external/openssl/include \
+ external/skia/include/core \
LOCAL_MODULE:= libinputservice
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index e3a3e173..a302cd2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -48,7 +48,8 @@
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
-#include <sys/sha1.h>
+
+#include <openssl/sha.h>
/* this macro is used to tell if "bit" is set in "array"
* it selects a byte from the array, and does a boolean AND
@@ -80,14 +81,14 @@
}
static String8 sha1(const String8& in) {
- SHA1_CTX ctx;
- SHA1Init(&ctx);
- SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
- u_char digest[SHA1_DIGEST_LENGTH];
- SHA1Final(digest, &ctx);
+ SHA_CTX ctx;
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+ u_char digest[SHA_DIGEST_LENGTH];
+ SHA1_Final(digest, &ctx);
String8 out;
- for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+ for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
out.appendFormat("%02x", digest[i]);
}
return out;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b7a1a55..2d1921e 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -3297,6 +3297,11 @@
return mTethering.getTetherableIfaces();
}
+ public String[] getTetheredDhcpRanges() {
+ enforceConnectivityInternalPermission();
+ return mTethering.getTetheredDhcpRanges();
+ }
+
public String[] getTetheredIfaces() {
enforceTetherAccessPermission();
return mTethering.getTetheredIfaces();
diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java
index 9105103..9c4b7d1 100644
--- a/services/java/com/android/server/am/TaskRecord.java
+++ b/services/java/com/android/server/am/TaskRecord.java
@@ -173,6 +173,11 @@
foundFront = true;
}
}
+ if (!foundFront && numActivities > 0) {
+ // All activities of this task are finishing. As we ought to have a frontOfTask
+ // activity, make the bottom activity front.
+ mActivities.get(0).frontOfTask = true;
+ }
}
/**
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index adf1dfc..91b9b07 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -109,6 +109,7 @@
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
+ // P2P is 192.168.49.1 and 255.255.255.0
// BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
// with 255.255.255.0
@@ -117,7 +118,7 @@
"192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
"192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
"192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
- "192.168.48.2", "192.168.48.254",
+ "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
};
private String[] mDefaultDnsServers;
@@ -699,6 +700,10 @@
return retVal;
}
+ public String[] getTetheredDhcpRanges() {
+ return mDhcpRange;
+ }
+
public String[] getErroredIfaces() {
ArrayList<String> list = new ArrayList<String>();
synchronized (mPublicSync) {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index b776ce1..7981a5b 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.List;
public final class Installer {
private static final String TAG = "Installer";
@@ -335,6 +336,10 @@
}
}
+ public int pruneDexCache(String cacheSubDir) {
+ return execute("prunedexcache " + cacheSubDir);
+ }
+
public int freeCache(long freeStorageSize) {
StringBuilder builder = new StringBuilder("freecache");
builder.append(' ');
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index ab59e6a..2d5e357 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -604,10 +604,10 @@
private final AtomicLong mLastWritten = new AtomicLong(0);
private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
- private boolean mIsFirstBoot = false;
+ private boolean mIsHistoricalPackageUsageAvailable = true;
- boolean isFirstBoot() {
- return mIsFirstBoot;
+ boolean isHistoricalPackageUsageAvailable() {
+ return mIsHistoricalPackageUsageAvailable;
}
void write(boolean force) {
@@ -698,7 +698,7 @@
pkg.mLastPackageUsageTimeInMills = timeInMillis;
}
} catch (FileNotFoundException expected) {
- mIsFirstBoot = true;
+ mIsHistoricalPackageUsageAvailable = false;
} catch (IOException e) {
Log.w(TAG, "Failed to read package usage times", e);
} finally {
@@ -1433,7 +1433,26 @@
}
if (didDexOptLibraryOrTool) {
- pruneDexFiles(new File(dataDir, "dalvik-cache"));
+ // If we dexopted a library or tool, then something on the system has
+ // changed. Consider this significant, and wipe away all other
+ // existing dexopt files to ensure we don't leave any dangling around.
+ //
+ // TODO: This should be revisited because it isn't as good an indicator
+ // as it used to be. It used to include the boot classpath but at some point
+ // DexFile.isDexOptNeeded started returning false for the boot
+ // class path files in all cases. It is very possible in a
+ // small maintenance release update that the library and tool
+ // jars may be unchanged but APK could be removed resulting in
+ // unused dalvik-cache files.
+ for (String instructionSet : instructionSets) {
+ mInstaller.pruneDexCache(instructionSet);
+ }
+
+ // Additionally, delete all dex files from the root directory
+ // since there shouldn't be any there anyway, unless we're upgrading
+ // from an older OS version or a build that contained the "old" style
+ // flat scheme.
+ mInstaller.pruneDexCache(".");
}
// Collect vendor overlay packages.
@@ -1661,48 +1680,9 @@
} // synchronized (mInstallLock)
}
- private static void pruneDexFiles(File cacheDir) {
- // If we had to do a dexopt of one of the previous
- // things, then something on the system has changed.
- // Consider this significant, and wipe away all other
- // existing dexopt files to ensure we don't leave any
- // dangling around.
- //
- // Additionally, delete all dex files from the root directory
- // since there shouldn't be any there anyway.
- //
- // Note: This isn't as good an indicator as it used to be. It
- // used to include the boot classpath but at some point
- // DexFile.isDexOptNeeded started returning false for the boot
- // class path files in all cases. It is very possible in a
- // small maintenance release update that the library and tool
- // jars may be unchanged but APK could be removed resulting in
- // unused dalvik-cache files.
- File[] files = cacheDir.listFiles();
- if (files != null) {
- for (File file : files) {
- if (!file.isDirectory()) {
- Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath());
- file.delete();
- } else {
- File[] subDirList = file.listFiles();
- if (subDirList != null) {
- for (File subDirFile : subDirList) {
- final String fn = subDirFile.getName();
- if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) {
- Slog.i(TAG, "Pruning dalvik file: " + fn);
- subDirFile.delete();
- }
- }
- }
- }
- }
- }
- }
-
@Override
public boolean isFirstBoot() {
- return !mRestoredSettings || mPackageUsage.isFirstBoot();
+ return !mRestoredSettings;
}
@Override
@@ -4149,7 +4129,7 @@
// The exception is first boot of a non-eng device, which
// should do a full dexopt.
boolean eng = "eng".equals(SystemProperties.get("ro.build.type"));
- if (eng || !isFirstBoot()) {
+ if (eng || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
// TODO: add a property to control this?
long dexOptLRUThresholdInMinutes;
if (eng) {
diff --git a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
index 55dd4ab..24318df 100644
--- a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
+++ b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
@@ -42,6 +42,7 @@
private static final String seappContextsPath = "seapp_contexts";
private static final String versionPath = "selinux_version";
private static final String macPermissionsPath = "mac_permissions.xml";
+ private static final String serviceContextsPath = "service_contexts";
public SELinuxPolicyInstallReceiver() {
super("/data/security/bundle", "sepolicy_bundle", "metadata/", "version");
@@ -65,6 +66,9 @@
new File(contexts, sepolicyPath).renameTo(
new File(contexts, sepolicyPath + "_backup"));
+
+ new File(contexts, serviceContextsPath).renameTo(
+ new File(contexts, serviceContextsPath + "_backup"));
}
private void copyUpdate(File contexts) {
@@ -74,6 +78,7 @@
new File(updateDir, propertyContextsPath).renameTo(new File(contexts, propertyContextsPath));
new File(updateDir, fileContextsPath).renameTo(new File(contexts, fileContextsPath));
new File(updateDir, sepolicyPath).renameTo(new File(contexts, sepolicyPath));
+ new File(updateDir, serviceContextsPath).renameTo(new File(contexts, serviceContextsPath));
}
private int readInt(BufferedInputStream reader) throws IOException {
@@ -85,13 +90,14 @@
}
private int[] readChunkLengths(BufferedInputStream bundle) throws IOException {
- int[] chunks = new int[6];
+ int[] chunks = new int[7];
chunks[0] = readInt(bundle);
chunks[1] = readInt(bundle);
chunks[2] = readInt(bundle);
chunks[3] = readInt(bundle);
chunks[4] = readInt(bundle);
chunks[5] = readInt(bundle);
+ chunks[6] = readInt(bundle);
return chunks;
}
@@ -112,6 +118,7 @@
installFile(new File(updateDir, propertyContextsPath), stream, chunkLengths[3]);
installFile(new File(updateDir, fileContextsPath), stream, chunkLengths[4]);
installFile(new File(updateDir, sepolicyPath), stream, chunkLengths[5]);
+ installFile(new File(updateDir, serviceContextsPath), stream, chunkLengths[6]);
} finally {
IoUtils.closeQuietly(stream);
}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 0d9e4f1..b12795c 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -20,7 +20,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := core core-junit framework
+LOCAL_JAVA_LIBRARIES := core-libart core-junit framework
LOCAL_STATIC_JAVA_LIBRARIES := junit-runner
LOCAL_MODULE:= android.test.runner
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index cb68340..258d9b3 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -28,8 +28,8 @@
built_framework_dep := $(call java-lib-deps,framework-base)
built_framework_classes := $(call java-lib-files,framework-base)
-built_core_dep := $(call java-lib-deps,core)
-built_core_classes := $(call java-lib-files,core)
+built_core_dep := $(call java-lib-deps,core-libart)
+built_core_classes := $(call java-lib-files,core-libart)
built_ext_dep := $(call java-lib-deps,ext)
built_ext_classes := $(call java-lib-files,ext)
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 8b07208..a38f234 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -109,6 +109,7 @@
INetworkManagementService mNwService;
private DhcpStateMachine mDhcpStateMachine;
+ private ConnectivityManager mCm;
private P2pStateMachine mP2pStateMachine;
private AsyncChannel mReplyChannel = new AsyncChannel();
@@ -226,9 +227,6 @@
/* clients(application) information list. */
private HashMap<Messenger, ClientInfo> mClientInfoList = new HashMap<Messenger, ClientInfo>();
- /* Is chosen as a unique range to avoid conflict with
- the range defined in Tethering.java */
- private static final String[] DHCP_RANGE = {"192.168.49.2", "192.168.49.254"};
private static final String SERVER_ADDRESS = "192.168.49.1";
/**
@@ -2058,8 +2056,15 @@
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void checkAndSetConnectivityInstance() {
+ if (mCm == null) {
+ mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+ }
+
private void startDhcpServer(String intf) {
InterfaceConfiguration ifcg = null;
+ checkAndSetConnectivityInstance();
try {
ifcg = mNwService.getInterfaceConfig(intf);
ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
@@ -2067,17 +2072,30 @@
ifcg.setInterfaceUp();
mNwService.setInterfaceConfig(intf, ifcg);
/* This starts the dnsmasq server */
- mNwService.startTethering(DHCP_RANGE);
+ String[] tetheringDhcpRanges = mCm.getTetheredDhcpRanges();
+ if (mNwService.isTetheringStarted()) {
+ if (DBG) logd("Stop exist tethering and will restart it");
+ mNwService.stopTethering();
+ mNwService.tetherInterface(intf);
+ }
+ mNwService.startTethering(tetheringDhcpRanges);
} catch (Exception e) {
loge("Error configuring interface " + intf + ", :" + e);
return;
}
-
logd("Started Dhcp server on " + intf);
}
private void stopDhcpServer(String intf) {
try {
+ for (String temp : mNwService.listTetheredInterfaces()) {
+ logd("List all interfaces " + temp);
+ if (temp.compareTo(intf) != 0 ) {
+ logd("Found other tethering interface so keep tethering alive");
+ mNwService.untetherInterface(intf);
+ return;
+ }
+ }
mNwService.stopTethering();
} catch (Exception e) {
loge("Error stopping Dhcp server" + e);