Merge "Transplant the Logging system from Telecom"
diff --git a/api/current.txt b/api/current.txt
index 125e113..b391b00 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29169,6 +29169,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -29181,6 +29182,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
}
public static final class StrictMode.VmPolicy {
@@ -51763,6 +51765,8 @@
enum_constant public static final java.lang.annotation.ElementType PACKAGE;
enum_constant public static final java.lang.annotation.ElementType PARAMETER;
enum_constant public static final java.lang.annotation.ElementType TYPE;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
}
public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -51844,7 +51848,7 @@
method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
- method public default <T extends java.lang.annotation.Annotation> java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+ method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
@@ -59113,8 +59117,10 @@
method public java.util.Set<java.lang.String> getUnicodeLocaleKeys();
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
+ method public boolean hasExtensions();
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
+ method public java.util.Locale stripExtensions();
method public java.lang.String toLanguageTag();
method public final java.lang.String toString();
field public static final java.util.Locale CANADA;
diff --git a/api/system-current.txt b/api/system-current.txt
index 6dc2bcf..68c7b48 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -31637,6 +31637,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -31649,6 +31650,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
}
public static final class StrictMode.VmPolicy {
@@ -55120,6 +55122,8 @@
enum_constant public static final java.lang.annotation.ElementType PACKAGE;
enum_constant public static final java.lang.annotation.ElementType PARAMETER;
enum_constant public static final java.lang.annotation.ElementType TYPE;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
}
public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -55201,7 +55205,7 @@
method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
- method public default <T extends java.lang.annotation.Annotation> java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+ method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
@@ -62470,8 +62474,10 @@
method public java.util.Set<java.lang.String> getUnicodeLocaleKeys();
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
+ method public boolean hasExtensions();
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
+ method public java.util.Locale stripExtensions();
method public java.lang.String toLanguageTag();
method public final java.lang.String toString();
field public static final java.util.Locale CANADA;
diff --git a/api/test-current.txt b/api/test-current.txt
index 941790e..2aa6cfe 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -29238,6 +29238,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeath();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDeathOnNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder penaltyDialog();
@@ -29250,6 +29251,7 @@
method public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
method public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
method public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
+ method public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
}
public static final class StrictMode.VmPolicy {
@@ -51843,6 +51845,8 @@
enum_constant public static final java.lang.annotation.ElementType PACKAGE;
enum_constant public static final java.lang.annotation.ElementType PARAMETER;
enum_constant public static final java.lang.annotation.ElementType TYPE;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_PARAMETER;
+ enum_constant public static final java.lang.annotation.ElementType TYPE_USE;
}
public class IncompleteAnnotationException extends java.lang.RuntimeException {
@@ -51924,7 +51928,7 @@
method public abstract <T extends java.lang.annotation.Annotation> T getAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(java.lang.Class<T>);
- method public default <T extends java.lang.annotation.Annotation> java.lang.annotation.Annotation getDeclaredAnnotation(java.lang.Class<T>);
+ method public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(java.lang.Class<T>);
method public abstract java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(java.lang.Class<T>);
method public default boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
@@ -59193,8 +59197,10 @@
method public java.util.Set<java.lang.String> getUnicodeLocaleKeys();
method public java.lang.String getUnicodeLocaleType(java.lang.String);
method public java.lang.String getVariant();
+ method public boolean hasExtensions();
method public static synchronized void setDefault(java.util.Locale);
method public static synchronized void setDefault(java.util.Locale.Category, java.util.Locale);
+ method public java.util.Locale stripExtensions();
method public java.lang.String toLanguageTag();
method public final java.lang.String toString();
field public static final java.util.Locale CANADA;
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index e530184..b5f1c2a 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -62,7 +62,6 @@
LOCAL_LDFLAGS := -ldl
LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
-LOCAL_CPPFLAGS := -std=c++11
LOCAL_MODULE := app_process__asan
LOCAL_MULTILIB := both
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index fa70c3f..ce54637 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -892,6 +892,14 @@
return false;
}
+ /** @hide */
+ public boolean isBondingInitiatedLocally() {
+ try {
+ return sService.isBondingInitiatedLocally(this);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
/**
* Set the Out Of Band data for a remote device to be used later
* in the pairing mechanism. Users can obtain this data through other
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index a420539..8c98536 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -62,6 +62,7 @@
boolean cancelBondProcess(in BluetoothDevice device);
boolean removeBond(in BluetoothDevice device);
int getBondState(in BluetoothDevice device);
+ boolean isBondingInitiatedLocally(in BluetoothDevice device);
int getConnectionState(in BluetoothDevice device);
String getRemoteName(in BluetoothDevice device);
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index 12830a4..c5ceecd 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -25,4 +25,5 @@
boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
boolean setupBcb(in String command);
boolean clearBcb();
+ void rebootRecoveryWithCommand(in String command);
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 2d5a144..662e14c 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -671,28 +671,22 @@
* @throws IOException if something goes wrong.
*/
private static void bootCommand(Context context, String... args) throws IOException {
- synchronized (sRequestLock) {
- LOG_FILE.delete();
+ LOG_FILE.delete();
- StringBuilder command = new StringBuilder();
- for (String arg : args) {
- if (!TextUtils.isEmpty(arg)) {
- command.append(arg);
- command.append("\n");
- }
+ StringBuilder command = new StringBuilder();
+ for (String arg : args) {
+ if (!TextUtils.isEmpty(arg)) {
+ command.append(arg);
+ command.append("\n");
}
-
- // Write the command into BCB (bootloader control block).
- RecoverySystem rs = (RecoverySystem) context.getSystemService(
- Context.RECOVERY_SERVICE);
- rs.setupBcb(command.toString());
-
- // Having set up the BCB, go ahead and reboot.
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY);
-
- throw new IOException("Reboot failed (no permissions?)");
}
+
+ // Write the command into BCB (bootloader control block) and boot from
+ // there. Will not return unless failed.
+ RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
+ rs.rebootRecoveryWithCommand(command.toString());
+
+ throw new IOException("Reboot failed (no permissions?)");
}
// Read last_install; then report time (in seconds) and I/O (in MiB) for
@@ -887,6 +881,17 @@
}
/**
+ * Talks to RecoverySystemService via Binder to set up the BCB command and
+ * reboot into recovery accordingly.
+ */
+ private void rebootRecoveryWithCommand(String command) {
+ try {
+ mService.rebootRecoveryWithCommand(command);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Internally, recovery treats each line of the command file as a separate
* argv, so we only need to protect against newlines and nulls.
*/
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index c36b488..ff69cf6 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -191,9 +191,14 @@
*/
public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy
+ /**
+ * @hide
+ */
+ public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy
+
private static final int ALL_THREAD_DETECT_BITS =
DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
- DETECT_RESOURCE_MISMATCH;
+ DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
// Byte 2: Process-policy
@@ -465,6 +470,20 @@
}
/**
+ * Detect unbuffered input/output operations.
+ */
+ public Builder detectUnbufferedIo() {
+ return enable(DETECT_UNBUFFERED_IO);
+ }
+
+ /**
+ * Detect unbuffered input/output operations.
+ */
+ public Builder permitUnbufferedIo() {
+ return disable(DETECT_UNBUFFERED_IO);
+ }
+
+ /**
* Enables detection of mismatches between defined resource types
* and getter calls.
* <p>
@@ -974,6 +993,15 @@
}
/**
+ * @hide
+ */
+ private static class StrictModeUnbufferedIOViolation extends StrictModeViolation {
+ public StrictModeUnbufferedIOViolation(int policyMask) {
+ super(policyMask, DETECT_UNBUFFERED_IO, null);
+ }
+ }
+
+ /**
* Returns the bitmask of the current thread's policy.
*
* @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
@@ -1281,6 +1309,20 @@
startHandlingViolationException(e);
}
+ // Part of BlockGuard.Policy; just part of StrictMode:
+ public void onUnbufferedIO() {
+ if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
+ return;
+ }
+ if (tooManyViolationsThisLoop()) {
+ return;
+ }
+ BlockGuard.BlockGuardPolicyException e =
+ new StrictModeUnbufferedIOViolation(mPolicyMask);
+ e.fillInStackTrace();
+ startHandlingViolationException(e);
+ }
+
// Part of BlockGuard.Policy interface:
public void onReadFromDisk() {
if ((mPolicyMask & DETECT_DISK_READ) == 0) {
@@ -2208,6 +2250,18 @@
/**
* @hide
*/
+ public static void noteUnbufferedIO() {
+ BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
+ if (!(policy instanceof AndroidBlockGuardPolicy)) {
+ // StrictMode not enabled.
+ return;
+ }
+ ((AndroidBlockGuardPolicy) policy).onUnbufferedIO();
+ }
+
+ /**
+ * @hide
+ */
public static void noteDiskRead() {
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (!(policy instanceof AndroidBlockGuardPolicy)) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6d2d7c0..25cc961 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8189,6 +8189,13 @@
public static final String CALL_AUTO_RETRY = "call_auto_retry";
/**
+ * A setting that can be read whether the emergency affordance is currently needed.
+ * The value is a boolean (1 or 0).
+ * @hide
+ */
+ public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed";
+
+ /**
* See RIL_PreferredNetworkType in ril.h
* @hide
*/
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 8c5df08..8c2c236 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -379,7 +379,7 @@
public void setState(int state, long now) {
ensureNotDead();
- if (mCurState != state) {
+ if (!mDead && (mCurState != state)) {
//Slog.i(TAG, "Setting state in " + mName + "/" + mPackage + ": " + state);
commitStateTime(now);
mCurState = state;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 52b72a4..1c307c9 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -476,11 +476,11 @@
*/
private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
int targetSdkVersion) {
- String librarySearchPath = System.getProperty("java.library.path");
+ String libraryPath = System.getProperty("java.library.path");
return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
- librarySearchPath,
- null /* libraryPermittedPath */,
+ libraryPath,
+ libraryPath,
ClassLoader.getSystemClassLoader(),
targetSdkVersion,
true /* isNamespaceShared */);
diff --git a/core/java/com/android/internal/policy/EmergencyAffordanceManager.java b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
new file mode 100644
index 0000000..bed7c1ba
--- /dev/null
+++ b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+
+/**
+ * A class that manages emergency affordances and enables immediate calling to emergency services
+ */
+public class EmergencyAffordanceManager {
+
+ public static final boolean ENABLED = true;
+
+ /**
+ * Global setting override with the number to call with the emergency affordance.
+ * @hide
+ */
+ private static final String EMERGENCY_CALL_NUMBER_SETTING = "emergency_affordance_number";
+
+ /**
+ * Global setting, whether the emergency affordance should be shown regardless of device state.
+ * The value is a boolean (1 or 0).
+ * @hide
+ */
+ private static final String FORCE_EMERGENCY_AFFORDANCE_SETTING = "force_emergency_affordance";
+
+ private final Context mContext;
+
+ public EmergencyAffordanceManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * perform an emergency call.
+ */
+ public final void performEmergencyCall() {
+ performEmergencyCall(mContext);
+ }
+
+ private static Uri getPhoneUri(Context context) {
+ String number = context.getResources().getString(
+ com.android.internal.R.string.config_emergency_call_number);
+ if (Build.IS_DEBUGGABLE) {
+ String override = Settings.Global.getString(
+ context.getContentResolver(), EMERGENCY_CALL_NUMBER_SETTING);
+ if (override != null) {
+ number = override;
+ }
+ }
+ return Uri.fromParts("tel", number, null);
+ }
+
+ private static void performEmergencyCall(Context context) {
+ Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
+ intent.setData(getPhoneUri(context));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+
+ /**
+ * @return whether emergency affordance should be active.
+ */
+ public boolean needsEmergencyAffordance() {
+ if (!ENABLED) {
+ return false;
+ }
+ if (forceShowing()) {
+ return true;
+ }
+ return isEmergencyAffordanceNeeded();
+ }
+
+ private boolean isEmergencyAffordanceNeeded() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.EMERGENCY_AFFORDANCE_NEEDED, 0) != 0;
+ }
+
+
+ private boolean forceShowing() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ FORCE_EMERGENCY_AFFORDANCE_SETTING, 0) != 0;
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 7e1a0ab..bb55610 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -220,6 +220,7 @@
LOCAL_SHARED_LIBRARIES := \
libmemtrack \
libandroidfw \
+ libbase \
libexpat \
libnativehelper \
liblog \
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
index da47c4c..e8ca793 100644
--- a/core/jni/android_app_admin_SecurityLog.cpp
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -19,7 +19,7 @@
#include "JNIHelp.h"
#include "core_jni_helpers.h"
#include "jni.h"
-#include "log/logger.h"
+#include <private/android_logger.h>
// The size of the tag number comes out of the payload size.
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index e0bfecb..2a46edf 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -15,15 +15,7 @@
*/
#define LOG_TAG "android.os.Debug"
-#include "JNIHelp.h"
-#include "jni.h"
-#include <utils/String8.h>
-#include "utils/misc.h"
-#include "cutils/debugger.h"
-#include <memtrack/memtrack.h>
-#include <memunreachable/memunreachable.h>
-#include <cutils/log.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
@@ -40,9 +32,26 @@
#include <iomanip>
#include <string>
+#include "jni.h"
+
+#include "android-base/stringprintf.h"
+#include "cutils/debugger.h"
+#include "cutils/log.h"
+#include "JNIHelp.h"
+#include "memtrack/memtrack.h"
+#include "memunreachable/memunreachable.h"
+#include "utils/misc.h"
+#include "utils/String8.h"
+
namespace android
{
+using UniqueFile = std::unique_ptr<FILE, decltype(&fclose)>;
+
+static inline UniqueFile MakeUniqueFile(const char* path, const char* mode) {
+ return UniqueFile(fopen(path, mode), fclose);
+}
+
enum {
HEAP_UNKNOWN,
HEAP_DALVIK,
@@ -427,15 +436,13 @@
static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
{
- char tmp[128];
- FILE *fp;
+ *foundSwapPss = false;
- sprintf(tmp, "/proc/%d/smaps", pid);
- fp = fopen(tmp, "r");
- if (fp == 0) return;
+ std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
+ UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
+ if (fp == nullptr) return;
- read_mapinfo(fp, stats, foundSwapPss);
- fclose(fp);
+ read_mapinfo(fp.get(), stats, foundSwapPss);
}
static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
@@ -517,51 +524,48 @@
jlong uss = 0;
jlong memtrack = 0;
- char tmp[128];
- FILE *fp;
-
struct graphics_memory_pss graphics_mem;
if (read_memtrack_memory(pid, &graphics_mem) == 0) {
pss = uss = memtrack = graphics_mem.graphics + graphics_mem.gl + graphics_mem.other;
}
- sprintf(tmp, "/proc/%d/smaps", pid);
- fp = fopen(tmp, "r");
+ {
+ std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
+ UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
- if (fp != 0) {
- while (true) {
- if (fgets(line, 1024, fp) == NULL) {
- break;
- }
+ if (fp != nullptr) {
+ while (true) {
+ if (fgets(line, 1024, fp.get()) == NULL) {
+ break;
+ }
- if (line[0] == 'P') {
- if (strncmp(line, "Pss:", 4) == 0) {
- char* c = line + 4;
+ if (line[0] == 'P') {
+ if (strncmp(line, "Pss:", 4) == 0) {
+ char* c = line + 4;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ pss += atoi(c);
+ } else if (strncmp(line, "Private_Clean:", 14) == 0
+ || strncmp(line, "Private_Dirty:", 14) == 0) {
+ char* c = line + 14;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ uss += atoi(c);
+ }
+ } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
+ char* c = line + 8;
+ jlong lSwapPss;
while (*c != 0 && (*c < '0' || *c > '9')) {
c++;
}
- pss += atoi(c);
- } else if (strncmp(line, "Private_Clean:", 14) == 0
- || strncmp(line, "Private_Dirty:", 14) == 0) {
- char* c = line + 14;
- while (*c != 0 && (*c < '0' || *c > '9')) {
- c++;
- }
- uss += atoi(c);
+ lSwapPss = atoi(c);
+ swapPss += lSwapPss;
+ pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
}
- } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
- char* c = line + 8;
- jlong lSwapPss;
- while (*c != 0 && (*c < '0' || *c > '9')) {
- c++;
- }
- lSwapPss = atoi(c);
- swapPss += lSwapPss;
- pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
}
}
-
- fclose(fp);
}
if (outUssSwapPss != NULL) {
@@ -605,12 +609,14 @@
NULL
};
long size, vmalloc_allocated_size = 0;
- FILE* fp = fopen("/proc/vmallocinfo", "r");
- if (fp == NULL) {
+
+ UniqueFile fp = MakeUniqueFile("/proc/vmallocinfo", "re");
+ if (fp == nullptr) {
return 0;
}
+
while (true) {
- if (fgets(line, 1024, fp) == NULL) {
+ if (fgets(line, 1024, fp.get()) == NULL) {
break;
}
bool valid_line = true;
@@ -626,7 +632,6 @@
vmalloc_allocated_size += size;
}
}
- fclose(fp);
return vmalloc_allocated_size;
}
@@ -650,27 +655,25 @@
static long long get_zram_mem_used()
{
#define ZRAM_SYSFS "/sys/block/zram0/"
- FILE *f = fopen(ZRAM_SYSFS "mm_stat", "r");
- if (f) {
+ UniqueFile mm_stat_file = MakeUniqueFile(ZRAM_SYSFS "mm_stat", "re");
+ if (mm_stat_file) {
long long mem_used_total = 0;
- int matched = fscanf(f, "%*d %*d %lld %*d %*d %*d %*d", &mem_used_total);
+ int matched = fscanf(mm_stat_file.get(), "%*d %*d %lld %*d %*d %*d %*d", &mem_used_total);
if (matched != 1)
ALOGW("failed to parse " ZRAM_SYSFS "mm_stat");
- fclose(f);
return mem_used_total;
}
- f = fopen(ZRAM_SYSFS "mem_used_total", "r");
- if (f) {
+ UniqueFile mem_used_total_file = MakeUniqueFile(ZRAM_SYSFS "mem_used_total", "re");
+ if (mem_used_total_file) {
long long mem_used_total = 0;
- int matched = fscanf(f, "%lld", &mem_used_total);
+ int matched = fscanf(mem_used_total_file.get(), "%lld", &mem_used_total);
if (matched != 1)
ALOGW("failed to parse " ZRAM_SYSFS "mem_used_total");
- fclose(f);
return mem_used_total;
}
@@ -783,8 +786,8 @@
static jint read_binder_stat(const char* stat)
{
- FILE* fp = fopen(BINDER_STATS, "r");
- if (fp == NULL) {
+ UniqueFile fp = MakeUniqueFile(BINDER_STATS, "re");
+ if (fp == nullptr) {
return -1;
}
@@ -795,8 +798,7 @@
// loop until we have the block that represents this process
do {
- if (fgets(line, 1024, fp) == 0) {
- fclose(fp);
+ if (fgets(line, 1024, fp.get()) == 0) {
return -1;
}
} while (strncmp(compare, line, len));
@@ -805,8 +807,7 @@
len = snprintf(compare, 128, " %s: ", stat);
do {
- if (fgets(line, 1024, fp) == 0) {
- fclose(fp);
+ if (fgets(line, 1024, fp.get()) == 0) {
return -1;
}
} while (strncmp(compare, line, len));
@@ -814,7 +815,6 @@
// we have the line, now increment the line ptr to the value
char* ptr = line + len;
jint result = atoi(ptr);
- fclose(fp);
return result;
}
@@ -839,7 +839,8 @@
size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
extern "C" void free_malloc_leak_info(uint8_t* info);
#define SIZE_FLAG_ZYGOTE_CHILD (1<<31)
-#define BACKTRACE_SIZE 32
+
+static size_t gNumBacktraceElements;
/*
* This is a qsort() callback.
@@ -859,11 +860,11 @@
return -1;
}
- intptr_t* bt1 = (intptr_t*)(rec1 + 2);
- intptr_t* bt2 = (intptr_t*)(rec2 + 2);
- for (size_t idx = 0; idx < BACKTRACE_SIZE; idx++) {
- intptr_t addr1 = bt1[idx];
- intptr_t addr2 = bt2[idx];
+ uintptr_t* bt1 = (uintptr_t*)(rec1 + 2);
+ uintptr_t* bt2 = (uintptr_t*)(rec2 + 2);
+ for (size_t idx = 0; idx < gNumBacktraceElements; idx++) {
+ uintptr_t addr1 = bt1[idx];
+ uintptr_t addr2 = bt2[idx];
if (addr1 == addr2) {
if (addr1 == 0)
break;
@@ -907,9 +908,10 @@
if (info == NULL) {
fprintf(fp, "Native heap dump not available. To enable, run these"
" commands (requires root):\n");
- fprintf(fp, "$ adb shell setprop libc.debug.malloc 1\n");
- fprintf(fp, "$ adb shell stop\n");
- fprintf(fp, "$ adb shell start\n");
+ fprintf(fp, "# adb shell stop\n");
+ fprintf(fp, "# adb shell setprop libc.debug.malloc.options "
+ "backtrace\n");
+ fprintf(fp, "# adb shell start\n");
return;
}
assert(infoSize != 0);
@@ -920,13 +922,11 @@
size_t recordCount = overallSize / infoSize;
fprintf(fp, "Total memory: %zu\n", totalMemory);
fprintf(fp, "Allocation records: %zd\n", recordCount);
- if (backtraceSize != BACKTRACE_SIZE) {
- fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
- backtraceSize, BACKTRACE_SIZE);
- }
+ fprintf(fp, "Backtrace size: %zd\n", backtraceSize);
fprintf(fp, "\n");
/* re-sort the entries */
+ gNumBacktraceElements = backtraceSize;
qsort(info, recordCount, infoSize, compareHeapRecords);
/* dump the entries to the file */
@@ -934,7 +934,7 @@
for (size_t idx = 0; idx < recordCount; idx++) {
size_t size = *(size_t*) ptr;
size_t allocations = *(size_t*) (ptr + sizeof(size_t));
- intptr_t* backtrace = (intptr_t*) (ptr + sizeof(size_t) * 2);
+ uintptr_t* backtrace = (uintptr_t*) (ptr + sizeof(size_t) * 2);
fprintf(fp, "z %d sz %8zu num %4zu bt",
(size & SIZE_FLAG_ZYGOTE_CHILD) != 0,
@@ -960,16 +960,15 @@
fprintf(fp, "MAPS\n");
const char* maps = "/proc/self/maps";
- FILE* in = fopen(maps, "r");
- if (in == NULL) {
+ UniqueFile in = MakeUniqueFile(maps, "re");
+ if (in == nullptr) {
fprintf(fp, "Could not open %s\n", maps);
return;
}
char buf[BUFSIZ];
- while (size_t n = fread(buf, sizeof(char), BUFSIZ, in)) {
+ while (size_t n = fread(buf, sizeof(char), BUFSIZ, in.get())) {
fwrite(buf, sizeof(char), n, fp);
}
- fclose(in);
fprintf(fp, "END\n");
}
@@ -999,8 +998,8 @@
return;
}
- FILE* fp = fdopen(fd, "w");
- if (fp == NULL) {
+ UniqueFile fp(fdopen(fd, "w"), fclose);
+ if (fp == nullptr) {
ALOGW("fdopen(%d) failed: %s\n", fd, strerror(errno));
close(fd);
jniThrowRuntimeException(env, "fdopen() failed");
@@ -1008,10 +1007,8 @@
}
ALOGD("Native heap dump starting...\n");
- dumpNativeHeap(fp);
+ dumpNativeHeap(fp.get());
ALOGD("Native heap dump complete.\n");
-
- fclose(fp);
}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 7da0314..13e3f0d 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -266,6 +266,9 @@
return NULL;
}
+ LOG(INFO) << "Starting thread pool.";
+ ::android::hardware::ProcessState::self()->startThreadPool();
+
return JHwRemoteBinder::NewObject(env, service);
}
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 4f8a2cb..173afd8 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -19,7 +19,7 @@
#include "JNIHelp.h"
#include "core_jni_helpers.h"
#include "jni.h"
-#include "log/logger.h"
+#include <log/logger.h>
#define UNUSED __attribute__((__unused__))
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 4fc546c..b0028e1 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -573,8 +573,9 @@
bounds.roundOut();
}
+ incStrong(0);
auto functor = std::bind(
- std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
+ std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
(jlong) info.canvasContext.getFrameNumber(),
(jint) bounds.left, (jint) bounds.top,
(jint) bounds.right, (jint) bounds.bottom);
@@ -585,15 +586,18 @@
virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
- if (info) {
- auto functor = std::bind(
- std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this,
- (jlong) info->canvasContext.getFrameNumber());
-
- info->canvasContext.enqueueFrameWork(std::move(functor));
- } else {
- doNotifyPositionLost(0);
+ ATRACE_NAME("SurfaceView position lost");
+ JNIEnv* env = jnienv();
+ jobject localref = env->NewLocalRef(mWeakRef);
+ if (CC_UNLIKELY(!localref)) {
+ jnienv()->DeleteWeakGlobalRef(mWeakRef);
+ mWeakRef = nullptr;
+ return;
}
+
+ env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
+ info ? info->canvasContext.getFrameNumber() : 0);
+ env->DeleteLocalRef(localref);
}
private:
@@ -605,36 +609,23 @@
return env;
}
- void doUpdatePosition(jlong frameNumber, jint left, jint top,
+ void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
jint right, jint bottom) {
ATRACE_NAME("Update SurfaceView position");
JNIEnv* env = jnienv();
jobject localref = env->NewLocalRef(mWeakRef);
if (CC_UNLIKELY(!localref)) {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
+ env->DeleteWeakGlobalRef(mWeakRef);
mWeakRef = nullptr;
- return;
+ } else {
+ env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+ frameNumber, left, top, right, bottom);
+ env->DeleteLocalRef(localref);
}
- env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
- frameNumber, left, top, right, bottom);
- env->DeleteLocalRef(localref);
- }
-
- void doNotifyPositionLost(jlong frameNumber) {
- ATRACE_NAME("SurfaceView position lost");
-
- JNIEnv* env = jnienv();
- jobject localref = env->NewLocalRef(mWeakRef);
- if (CC_UNLIKELY(!localref)) {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
- return;
- }
-
- env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber);
- env->DeleteLocalRef(localref);
+ // We need to release ourselves here
+ decStrong(0);
}
JavaVM* mVm;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b0b57d9..372dc7f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -148,6 +148,8 @@
<protected-broadcast
android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
<protected-broadcast
+ android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
@@ -289,6 +291,7 @@
<protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
+ <protected-broadcast android:name="android.net.wifi.nan.action.WIFI_NAN_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
<protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
<protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml
new file mode 100644
index 0000000..8e460d7
--- /dev/null
+++ b/core/res/res/drawable/emergency_icon.xml
@@ -0,0 +1,34 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="68.0"
+ android:viewportHeight="68.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M55.2,58.3l-6.3,-7.8C54.0,46.3 57.0,40.1 57.0,33.4c0.0,-6.2 -2.6,-12.1 -7.2,-16.3l6.7,-7.4C63.2,15.8 67.0,24.4 67.0,33.4C67.0,43.1 62.7,52.2 55.2,58.3z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12.9,58.3C5.3,52.2 1.0,43.1 1.0,33.4c0.0,-9.0 3.8,-17.6 10.5,-23.7l6.7,7.4C13.6,21.3 11.0,27.2 11.0,33.4c0.0,6.7 3.0,12.9 8.2,17.1L12.9,58.3z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M29.0,11.4l10.0,0.0l0.0,29.0l-10.0,0.0z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M29.0,48.4l10.0,0.0l0.0,9.0l-10.0,0.0z"/>
+</vector>
diff --git a/core/res/res/values-mcc204-mnc04/config.xml b/core/res/res/values-mcc204-mnc04/config.xml
index 0f39e42..ddf0e9f 100755
--- a/core/res/res/values-mcc204-mnc04/config.xml
+++ b/core/res/res/values-mcc204-mnc04/config.xml
@@ -25,13 +25,6 @@
-->
<integer name="config_mobile_mtu">1358</integer>
- <!-- service number convert map in roaming network. -->
- <!-- [dialstring],[replacement][,optional gid] -->
- <string-array translatable="false" name="dial_string_replace">
- <item>"*611:+19085594899,BAE0000000000000"</item>
- <item>"*86:+1MDN,BAE0000000000000"</item>
- </string-array>
-
<!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
when evaluating RSRP for LTE antenna bar display
0. Strict threshold
diff --git a/core/res/res/values-mcc238-mnc06/config.xml b/core/res/res/values-mcc238-mnc06/config.xml
deleted file mode 100644
index afc0cc4..0000000
--- a/core/res/res/values-mcc238-mnc06/config.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- SIM does not save, but the voice mail number to be changed. -->
- <bool name="editable_voicemailnumber">true</bool>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 4b61688..413c698 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,9 +25,6 @@
-->
<integer name="config_mobile_mtu">1422</integer>
- <!-- Sprint need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">70</integer>
-
<!-- If this value is true, The mms content-disposition field is supported correctly.
If false, Content-disposition fragments are ignored -->
<bool name="config_mms_content_disposition_support">false</bool>
diff --git a/core/res/res/values-mcc310-mnc160/config.xml b/core/res/res/values-mcc310-mnc160/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc160/config.xml
+++ b/core/res/res/values-mcc310-mnc160/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc200/config.xml b/core/res/res/values-mcc310-mnc200/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc200/config.xml
+++ b/core/res/res/values-mcc310-mnc200/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc210/config.xml b/core/res/res/values-mcc310-mnc210/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc210/config.xml
+++ b/core/res/res/values-mcc310-mnc210/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc220/config.xml b/core/res/res/values-mcc310-mnc220/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc220/config.xml
+++ b/core/res/res/values-mcc310-mnc220/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc230/config.xml b/core/res/res/values-mcc310-mnc230/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc230/config.xml
+++ b/core/res/res/values-mcc310-mnc230/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc240/config.xml b/core/res/res/values-mcc310-mnc240/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc240/config.xml
+++ b/core/res/res/values-mcc310-mnc240/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc250/config.xml b/core/res/res/values-mcc310-mnc250/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc250/config.xml
+++ b/core/res/res/values-mcc310-mnc250/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc270/config.xml b/core/res/res/values-mcc310-mnc270/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc270/config.xml
+++ b/core/res/res/values-mcc310-mnc270/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc300/config.xml b/core/res/res/values-mcc310-mnc300/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc300/config.xml
+++ b/core/res/res/values-mcc310-mnc300/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc310/config.xml b/core/res/res/values-mcc310-mnc310/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc310/config.xml
+++ b/core/res/res/values-mcc310-mnc310/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc490/config.xml b/core/res/res/values-mcc310-mnc490/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc490/config.xml
+++ b/core/res/res/values-mcc310-mnc490/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc530/config.xml b/core/res/res/values-mcc310-mnc530/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc530/config.xml
+++ b/core/res/res/values-mcc310-mnc530/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc580/config.xml b/core/res/res/values-mcc310-mnc580/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc580/config.xml
+++ b/core/res/res/values-mcc310-mnc580/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc590/config.xml b/core/res/res/values-mcc310-mnc590/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc590/config.xml
+++ b/core/res/res/values-mcc310-mnc590/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc640/config.xml b/core/res/res/values-mcc310-mnc640/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc640/config.xml
+++ b/core/res/res/values-mcc310-mnc640/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc660/config.xml b/core/res/res/values-mcc310-mnc660/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc660/config.xml
+++ b/core/res/res/values-mcc310-mnc660/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc800/config.xml b/core/res/res/values-mcc310-mnc800/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc800/config.xml
+++ b/core/res/res/values-mcc310-mnc800/config.xml
@@ -32,9 +32,4 @@
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">false</bool>
-
- <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
- carrier provisioning. If false: hard disabled. If true: then depends on carrier
- provisioning, availability etc -->
- <bool name="config_carrier_wfc_ims_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc311-mnc220/config.xml b/core/res/res/values-mcc311-mnc220/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc220/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc221/config.xml b/core/res/res/values-mcc311-mnc221/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc221/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc222/config.xml b/core/res/res/values-mcc311-mnc222/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc222/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc223/config.xml b/core/res/res/values-mcc311-mnc223/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc223/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc224/config.xml b/core/res/res/values-mcc311-mnc224/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc224/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc225/config.xml b/core/res/res/values-mcc311-mnc225/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc225/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc226/config.xml b/core/res/res/values-mcc311-mnc226/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc226/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc227/config.xml b/core/res/res/values-mcc311-mnc227/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc227/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc228/config.xml b/core/res/res/values-mcc311-mnc228/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc228/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc229/config.xml b/core/res/res/values-mcc311-mnc229/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc229/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 39ea2bf..8d7fd61 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -52,11 +52,6 @@
<bool name="config_carrier_volte_provisioned">true</bool>
<bool name="config_auto_attach_data_on_creation">false</bool>
- <!-- service number convert map in roaming network. -->
- <string-array translatable="false" name="dial_string_replace">
- <item>"*611:+19085594899,"</item>
- <item>"*86:+1MDN,"</item>
- </string-array>
<!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
when evaluating RSRP for LTE antenna bar display
diff --git a/core/res/res/values-mcc311-mnc490/config.xml b/core/res/res/values-mcc311-mnc490/config.xml
index d481c97..836abdf 100644
--- a/core/res/res/values-mcc311-mnc490/config.xml
+++ b/core/res/res/values-mcc311-mnc490/config.xml
@@ -21,9 +21,6 @@
for different hardware and product builds. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Sprint need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">70</integer>
-
<!-- An array of CDMA roaming indicators which means international roaming -->
<integer-array translatable="false" name="config_cdma_international_roaming_indicators" >
<item>2</item>
diff --git a/core/res/res/values-mcc311-mnc580/config.xml b/core/res/res/values-mcc311-mnc580/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc580/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc581/config.xml b/core/res/res/values-mcc311-mnc581/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc581/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc582/config.xml b/core/res/res/values-mcc311-mnc582/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc582/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc583/config.xml b/core/res/res/values-mcc311-mnc583/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc583/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc584/config.xml b/core/res/res/values-mcc311-mnc584/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc584/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc585/config.xml b/core/res/res/values-mcc311-mnc585/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc585/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc586/config.xml b/core/res/res/values-mcc311-mnc586/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc586/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc587/config.xml b/core/res/res/values-mcc311-mnc587/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc587/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc588/config.xml b/core/res/res/values-mcc311-mnc588/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc588/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc589/config.xml b/core/res/res/values-mcc311-mnc589/config.xml
deleted file mode 100644
index 811e9c7..0000000
--- a/core/res/res/values-mcc311-mnc589/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2014, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- USC need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">300</integer>
-</resources>
diff --git a/core/res/res/values-mcc311-mnc870/config.xml b/core/res/res/values-mcc311-mnc870/config.xml
index 98cb72e..f6aed13 100644
--- a/core/res/res/values-mcc311-mnc870/config.xml
+++ b/core/res/res/values-mcc311-mnc870/config.xml
@@ -25,9 +25,6 @@
-->
<integer name="config_mobile_mtu">1422</integer>
- <!-- Sprint need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">70</integer>
-
<!-- An array of CDMA roaming indicators which means international roaming -->
<integer-array translatable="false" name="config_cdma_international_roaming_indicators" >
<item>2</item>
diff --git a/core/res/res/values-mcc312-mnc530/config.xml b/core/res/res/values-mcc312-mnc530/config.xml
index 98cb72e..f6aed13 100644
--- a/core/res/res/values-mcc312-mnc530/config.xml
+++ b/core/res/res/values-mcc312-mnc530/config.xml
@@ -25,9 +25,6 @@
-->
<integer name="config_mobile_mtu">1422</integer>
- <!-- Sprint need a 70 ms delay for 3way call -->
- <integer name="config_cdma_3waycall_flash_delay">70</integer>
-
<!-- An array of CDMA roaming indicators which means international roaming -->
<integer-array translatable="false" name="config_cdma_international_roaming_indicators" >
<item>2</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 44cbc0f..587bc55 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2212,6 +2212,21 @@
<!-- Sprint need a 70 ms delay for 3way call -->
<integer name="config_cdma_3waycall_flash_delay">0</integer>
+ <!-- If there is no preload VM number in the sim card, carriers such as
+ Verizon require to load a default vm number from the configurantion.
+ Define config_default_vm_number for this purpose. And there are two
+ optional formats for this configuration as below:
+ (1)<item>voicemail number</item>
+ (2)<item>voicemail number;gid</item>
+ The logic to pick up the correct voicemail number:
+ (1) If the config_default_vm_number array has no gid special item, the last one will be
+ picked
+ (2) If the config_default_vm_number array has gid special item and it matches the current
+ sim's gid, it will be picked.
+ (3) If the config_default_vm_number array has gid special item but it doesn't match the
+ current sim's gid, the last one without gid will be picked -->
+ <string-array translatable="false" name="config_default_vm_number" />
+
<!--SIM does not save, but the voice mail number to be changed. -->
<bool name="editable_voicemailnumber">false</bool>
@@ -2220,6 +2235,10 @@
<string-array translatable="false" name="dial_string_replace">
</string-array>
+ <!-- Flag indicating whether radio is to be restarted on the error of
+ PDP_FAIL_REGULAR_DEACTIVATION/0x24 -->
+ <bool name="config_restart_radio_on_pdp_fail_regular_deactivation">false</bool>
+
<!-- networks that don't want data deactivate when shutdown the phone
note this is dependent on the operator of the network we're on,
not operator on the SIM -->
@@ -2488,4 +2507,14 @@
<string-array translatable="false" name="config_defaultPinnerServiceFiles">
</string-array>
+ <!-- emergency call number for the emergency affordance -->
+ <string name="config_emergency_call_number" translatable="false">112</string>
+
+ <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency
+ affordances-->
+ <integer-array name="config_emergency_mcc_codes" translatable="false">
+ <item>404</item>
+ <item>405</item>
+ </integer-array>
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b55a9b22..ceb79ed 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -482,6 +482,9 @@
<!-- label for item that turns off power in phone options dialog -->
<string name="global_action_power_off">Power off</string>
+ <!-- label for item that starts emergency call -->
+ <string name="global_action_emergency">Emergency</string>
+
<!-- label for item that generates a bug report in the phone options dialog -->
<string name="global_action_bug_report">Bug report</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 206a910..6877624 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -345,8 +345,6 @@
<java-symbol type="integer" name="config_wifi_operating_voltage_mv" />
<java-symbol type="string" name="config_wifi_framework_sap_2G_channel_list" />
- <java-symbol type="bool" name="editable_voicemailnumber" />
-
<java-symbol type="bool" name="config_wifi_framework_cellular_handover_enable_user_triggered_adjustment" />
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_tx_packet_threshold" />
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_rx_packet_threshold" />
@@ -2237,9 +2235,11 @@
<java-symbol type="layout" name="resolver_different_item_header" />
<java-symbol type="array" name="config_default_vm_number" />
<java-symbol type="integer" name="config_cdma_3waycall_flash_delay"/>
+ <java-symbol type="array" name="config_default_vm_number" />
<java-symbol type="attr" name="windowBackgroundFallback" />
<java-symbol type="id" name="textSpacerNoButtons" />
<java-symbol type="array" name="dial_string_replace" />
+ <java-symbol type="bool" name="config_restart_radio_on_pdp_fail_regular_deactivation" />
<java-symbol type="array" name="networks_not_clear_data" />
<java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" />
<java-symbol type="string" name="whichHomeApplicationNamed" />
@@ -2612,4 +2612,9 @@
<java-symbol type="layout" name="unsupported_display_size_dialog_content" />
<java-symbol type="string" name="unsupported_display_size_message" />
+ <java-symbol type="string" name="global_action_emergency" />
+ <java-symbol type="string" name="config_emergency_call_number" />
+ <java-symbol type="array" name="config_emergency_mcc_codes" />
+
+ <java-symbol type="drawable" name="emergency_icon" />
</resources>
diff --git a/core/tests/coretests/src/com/android/internal/os/DebugTest.java b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
index 88c7d1b..efb78d7 100644
--- a/core/tests/coretests/src/com/android/internal/os/DebugTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
@@ -64,4 +64,12 @@
public void testGetCallers() {
assertTrue(callDepth1().matches(EXPECTED_GET_CALLERS));
}
+
+ /**
+ * Regression test for b/31943543. Note: must be run under CheckJNI to detect the issue.
+ */
+ public void testGetMemoryInfo() {
+ Debug.MemoryInfo info = new Debug.MemoryInfo();
+ Debug.getMemoryInfo(-1, info);
+ }
}
diff --git a/core/tests/systemproperties/Android.mk b/core/tests/systemproperties/Android.mk
index ffc1282..e16c367 100644
--- a/core/tests/systemproperties/Android.mk
+++ b/core/tests/systemproperties/Android.mk
@@ -11,7 +11,6 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := FrameworksCoreSystemPropertiesTests
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_CERTIFICATE := platform
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index f50cff4..8ea25d6 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -1892,6 +1892,7 @@
Asset* AssetManager::SharedZip::getResourceTableAsset()
{
+ AutoMutex _l(gLock);
ALOGV("Getting from SharedZip %p resource asset %p\n", this, mResourceTableAsset);
return mResourceTableAsset;
}
@@ -1901,10 +1902,10 @@
{
AutoMutex _l(gLock);
if (mResourceTableAsset == NULL) {
- mResourceTableAsset = asset;
// This is not thread safe the first time it is called, so
// do it here with the global lock held.
asset->getBuffer(true);
+ mResourceTableAsset = asset;
return asset;
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 1eaf5d6..f9735a2 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -232,7 +232,7 @@
// the frameNumber to appropriately batch/synchronize these transactions.
// There is no other filtering/batching to ensure that only the "final"
// state called once per frame.
- class ANDROID_API PositionListener {
+ class ANDROID_API PositionListener : public VirtualLightRefBase {
public:
virtual ~PositionListener() {}
// Called when the RenderNode's position changes
@@ -247,7 +247,7 @@
// before the RenderNode is used for drawing.
// RenderNode takes ownership of the pointer
ANDROID_API void setPositionListener(PositionListener* listener) {
- mPositionListener.reset(listener);
+ mPositionListener = listener;
}
// This is only modified in MODE_FULL, so it can be safely accessed
@@ -366,7 +366,7 @@
// mDisplayList, not mStagingDisplayList.
uint32_t mParentCount;
- std::unique_ptr<PositionListener> mPositionListener;
+ sp<PositionListener> mPositionListener;
}; // class RenderNode
} /* namespace uirenderer */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c626c54..75e7fdf 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -783,6 +783,7 @@
}
sp<FuncTask> task(new FuncTask());
task->func = func;
+ mFrameFences.push_back(task);
mFrameWorkProcessor->add(task);
}
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index c0c47ef..d68bb53 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -31,7 +31,7 @@
struct AMessage;
struct AString;
struct ICrypto;
-struct IGraphicBufferProducer;
+class IGraphicBufferProducer;
struct MediaCodec;
struct PersistentSurface;
class Surface;
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 7e438a1..29557be 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -7,8 +7,6 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
LOCAL_STATIC_JAVA_LIBRARIES := easymocklib \
mockito-target \
android-support-test \
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 8d41145..7256843 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -28,13 +28,16 @@
import android.telecom.TelecomManager;
import android.util.AttributeSet;
import android.util.Slog;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.EmergencyAffordanceManager;
/**
* This class implements a smart emergency button that updates itself based
@@ -51,7 +54,10 @@
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
private static final String LOG_TAG = "EmergencyButton";
+ private final EmergencyAffordanceManager mEmergencyAffordanceManager;
+ private int mDownX;
+ private int mDownY;
KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -64,6 +70,7 @@
updateEmergencyCallButton();
}
};
+ private boolean mLongPressWasDragged;
public interface EmergencyButtonCallback {
public void onEmergencyButtonClickedWhenInCall();
@@ -86,6 +93,7 @@
com.android.internal.R.bool.config_voice_capable);
mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked);
+ mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
}
@Override
@@ -110,10 +118,40 @@
takeEmergencyCallAction();
}
});
+ setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (!mLongPressWasDragged
+ && mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+ mEmergencyAffordanceManager.performEmergencyCall();
+ return true;
+ }
+ return false;
+ }
+ });
updateEmergencyCallButton();
}
@Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int x = (int) event.getX();
+ final int y = (int) event.getY();
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mDownX = x;
+ mDownY = y;
+ mLongPressWasDragged = false;
+ } else {
+ final int xDiff = Math.abs(x - mDownX);
+ final int yDiff = Math.abs(y - mDownY);
+ int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ if (Math.abs(yDiff) > touchSlop || Math.abs(xDiff) > touchSlop) {
+ mLongPressWasDragged = true;
+ }
+ }
+ return super.onTouchEvent(event);
+ }
+
+ @Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateEmergencyCallButton();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index a7e4e12..61e2fc0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -173,6 +173,7 @@
final AlertDialog dialog = new AlertDialog.Builder(mContext)
.setTitle(title)
.setMessage(message)
+ .setCancelable(false)
.setNeutralButton(R.string.ok, null)
.create();
if (!(mContext instanceof Activity)) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index c075703..281f1db 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -102,9 +102,6 @@
private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
- /** Auto-connect after pairing only if locally initiated. */
- private boolean mConnectAfterPairing;
-
/**
* Describes the current device and profile for logging.
*
@@ -300,7 +297,6 @@
return false;
}
- mConnectAfterPairing = true; // auto-connect after pairing
return true;
}
@@ -309,7 +305,7 @@
* slightly different for local vs. remote initiated pairing dialogs.
*/
boolean isUserInitiatedPairing() {
- return mConnectAfterPairing;
+ return mDevice.isBondingInitiatedLocally();
}
public void unpair() {
@@ -549,7 +545,6 @@
void onBondingStateChanged(int bondState) {
if (bondState == BluetoothDevice.BOND_NONE) {
mProfiles.clear();
- mConnectAfterPairing = false; // cancel auto-connect
setPhonebookPermissionChoice(ACCESS_UNKNOWN);
setMessagePermissionChoice(ACCESS_UNKNOWN);
setSimPermissionChoice(ACCESS_UNKNOWN);
@@ -562,10 +557,9 @@
if (bondState == BluetoothDevice.BOND_BONDED) {
if (mDevice.isBluetoothDock()) {
onBondingDockConnect();
- } else if (mConnectAfterPairing) {
+ } else if (mDevice.isBondingInitiatedLocally()) {
connect(false);
}
- mConnectAfterPairing = false;
}
}
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 0658620..bf3681b 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -28,7 +28,7 @@
frameworks/base/libs/hwui \
$(rs_generated_include_dir)
-LOCAL_CFLAGS += -Wno-unused-parameter -std=c++11
+LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 06c4350..af370ff 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -644,7 +644,7 @@
in_allocs[2] = (RsAllocation)C;
rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
- in_allocs, sizeof(in_allocs), nullptr,
+ in_allocs, NELEM(in_allocs), nullptr,
&call, sizeof(call), nullptr, 0);
}
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 276687f..3c8c699 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -21,6 +21,7 @@
import android.net.LocalSocketAddress;
import android.os.IRecoverySystem;
import android.os.IRecoverySystemProgressListener;
+import android.os.PowerManager;
import android.os.RecoverySystem;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -50,8 +51,15 @@
// The socket at /dev/socket/uncrypt to communicate with uncrypt.
private static final String UNCRYPT_SOCKET = "uncrypt";
+ // The init services that communicate with /system/bin/uncrypt.
+ private static final String INIT_SERVICE_UNCRYPT = "init.svc.uncrypt";
+ private static final String INIT_SERVICE_SETUP_BCB = "init.svc.setup-bcb";
+ private static final String INIT_SERVICE_CLEAR_BCB = "init.svc.clear-bcb";
+
private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
+ private static final Object sRequestLock = new Object();
+
private Context mContext;
public RecoverySystemService(Context context) {
@@ -69,95 +77,155 @@
public boolean uncrypt(String filename, IRecoverySystemProgressListener listener) {
if (DEBUG) Slog.d(TAG, "uncrypt: " + filename);
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ synchronized (sRequestLock) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
- // Write the filename into UNCRYPT_PACKAGE_FILE to be read by
- // uncrypt.
- RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
-
- try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) {
- uncryptFile.write(filename + "\n");
- } catch (IOException e) {
- Slog.e(TAG, "IOException when writing \"" + RecoverySystem.UNCRYPT_PACKAGE_FILE +
- "\": ", e);
- return false;
- }
-
- // Trigger uncrypt via init.
- SystemProperties.set("ctl.start", "uncrypt");
-
- // Connect to the uncrypt service socket.
- LocalSocket socket = connectService();
- if (socket == null) {
- Slog.e(TAG, "Failed to connect to uncrypt socket");
- return false;
- }
-
- // Read the status from the socket.
- DataInputStream dis = null;
- DataOutputStream dos = null;
- try {
- dis = new DataInputStream(socket.getInputStream());
- dos = new DataOutputStream(socket.getOutputStream());
- int lastStatus = Integer.MIN_VALUE;
- while (true) {
- int status = dis.readInt();
- // Avoid flooding the log with the same message.
- if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
- continue;
- }
- lastStatus = status;
-
- if (status >= 0 && status <= 100) {
- // Update status
- Slog.i(TAG, "uncrypt read status: " + status);
- if (listener != null) {
- try {
- listener.onProgress(status);
- } catch (RemoteException ignored) {
- Slog.w(TAG, "RemoteException when posting progress");
- }
- }
- if (status == 100) {
- Slog.i(TAG, "uncrypt successfully finished.");
- // Ack receipt of the final status code. uncrypt
- // waits for the ack so the socket won't be
- // destroyed before we receive the code.
- dos.writeInt(0);
- break;
- }
- } else {
- // Error in /system/bin/uncrypt.
- Slog.e(TAG, "uncrypt failed with status: " + status);
- // Ack receipt of the final status code. uncrypt waits
- // for the ack so the socket won't be destroyed before
- // we receive the code.
- dos.writeInt(0);
- return false;
- }
+ final boolean available = checkAndWaitForUncryptService();
+ if (!available) {
+ Slog.e(TAG, "uncrypt service is unavailable.");
+ return false;
}
- } catch (IOException e) {
- Slog.e(TAG, "IOException when reading status: ", e);
- return false;
- } finally {
- IoUtils.closeQuietly(dis);
- IoUtils.closeQuietly(dos);
- IoUtils.closeQuietly(socket);
- }
- return true;
+ // Write the filename into UNCRYPT_PACKAGE_FILE to be read by
+ // uncrypt.
+ RecoverySystem.UNCRYPT_PACKAGE_FILE.delete();
+
+ try (FileWriter uncryptFile = new FileWriter(RecoverySystem.UNCRYPT_PACKAGE_FILE)) {
+ uncryptFile.write(filename + "\n");
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when writing \"" +
+ RecoverySystem.UNCRYPT_PACKAGE_FILE + "\":", e);
+ return false;
+ }
+
+ // Trigger uncrypt via init.
+ SystemProperties.set("ctl.start", "uncrypt");
+
+ // Connect to the uncrypt service socket.
+ LocalSocket socket = connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ // Read the status from the socket.
+ DataInputStream dis = null;
+ DataOutputStream dos = null;
+ try {
+ dis = new DataInputStream(socket.getInputStream());
+ dos = new DataOutputStream(socket.getOutputStream());
+ int lastStatus = Integer.MIN_VALUE;
+ while (true) {
+ int status = dis.readInt();
+ // Avoid flooding the log with the same message.
+ if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+ continue;
+ }
+ lastStatus = status;
+
+ if (status >= 0 && status <= 100) {
+ // Update status
+ Slog.i(TAG, "uncrypt read status: " + status);
+ if (listener != null) {
+ try {
+ listener.onProgress(status);
+ } catch (RemoteException ignored) {
+ Slog.w(TAG, "RemoteException when posting progress");
+ }
+ }
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt successfully finished.");
+ // Ack receipt of the final status code. uncrypt
+ // waits for the ack so the socket won't be
+ // destroyed before we receive the code.
+ dos.writeInt(0);
+ break;
+ }
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ // Ack receipt of the final status code. uncrypt waits
+ // for the ack so the socket won't be destroyed before
+ // we receive the code.
+ dos.writeInt(0);
+ return false;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when reading status: ", e);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(dis);
+ IoUtils.closeQuietly(dos);
+ IoUtils.closeQuietly(socket);
+ }
+
+ return true;
+ }
}
@Override // Binder call
public boolean clearBcb() {
if (DEBUG) Slog.d(TAG, "clearBcb");
- return setupOrClearBcb(false, null);
+ synchronized (sRequestLock) {
+ return setupOrClearBcb(false, null);
+ }
}
@Override // Binder call
public boolean setupBcb(String command) {
if (DEBUG) Slog.d(TAG, "setupBcb: [" + command + "]");
- return setupOrClearBcb(true, command);
+ synchronized (sRequestLock) {
+ return setupOrClearBcb(true, command);
+ }
+ }
+
+ @Override // Binder call
+ public void rebootRecoveryWithCommand(String command) {
+ if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
+ synchronized (sRequestLock) {
+ if (!setupOrClearBcb(true, command)) {
+ return;
+ }
+
+ // Having set up the BCB, go ahead and reboot.
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ pm.reboot(PowerManager.REBOOT_RECOVERY);
+ }
+ }
+
+ /**
+ * Check if any of the init services is still running. If so, we cannot
+ * start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
+ * it may break the socket communication since init creates / deletes
+ * the socket (/dev/socket/uncrypt) on service start / exit.
+ */
+ private boolean checkAndWaitForUncryptService() {
+ for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+ final String uncryptService = SystemProperties.get(INIT_SERVICE_UNCRYPT);
+ final String setupBcbService = SystemProperties.get(INIT_SERVICE_SETUP_BCB);
+ final String clearBcbService = SystemProperties.get(INIT_SERVICE_CLEAR_BCB);
+ final boolean busy = "running".equals(uncryptService) ||
+ "running".equals(setupBcbService) || "running".equals(clearBcbService);
+ if (DEBUG) {
+ Slog.i(TAG, "retry: " + retry + " busy: " + busy +
+ " uncrypt: [" + uncryptService + "]" +
+ " setupBcb: [" + setupBcbService + "]" +
+ " clearBcb: [" + clearBcbService + "]");
+ }
+
+ if (!busy) {
+ return true;
+ }
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Interrupted:", e);
+ }
+ }
+
+ return false;
}
private LocalSocket connectService() {
@@ -176,7 +244,7 @@
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
- Slog.w(TAG, "Interrupted: ", e);
+ Slog.w(TAG, "Interrupted:", e);
}
}
}
@@ -190,6 +258,12 @@
private boolean setupOrClearBcb(boolean isSetup, String command) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ final boolean available = checkAndWaitForUncryptService();
+ if (!available) {
+ Slog.e(TAG, "uncrypt service is unavailable.");
+ return false;
+ }
+
if (isSetup) {
SystemProperties.set("ctl.start", "setup-bcb");
} else {
@@ -232,7 +306,7 @@
return false;
}
} catch (IOException e) {
- Slog.e(TAG, "IOException when communicating with uncrypt: ", e);
+ Slog.e(TAG, "IOException when communicating with uncrypt:", e);
return false;
} finally {
IoUtils.closeQuietly(dis);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 74af37f..eb5bf22 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6098,6 +6098,8 @@
ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent,
packageName == null ? ("stop user " + userId) : ("stop " + packageName));
+ didSomething |= mActivityStarter.clearPendingActivityLaunchesLocked(packageName);
+
if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
packageName, null, doit, evenPersistent, userId)) {
if (!doit) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4ead64b..eaeb1a7 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3157,7 +3157,8 @@
}
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
- if (!mStackSupervisor.isFocusedStack(this) || mService.mFocusedActivity != r) {
+ if (!mStackSupervisor.isFocusedStack(this) || (mService.mFocusedActivity != r
+ && mService.mFocusedActivity != null)) {
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 7b3f65a..85fa139 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -2006,4 +2006,18 @@
}
}
}
+
+ boolean clearPendingActivityLaunchesLocked(String packageName) {
+ boolean didSomething = false;
+
+ for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
+ PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
+ ActivityRecord r = pal.r;
+ if (r != null && r.packageName.equals(packageName)) {
+ mPendingActivityLaunches.remove(palNdx);
+ didSomething = true;
+ }
+ }
+ return didSomething;
+ }
}
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
new file mode 100644
index 0000000..cca9f10
--- /dev/null
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.emergency;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.telephony.CellInfo;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellLocation;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import com.android.server.SystemService;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A service that listens to connectivity and SIM card changes and determines if the emergency mode
+ * should be enabled
+ */
+public class EmergencyAffordanceService extends SystemService {
+
+ private static final String TAG = "EmergencyAffordanceService";
+
+ private static final int NUM_SCANS_UNTIL_ABORT = 4;
+
+ private static final int INITIALIZE_STATE = 1;
+ private static final int CELL_INFO_STATE_CHANGED = 2;
+ private static final int SUBSCRIPTION_CHANGED = 3;
+
+ /**
+ * Global setting, whether the last scan of the sim cards reveal that a sim was inserted that
+ * requires the emergency affordance. The value is a boolean (1 or 0).
+ * @hide
+ */
+ private static final String EMERGENCY_SIM_INSERTED_SETTING = "emergency_sim_inserted_before";
+
+ private final Context mContext;
+ private final ArrayList<Integer> mEmergencyCallMccNumbers;
+
+ private final Object mLock = new Object();
+
+ private TelephonyManager mTelephonyManager;
+ private SubscriptionManager mSubscriptionManager;
+ private boolean mEmergencyAffordanceNeeded;
+ private MyHandler mHandler;
+ private int mScansCompleted;
+ private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCellInfoChanged(List<CellInfo> cellInfo) {
+ if (!isEmergencyAffordanceNeeded()) {
+ requestCellScan();
+ }
+ }
+
+ @Override
+ public void onCellLocationChanged(CellLocation location) {
+ if (!isEmergencyAffordanceNeeded()) {
+ requestCellScan();
+ }
+ }
+ };
+ private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 0) {
+ startScanning();
+ requestCellScan();
+ }
+ }
+ };
+ private boolean mSimNeedsEmergencyAffordance;
+ private boolean mNetworkNeedsEmergencyAffordance;
+
+ private void requestCellScan() {
+ mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget();
+ }
+
+ private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener
+ = new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ mHandler.obtainMessage(SUBSCRIPTION_CHANGED).sendToTarget();
+ }
+ };
+
+ public EmergencyAffordanceService(Context context) {
+ super(context);
+ mContext = context;
+ int[] numbers = context.getResources().getIntArray(
+ com.android.internal.R.array.config_emergency_mcc_codes);
+ mEmergencyCallMccNumbers = new ArrayList<>(numbers.length);
+ for (int i = 0; i < numbers.length; i++) {
+ mEmergencyCallMccNumbers.add(numbers[i]);
+ }
+ }
+
+ private void updateEmergencyAffordanceNeeded() {
+ synchronized (mLock) {
+ mEmergencyAffordanceNeeded = mSimNeedsEmergencyAffordance ||
+ mNetworkNeedsEmergencyAffordance;
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
+ mEmergencyAffordanceNeeded ? 1 : 0);
+ if (mEmergencyAffordanceNeeded) {
+ stopScanning();
+ }
+ }
+ }
+
+ private void stopScanning() {
+ synchronized (mLock) {
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ mScansCompleted = 0;
+ }
+ }
+
+ private boolean isEmergencyAffordanceNeeded() {
+ synchronized (mLock) {
+ return mEmergencyAffordanceNeeded;
+ }
+ }
+
+ @Override
+ public void onStart() {
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mSubscriptionManager = SubscriptionManager.from(mContext);
+ HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ mHandler = new MyHandler(thread.getLooper());
+ mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget();
+ startScanning();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ mContext.registerReceiver(mAirplaneModeReceiver, filter);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener);
+ }
+ }
+
+ private void startScanning() {
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO
+ | PhoneStateListener.LISTEN_CELL_LOCATION);
+ }
+
+ /** Handler to do the heavier work on */
+ private class MyHandler extends Handler {
+
+ public MyHandler(Looper l) {
+ super(l);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case INITIALIZE_STATE:
+ handleInitializeState();
+ break;
+ case CELL_INFO_STATE_CHANGED:
+ handleUpdateCellInfo();
+ break;
+ case SUBSCRIPTION_CHANGED:
+ handleUpdateSimSubscriptionInfo();
+ break;
+ }
+ }
+ }
+
+ private void handleInitializeState() {
+ if (handleUpdateSimSubscriptionInfo()) {
+ return;
+ }
+ if (handleUpdateCellInfo()) {
+ return;
+ }
+ updateEmergencyAffordanceNeeded();
+ }
+
+ private boolean handleUpdateSimSubscriptionInfo() {
+ boolean neededBefore = simNeededAffordanceBefore();
+ boolean neededNow = neededBefore;
+ List<SubscriptionInfo> activeSubscriptionInfoList =
+ mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (activeSubscriptionInfoList == null) {
+ return neededNow;
+ }
+ for (SubscriptionInfo info : activeSubscriptionInfoList) {
+ int mcc = info.getMcc();
+ if (mccRequiresEmergencyAffordance(mcc)) {
+ neededNow = true;
+ break;
+ } else if (mcc != 0 && mcc != Integer.MAX_VALUE){
+ // a Sim with a different mcc code was found
+ neededNow = false;
+ }
+ String simOperator = mTelephonyManager.getSimOperator(info.getSubscriptionId());
+ mcc = 0;
+ if (simOperator != null && simOperator.length() >= 3) {
+ mcc = Integer.parseInt(simOperator.substring(0, 3));
+ }
+ if (mcc != 0) {
+ if (mccRequiresEmergencyAffordance(mcc)) {
+ neededNow = true;
+ break;
+ } else {
+ // a Sim with a different mcc code was found
+ neededNow = false;
+ }
+ }
+ }
+ if (neededNow != neededBefore) {
+ setSimNeedsEmergencyAffordance(neededNow);
+ }
+ return neededNow;
+ }
+
+ private void setSimNeedsEmergencyAffordance(boolean simNeedsEmergencyAffordance) {
+ mSimNeedsEmergencyAffordance = simNeedsEmergencyAffordance;
+ Settings.Global.putInt(mContext.getContentResolver(),
+ EMERGENCY_SIM_INSERTED_SETTING,
+ simNeedsEmergencyAffordance ? 1 : 0);
+ updateEmergencyAffordanceNeeded();
+ }
+
+ private boolean simNeededAffordanceBefore() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ "emergency_sim_inserted_before", 0) != 0;
+ }
+
+ private boolean handleUpdateCellInfo() {
+ List<CellInfo> cellInfos = mTelephonyManager.getAllCellInfo();
+ if (cellInfos == null) {
+ return false;
+ }
+ boolean stopScanningAfterScan = false;
+ for (CellInfo cellInfo : cellInfos) {
+ int mcc = 0;
+ if (cellInfo instanceof CellInfoGsm) {
+ mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMcc();
+ } else if (cellInfo instanceof CellInfoLte) {
+ mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMcc();
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMcc();
+ }
+ if (mccRequiresEmergencyAffordance(mcc)) {
+ setNetworkNeedsEmergencyAffordance(true);
+ return true;
+ } else if (mcc != 0 && mcc != Integer.MAX_VALUE) {
+ // we found an mcc that isn't in the list, abort
+ stopScanningAfterScan = true;
+ }
+ }
+ if (stopScanningAfterScan) {
+ stopScanning();
+ } else {
+ onCellScanFinishedUnsuccessful();
+ }
+ setNetworkNeedsEmergencyAffordance(false);
+ return false;
+ }
+
+ private void setNetworkNeedsEmergencyAffordance(boolean needsAffordance) {
+ synchronized (mLock) {
+ mNetworkNeedsEmergencyAffordance = needsAffordance;
+ updateEmergencyAffordanceNeeded();
+ }
+ }
+
+ private void onCellScanFinishedUnsuccessful() {
+ synchronized (mLock) {
+ mScansCompleted++;
+ if (mScansCompleted >= NUM_SCANS_UNTIL_ABORT) {
+ stopScanning();
+ }
+ }
+ }
+
+ private boolean mccRequiresEmergencyAffordance(int mcc) {
+ return mEmergencyCallMccNumbers.contains(mcc);
+ }
+}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index cc556c7..a12a92c 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -178,6 +178,7 @@
public void binderDied() {
Slog.v(TAG, "fingerprintd died");
mDaemon = null;
+ mCurrentUserId = UserHandle.USER_CURRENT;
handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 72c549f..2e18b1c 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -230,6 +230,11 @@
mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
}
+ public void deleteOdex(String apkPath, String instructionSet, String outputPath)
+ throws InstallerException {
+ mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath);
+ }
+
private static void assertValidInstructionSet(String instructionSet)
throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index bff6d2d..689917c 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -31,7 +31,7 @@
import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
-
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.InstallerConnection;
import com.android.internal.os.InstallerConnection.InstallerException;
@@ -40,6 +40,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
* A service for A/B OTA dexopting.
@@ -53,6 +54,10 @@
// The synthetic library dependencies denoting "no checks."
private final static String[] NO_LIBRARIES = new String[] { "&" };
+ // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
+ // not bulk-delete unused apps' odex files.
+ private final static long BULK_DELETE_THRESHOLD = 1024 * 1024 * 1024; // 1GB.
+
private final Context mContext;
private final PackageManagerService mPackageManagerService;
@@ -65,6 +70,25 @@
private int completeSize;
+ // MetricsLogger properties.
+
+ // Space before and after.
+ private long availableSpaceBefore;
+ private long availableSpaceAfterBulkDelete;
+ private long availableSpaceAfterDexopt;
+
+ // Packages.
+ private int importantPackageCount;
+ private int otherPackageCount;
+
+ // Number of dexopt commands. This may be different from the count of packages.
+ private int dexoptCommandCountTotal;
+ private int dexoptCommandCountExecuted;
+
+ // For spent time.
+ private long otaDexoptTimeStart;
+
+
public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
this.mContext = context;
this.mPackageManagerService = packageManagerService;
@@ -128,6 +152,18 @@
generatePackageDexopts(p, PackageManagerService.REASON_FIRST_BOOT));
}
completeSize = mDexoptCommands.size();
+
+ long spaceAvailable = getAvailableSpace();
+ if (spaceAvailable < BULK_DELETE_THRESHOLD) {
+ Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: "
+ + PackageManagerServiceUtils.packagesToString(others));
+ for (PackageParser.Package pkg : others) {
+ deleteOatArtifactsOfPackage(pkg);
+ }
+ }
+ long spaceAvailableNow = getAvailableSpace();
+
+ prepareMetricsLogging(important.size(), others.size(), spaceAvailable, spaceAvailableNow);
}
@Override
@@ -136,6 +172,9 @@
Log.i(TAG, "Cleaning up OTA Dexopt state.");
}
mDexoptCommands = null;
+ availableSpaceAfterDexopt = getAvailableSpace();
+
+ performMetricsLogging();
}
@Override
@@ -169,28 +208,67 @@
String next = mDexoptCommands.remove(0);
- if (IsFreeSpaceAvailable()) {
+ if (getAvailableSpace() > 0) {
+ dexoptCommandCountExecuted++;
+
return next;
} else {
+ if (DEBUG_DEXOPT) {
+ Log.w(TAG, "Not enough space for OTA dexopt, stopping with "
+ + (mDexoptCommands.size() + 1) + " commands left.");
+ }
mDexoptCommands.clear();
return "(no free space)";
}
}
- /**
- * Check for low space. Returns true if there's space left.
- */
- private boolean IsFreeSpaceAvailable() {
- // TODO: If apps are not installed in the internal /data partition, we should compare
- // against that storage's free capacity.
+ private long getMainLowSpaceThreshold() {
File dataDir = Environment.getDataDirectory();
@SuppressWarnings("deprecation")
long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
if (lowThreshold == 0) {
throw new IllegalStateException("Invalid low memory threshold");
}
+ return lowThreshold;
+ }
+
+ /**
+ * Returns the difference of free space to the low-storage-space threshold. Positive values
+ * indicate free bytes.
+ */
+ private long getAvailableSpace() {
+ // TODO: If apps are not installed in the internal /data partition, we should compare
+ // against that storage's free capacity.
+ long lowThreshold = getMainLowSpaceThreshold();
+
+ File dataDir = Environment.getDataDirectory();
long usableSpace = dataDir.getUsableSpace();
- return (usableSpace >= lowThreshold);
+
+ return usableSpace - lowThreshold;
+ }
+
+ private static String getOatDir(PackageParser.Package pkg) {
+ if (!pkg.canHaveOatDir()) {
+ return null;
+ }
+ File codePath = new File(pkg.codePath);
+ if (codePath.isDirectory()) {
+ return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath();
+ }
+ return null;
+ }
+
+ private void deleteOatArtifactsOfPackage(PackageParser.Package pkg) {
+ String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ for (String codePath : pkg.getAllCodePaths()) {
+ for (String isa : instructionSets) {
+ try {
+ mPackageManagerService.mInstaller.deleteOdex(codePath, isa, getOatDir(pkg));
+ } catch (InstallerException e) {
+ Log.e(TAG, "Failed deleting oat files for " + codePath, e);
+ }
+ }
+ }
}
/**
@@ -271,6 +349,55 @@
}
}
+ /**
+ * Initialize logging fields.
+ */
+ private void prepareMetricsLogging(int important, int others, long spaceBegin, long spaceBulk) {
+ availableSpaceBefore = spaceBegin;
+ availableSpaceAfterBulkDelete = spaceBulk;
+ availableSpaceAfterDexopt = 0;
+
+ importantPackageCount = important;
+ otherPackageCount = others;
+
+ dexoptCommandCountTotal = mDexoptCommands.size();
+ dexoptCommandCountExecuted = 0;
+
+ otaDexoptTimeStart = System.nanoTime();
+ }
+
+ private static int inMegabytes(long value) {
+ long in_mega_bytes = value / (1024 * 1024);
+ if (in_mega_bytes > Integer.MAX_VALUE) {
+ Log.w(TAG, "Recording " + in_mega_bytes + "MB of free space, overflowing range");
+ return Integer.MAX_VALUE;
+ }
+ return (int)in_mega_bytes;
+ }
+
+ private void performMetricsLogging() {
+ long finalTime = System.nanoTime();
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_before_mb",
+ inMegabytes(availableSpaceBefore));
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_bulk_delete_mb",
+ inMegabytes(availableSpaceAfterBulkDelete));
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_dexopt_mb",
+ inMegabytes(availableSpaceAfterDexopt));
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_important_packages",
+ importantPackageCount);
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_other_packages", otherPackageCount);
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_commands", dexoptCommandCountTotal);
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_commands_executed",
+ dexoptCommandCountExecuted);
+
+ final int elapsedTimeSeconds =
+ (int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
+ MetricsLogger.histogram(mContext, "ota_dexopt_time_s", elapsedTimeSeconds);
+ }
+
private static class OTADexoptPackageDexOptimizer extends
PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 751c585..cfd0af7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -19,6 +19,7 @@
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.TAG;
+import android.annotation.NonNull;
import android.app.AppGlobals;
import android.content.Intent;
import android.content.pm.PackageParser;
@@ -35,13 +36,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
+import java.util.function.Predicate;
/**
* Class containing helper methods for the PackageManagerService.
@@ -67,34 +64,51 @@
return pkgNames;
}
- private static void filterRecentlyUsedApps(Collection<PackageParser.Package> pkgs,
- long estimatedPreviousSystemUseTime,
- long dexOptLRUThresholdInMills) {
- // Filter out packages that aren't recently used.
- int total = pkgs.size();
- int skipped = 0;
- for (Iterator<PackageParser.Package> i = pkgs.iterator(); i.hasNext();) {
- PackageParser.Package pkg = i.next();
- long then = pkg.getLatestForegroundPackageUseTimeInMills();
- if (then < estimatedPreviousSystemUseTime - dexOptLRUThresholdInMills) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipping dexopt of " + pkg.packageName +
- " last used in foreground: " +
- ((then == 0) ? "never" : new Date(then)));
- }
- i.remove();
- skipped++;
- } else {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Will dexopt " + pkg.packageName +
- " last used in foreground: " +
- ((then == 0) ? "never" : new Date(then)));
- }
+ // Sort a list of apps by their last usage, most recently used apps first. The order of
+ // packages without usage data is undefined (but they will be sorted after the packages
+ // that do have usage data).
+ public static void sortPackagesByUsageDate(List<PackageParser.Package> pkgs,
+ PackageManagerService packageManagerService) {
+ if (!packageManagerService.isHistoricalPackageUsageAvailable()) {
+ return;
+ }
+
+ Collections.sort(pkgs, (pkg1, pkg2) ->
+ Long.compare(pkg2.getLatestForegroundPackageUseTimeInMills(),
+ pkg1.getLatestForegroundPackageUseTimeInMills()));
+ }
+
+ // Apply the given {@code filter} to all packages in {@code packages}. If tested positive, the
+ // package will be removed from {@code packages} and added to {@code result} with its
+ // dependencies. If usage data is available, the positive packages will be sorted by usage
+ // data (with {@code sortTemp} as temporary storage).
+ private static void applyPackageFilter(Predicate<PackageParser.Package> filter,
+ Collection<PackageParser.Package> result,
+ Collection<PackageParser.Package> packages,
+ @NonNull List<PackageParser.Package> sortTemp,
+ PackageManagerService packageManagerService) {
+ for (PackageParser.Package pkg : packages) {
+ if (filter.test(pkg)) {
+ sortTemp.add(pkg);
}
}
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Skipped dexopt " + skipped + " of " + total);
+
+ sortPackagesByUsageDate(sortTemp, packageManagerService);
+ packages.removeAll(sortTemp);
+
+ for (PackageParser.Package pkg : sortTemp) {
+ result.add(pkg);
+
+ Collection<PackageParser.Package> deps =
+ packageManagerService.findSharedNonSystemLibraries(pkg);
+ if (!deps.isEmpty()) {
+ deps.removeAll(result);
+ result.addAll(deps);
+ packages.removeAll(deps);
+ }
}
+
+ sortTemp.clear();
}
// Sort apps by importance for dexopt ordering. Important apps are given
@@ -104,46 +118,25 @@
PackageManagerService packageManagerService) {
ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages);
LinkedList<PackageParser.Package> result = new LinkedList<>();
+ ArrayList<PackageParser.Package> sortTemp = new ArrayList<>(remainingPkgs.size());
// Give priority to core apps.
- for (PackageParser.Package pkg : remainingPkgs) {
- if (pkg.coreApp) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding core app " + result.size() + ": " + pkg.packageName);
- }
- result.add(pkg);
- }
- }
- remainingPkgs.removeAll(result);
+ applyPackageFilter((pkg) -> pkg.coreApp, result, remainingPkgs, sortTemp,
+ packageManagerService);
// Give priority to system apps that listen for pre boot complete.
Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
- ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
- for (PackageParser.Package pkg : remainingPkgs) {
- if (pkgNames.contains(pkg.packageName)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding pre boot system app " + result.size() + ": " +
- pkg.packageName);
- }
- result.add(pkg);
- }
- }
- remainingPkgs.removeAll(result);
+ final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
+ applyPackageFilter((pkg) -> pkgNames.contains(pkg.packageName), result, remainingPkgs,
+ sortTemp, packageManagerService);
// Give priority to apps used by other apps.
- for (PackageParser.Package pkg : remainingPkgs) {
- if (PackageDexOptimizer.isUsedByOtherApps(pkg)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding app used by other apps " + result.size() + ": " +
- pkg.packageName);
- }
- result.add(pkg);
- }
- }
- remainingPkgs.removeAll(result);
+ applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result,
+ remainingPkgs, sortTemp, packageManagerService);
// Filter out packages that aren't recently used, add all remaining apps.
// TODO: add a property to control this?
+ Predicate<PackageParser.Package> remainingPredicate;
if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) {
if (DEBUG_DEXOPT) {
Log.i(TAG, "Looking at historical package use");
@@ -159,34 +152,24 @@
lastUsed.getLatestForegroundPackageUseTimeInMills();
// Be defensive if for some reason package usage has bogus data.
if (estimatedPreviousSystemUseTime != 0) {
- filterRecentlyUsedApps(remainingPkgs, estimatedPreviousSystemUseTime,
- SEVEN_DAYS_IN_MILLISECONDS);
+ final long cutoffTime = estimatedPreviousSystemUseTime - SEVEN_DAYS_IN_MILLISECONDS;
+ remainingPredicate =
+ (pkg) -> pkg.getLatestForegroundPackageUseTimeInMills() >= cutoffTime;
+ } else {
+ // No meaningful historical info. Take all.
+ remainingPredicate = (pkg) -> true;
}
+ sortPackagesByUsageDate(remainingPkgs, packageManagerService);
+ } else {
+ // No historical info. Take all.
+ remainingPredicate = (pkg) -> true;
}
- result.addAll(remainingPkgs);
-
- // Now go ahead and also add the libraries required for these packages.
- // TODO: Think about interleaving things.
- Set<PackageParser.Package> dependencies = new HashSet<>();
- for (PackageParser.Package p : result) {
- dependencies.addAll(packageManagerService.findSharedNonSystemLibraries(p));
- }
- if (!dependencies.isEmpty()) {
- // We might have packages already in `result` that are dependencies
- // of other packages. Make sure we don't add those to the list twice.
- dependencies.removeAll(result);
- }
- result.addAll(dependencies);
+ applyPackageFilter(remainingPredicate, result, remainingPkgs, sortTemp,
+ packageManagerService);
if (DEBUG_DEXOPT) {
- StringBuilder sb = new StringBuilder();
- for (PackageParser.Package pkg : result) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
- sb.append(pkg.packageName);
- }
- Log.i(TAG, "Packages to be dexopted: " + sb.toString());
+ Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
+ Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgs));
}
return result;
@@ -203,4 +186,15 @@
throw ee.rethrowAsIOException();
}
}
+
+ public static String packagesToString(Collection<PackageParser.Package> c) {
+ StringBuilder sb = new StringBuilder();
+ for (PackageParser.Package pkg : c) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(pkg.packageName);
+ }
+ return sb.toString();
+ }
}
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index 5ef518e..6e2fb10 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -20,6 +20,7 @@
import com.android.internal.app.AlertController.AlertParams;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.policy.EmergencyAffordanceManager;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.R;
@@ -124,6 +125,7 @@
private boolean mHasTelephony;
private boolean mHasVibrator;
private final boolean mShowSilentToggle;
+ private final EmergencyAffordanceManager mEmergencyAffordanceManager;
/**
* @param context everything needs a context :(
@@ -158,6 +160,8 @@
mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
+
+ mEmergencyAffordanceManager = new EmergencyAffordanceManager(context);
}
/**
@@ -305,6 +309,10 @@
addedKeys.add(actionKey);
}
+ if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+ mItems.add(getEmergencyAction());
+ }
+
mAdapter = new MyAdapter();
AlertParams params = new AlertParams(mContext);
@@ -458,6 +466,26 @@
};
}
+ private Action getEmergencyAction() {
+ return new SinglePressAction(com.android.internal.R.drawable.emergency_icon,
+ R.string.global_action_emergency) {
+ @Override
+ public void onPress() {
+ mEmergencyAffordanceManager.performEmergencyCall();
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+ };
+ }
+
private Action getAssistAction() {
return new SinglePressAction(com.android.internal.R.drawable.ic_action_assist_focused,
R.string.global_action_assist) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 36d9697..afd451d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1033,7 +1033,7 @@
mDtDy = tmpFloats[Matrix.MSCALE_Y];
float x = tmpFloats[Matrix.MTRANS_X];
float y = tmpFloats[Matrix.MTRANS_Y];
- mWin.mShownPosition.set((int) x, (int) y);
+ mWin.mShownPosition.set(Math.round(x), Math.round(y));
// Now set the alpha... but because our current hardware
// can't do alpha transformation on a non-opaque surface,
@@ -1129,7 +1129,7 @@
mDtDy = tmpFloats[Matrix.MSCALE_Y];
float x = tmpFloats[Matrix.MTRANS_X];
float y = tmpFloats[Matrix.MTRANS_Y];
- mWin.mShownPosition.set((int) x, (int) y);
+ mWin.mShownPosition.set(Math.round(x), Math.round(y));
mShownAlpha = mAlpha;
} else {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1242560..58b71f5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -52,6 +52,7 @@
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.os.ZygoteInit;
+import com.android.internal.policy.EmergencyAffordanceManager;
import com.android.internal.widget.ILockSettings;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
@@ -62,6 +63,7 @@
import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
+import com.android.server.emergency.EmergencyAffordanceService;
import com.android.server.fingerprint.FingerprintService;
import com.android.server.hdmi.HdmiControlService;
import com.android.server.input.InputManagerService;
@@ -1077,6 +1079,11 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
+ if (!disableNetwork && !disableNonCoreServices && EmergencyAffordanceManager.ENABLED) {
+ // EmergencyMode sevice
+ mSystemServiceManager.startService(EmergencyAffordanceService.class);
+ }
+
if (!disableNonCoreServices) {
// Dreams (interactive idle-time views, a/k/a screen savers, and doze mode)
mSystemServiceManager.startService(DreamManagerService.class);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6eb792b..17f0da0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -182,6 +182,14 @@
public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
/**
+ * Since the default voicemail number is empty, if a SIM card does not have a voicemail number
+ * available the user cannot use voicemail. This flag allows the user to edit the voicemail
+ * number in such cases, and is false by default.
+ * @hide
+ */
+ public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL= "editable_voicemail_number_bool";
+
+ /**
* Determine whether the voicemail notification is persistent in the notification bar. If true,
* the voicemail notifications cannot be dismissed from the notification bar.
*/
@@ -261,6 +269,17 @@
public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
/**
+ * Specifies a map from dialstrings to replacements for roaming network service numbers which
+ * cannot be replaced on the carrier side.
+ * <p>
+ * Individual entries have the format:
+ * [dialstring to replace]:[replacement]
+ * @hide
+ */
+ public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY =
+ "dial_string_replace_string_array";
+
+ /**
* Flag specifying whether WFC over IMS supports the "wifi only" option. If false, the wifi
* calling settings will not include an option for "wifi only". If true, the wifi calling
* settings will include an option for "wifi only"
@@ -710,6 +729,15 @@
"duration_blocking_disabled_after_emergency_int";
/**
+ * For carriers which require an empty flash to be sent before sending the normal 3-way calling
+ * flash, the duration in milliseconds of the empty flash to send. When {@code 0}, no empty
+ * flash is sent.
+ * @hide
+ */
+ public static final String KEY_CDMA_3WAYCALL_FLASH_DELAY_INT = "cdma_3waycall_flash_delay_int";
+
+
+ /**
* @hide
* The default value for preferred CDMA roaming mode (aka CDMA system select.)
* CDMA_ROAMING_MODE_RADIO_DEFAULT = the default roaming mode from the radio
@@ -772,6 +800,7 @@
sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true);
sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
+ sDefaults.putBoolean(KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
sDefaults.putBoolean(KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL, false);
sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
@@ -813,10 +842,12 @@
sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_DIAL_STRING_REPLACE_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_FORCE_HOME_NETWORK_BOOL, false);
sDefaults.putInt(KEY_GSM_DTMF_TONE_DELAY_INT, 0);
sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0);
sDefaults.putInt(KEY_CDMA_DTMF_TONE_DELAY_INT, 100);
+ sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
sDefaults.putBoolean(KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false);
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 2e5fbdc..d86de1e 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -141,7 +141,7 @@
cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
cFlags_darwin := -D_DARWIN_UNLIMITED_STREAMS
cFlags_windows := -Wno-maybe-uninitialized # Incorrectly marking use of Maybe.value() as error.
-cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
+cppFlags := -Wno-missing-field-initializers -fno-exceptions -fno-rtti
protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST)
# ==========================================================
diff --git a/wifi/java/android/net/wifi/ParcelUtil.java b/wifi/java/android/net/wifi/ParcelUtil.java
new file mode 100644
index 0000000..a26877d
--- /dev/null
+++ b/wifi/java/android/net/wifi/ParcelUtil.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+
+import java.io.ByteArrayInputStream;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+/**
+ * Provides utilities for writing/reading a non-Parcelable objects to/from
+ * a Parcel object.
+ *
+ * @hide
+ */
+public class ParcelUtil {
+ /**
+ * Write a PrivateKey object |key| to the specified Parcel |dest|.
+ *
+ * Below is the data format:
+ * |algorithm| -> String of algorithm name
+ * |endcodedKey| -> byte[] of key data
+ *
+ * For a null PrivateKey object, a null string will be written to |algorithm| and
+ * |encodedKey| will be skipped. Since a PrivateKey can only be constructed with
+ * a valid algorithm String.
+ *
+ * @param dest Parcel object to write to
+ * @param key PrivateKey object to read from.
+ */
+ public static void writePrivateKey(Parcel dest, PrivateKey key) {
+ if (key == null) {
+ dest.writeString(null);
+ return;
+ }
+
+ dest.writeString(key.getAlgorithm());
+ dest.writeByteArray(key.getEncoded());
+ }
+
+ /**
+ * Read/create a PrivateKey object from a specified Parcel object |in|.
+ *
+ * Refer to the function above for the expected data format.
+ *
+ * @param in Parcel object to read from
+ * @return a PrivateKey object or null
+ */
+ public static PrivateKey readPrivateKey(Parcel in) {
+ String algorithm = in.readString();
+ if (algorithm == null) {
+ return null;
+ }
+
+ byte[] userKeyBytes = in.createByteArray();
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+ return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(userKeyBytes));
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Write a X509Certificate object |cert| to a Parcel object |dest|.
+ * The data being written to the Parcel is just a byte[] of the encoded certificate data.
+ *
+ * @param dest Parcel object to write to
+ * @param cert X509Certificate object to read from
+ */
+ public static void writeCertificate(Parcel dest, X509Certificate cert) {
+ byte[] certBytes = null;
+ if (cert != null) {
+ try {
+ certBytes = cert.getEncoded();
+ } catch (CertificateEncodingException e) {
+ /* empty, write null. */
+ }
+ }
+ dest.writeByteArray(certBytes);
+ }
+
+ /**
+ * Read/create a X509Certificate object from a specified Parcel object |in|.
+ *
+ * @param in Parcel object to read from
+ * @return a X509Certficate object or null
+ */
+ public static X509Certificate readCertificate(Parcel in) {
+ byte[] certBytes = in.createByteArray();
+ if (certBytes == null) {
+ return null;
+ }
+
+ try {
+ CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
+ return (X509Certificate) cFactory
+ .generateCertificate(new ByteArrayInputStream(certBytes));
+ } catch (CertificateException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Write an array of X509Certificate objects |certs| to a Parcel object |dest|.
+ * The data being written to the Parcel are consist of an integer indicating
+ * the size of the array and the certificates data. Certificates data will be
+ * skipped for a null array or size of 0 array.
+ *
+ * @param dest Parcel object to write to
+ * @param certs array of X509Certificate objects to read from
+ */
+ public static void writeCertificates(Parcel dest, X509Certificate[] certs) {
+ if (certs == null || certs.length == 0) {
+ dest.writeInt(0);
+ return;
+ }
+
+ dest.writeInt(certs.length);
+ for (int i = 0; i < certs.length; i++) {
+ writeCertificate(dest, certs[i]);
+ }
+ }
+
+ /**
+ * Read/create an array of X509Certificate objects from a specified Parcel object |in|.
+ *
+ * @param in Parcel object to read from
+ * @return X509Certficate[] or null
+ */
+ public static X509Certificate[] readCertificates(Parcel in) {
+ int length = in.readInt();
+ if (length == 0) {
+ return null;
+ }
+
+ X509Certificate[] certs = new X509Certificate[length];
+ for (int i = 0; i < length; i++) {
+ certs[i] = readCertificate(in);
+ }
+ return certs;
+ }
+}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 67cf107..465addf 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -139,12 +139,6 @@
public long seen;
/**
- * If the scan result is a valid autojoin candidate
- * {@hide}
- */
- public int isAutoJoinCandidate;
-
- /**
* @hide
* Update RSSI of the scan result
* @param previousRssi
@@ -452,7 +446,6 @@
numConnection = source.numConnection;
numUsage = source.numUsage;
numIpConfigFailures = source.numIpConfigFailures;
- isAutoJoinCandidate = source.isAutoJoinCandidate;
venueName = source.venueName;
operatorFriendlyName = source.operatorFriendlyName;
flags = source.flags;
@@ -530,7 +523,6 @@
dest.writeInt(numConnection);
dest.writeInt(numUsage);
dest.writeInt(numIpConfigFailures);
- dest.writeInt(isAutoJoinCandidate);
dest.writeString((venueName != null) ? venueName.toString() : "");
dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
dest.writeLong(this.flags);
@@ -600,7 +592,6 @@
sr.numConnection = in.readInt();
sr.numUsage = in.readInt();
sr.numIpConfigFailures = in.readInt();
- sr.isAutoJoinCandidate = in.readInt();
sr.venueName = in.readString();
sr.operatorFriendlyName = in.readString();
sr.flags = in.readLong();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index c0e8bc2..e410a9c 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -183,48 +183,14 @@
dest.writeInt(mEapMethod);
dest.writeInt(mPhase2Method);
- writeCertificates(dest, mCaCerts);
-
- if (mClientPrivateKey != null) {
- String algorithm = mClientPrivateKey.getAlgorithm();
- byte[] userKeyBytes = mClientPrivateKey.getEncoded();
- dest.writeInt(userKeyBytes.length);
- dest.writeByteArray(userKeyBytes);
- dest.writeString(algorithm);
- } else {
- dest.writeInt(0);
- }
-
- writeCertificate(dest, mClientCertificate);
- }
-
- private void writeCertificates(Parcel dest, X509Certificate[] cert) {
- if (cert != null && cert.length != 0) {
- dest.writeInt(cert.length);
- for (int i = 0; i < cert.length; i++) {
- writeCertificate(dest, cert[i]);
- }
- } else {
- dest.writeInt(0);
- }
- }
-
- private void writeCertificate(Parcel dest, X509Certificate cert) {
- if (cert != null) {
- try {
- byte[] certBytes = cert.getEncoded();
- dest.writeInt(certBytes.length);
- dest.writeByteArray(certBytes);
- } catch (CertificateEncodingException e) {
- dest.writeInt(0);
- }
- } else {
- dest.writeInt(0);
- }
+ ParcelUtil.writeCertificates(dest, mCaCerts);
+ ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
+ ParcelUtil.writeCertificate(dest, mClientCertificate);
}
public static final Creator<WifiEnterpriseConfig> CREATOR =
new Creator<WifiEnterpriseConfig>() {
+ @Override
public WifiEnterpriseConfig createFromParcel(Parcel in) {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
int count = in.readInt();
@@ -236,58 +202,13 @@
enterpriseConfig.mEapMethod = in.readInt();
enterpriseConfig.mPhase2Method = in.readInt();
- enterpriseConfig.mCaCerts = readCertificates(in);
-
- PrivateKey userKey = null;
- int len = in.readInt();
- if (len > 0) {
- try {
- byte[] bytes = new byte[len];
- in.readByteArray(bytes);
- String algorithm = in.readString();
- KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
- userKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes));
- } catch (NoSuchAlgorithmException e) {
- userKey = null;
- } catch (InvalidKeySpecException e) {
- userKey = null;
- }
- }
-
- enterpriseConfig.mClientPrivateKey = userKey;
- enterpriseConfig.mClientCertificate = readCertificate(in);
+ enterpriseConfig.mCaCerts = ParcelUtil.readCertificates(in);
+ enterpriseConfig.mClientPrivateKey = ParcelUtil.readPrivateKey(in);
+ enterpriseConfig.mClientCertificate = ParcelUtil.readCertificate(in);
return enterpriseConfig;
}
- private X509Certificate[] readCertificates(Parcel in) {
- X509Certificate[] certs = null;
- int len = in.readInt();
- if (len > 0) {
- certs = new X509Certificate[len];
- for (int i = 0; i < len; i++) {
- certs[i] = readCertificate(in);
- }
- }
- return certs;
- }
-
- private X509Certificate readCertificate(Parcel in) {
- X509Certificate cert = null;
- int len = in.readInt();
- if (len > 0) {
- try {
- byte[] bytes = new byte[len];
- in.readByteArray(bytes);
- CertificateFactory cFactory = CertificateFactory.getInstance("X.509");
- cert = (X509Certificate) cFactory
- .generateCertificate(new ByteArrayInputStream(bytes));
- } catch (CertificateException e) {
- cert = null;
- }
- }
- return cert;
- }
-
+ @Override
public WifiEnterpriseConfig[] newArray(int size) {
return new WifiEnterpriseConfig[size];
}
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index 56baba9..5485824 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
@@ -23,6 +23,7 @@
import android.net.wifi.nan.IWifiNanEventCallback;
import android.net.wifi.nan.PublishConfig;
import android.net.wifi.nan.SubscribeConfig;
+import android.net.wifi.nan.WifiNanCharacteristics;
import android.net.wifi.RttManager;
/**
@@ -36,6 +37,7 @@
void enableUsage();
void disableUsage();
boolean isUsageEnabled();
+ WifiNanCharacteristics getCharacteristics();
// client API
void connect(in IBinder binder, in String callingPackage, in IWifiNanEventCallback callback,
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/nan/PublishConfig.java
index 4b67f9a..30c5bc0 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/nan/PublishConfig.java
@@ -182,7 +182,7 @@
*
* @hide
*/
- public void validate() throws IllegalArgumentException {
+ public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
WifiNanUtils.validateServiceName(mServiceName);
if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
@@ -198,6 +198,26 @@
if (mTtlSec < 0) {
throw new IllegalArgumentException("Invalid ttlSec - must be non-negative");
}
+
+ if (characteristics != null) {
+ int maxServiceNameLength = characteristics.getMaxServiceNameLength();
+ if (maxServiceNameLength != 0 && mServiceName.length > maxServiceNameLength) {
+ throw new IllegalArgumentException(
+ "Service name longer than supported by device characteristics");
+ }
+ int maxServiceSpecificInfoLength = characteristics.getMaxServiceSpecificInfoLength();
+ if (maxServiceSpecificInfoLength != 0 && mServiceSpecificInfo != null
+ && mServiceSpecificInfo.length > maxServiceSpecificInfoLength) {
+ throw new IllegalArgumentException(
+ "Service specific info longer than supported by device characteristics");
+ }
+ int maxMatchFilterLength = characteristics.getMaxMatchFilterLength();
+ if (maxMatchFilterLength != 0 && mMatchFilter != null
+ && mMatchFilter.length > maxMatchFilterLength) {
+ throw new IllegalArgumentException(
+ "Match filter longer than supported by device characteristics");
+ }
+ }
}
/**
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
index 4352fcf..ea7b8e4 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
@@ -209,7 +209,7 @@
*
* @hide
*/
- public void validate() throws IllegalArgumentException {
+ public void assertValid(WifiNanCharacteristics characteristics) throws IllegalArgumentException {
WifiNanUtils.validateServiceName(mServiceName);
if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
@@ -229,6 +229,26 @@
throw new IllegalArgumentException(
"Invalid matchType - must be MATCH_FIRST_ONLY or MATCH_ALL");
}
+
+ if (characteristics != null) {
+ int maxServiceNameLength = characteristics.getMaxServiceNameLength();
+ if (maxServiceNameLength != 0 && mServiceName.length > maxServiceNameLength) {
+ throw new IllegalArgumentException(
+ "Service name longer than supported by device characteristics");
+ }
+ int maxServiceSpecificInfoLength = characteristics.getMaxServiceSpecificInfoLength();
+ if (maxServiceSpecificInfoLength != 0 && mServiceSpecificInfo != null
+ && mServiceSpecificInfo.length > maxServiceSpecificInfoLength) {
+ throw new IllegalArgumentException(
+ "Service specific info longer than supported by device characteristics");
+ }
+ int maxMatchFilterLength = characteristics.getMaxMatchFilterLength();
+ if (maxMatchFilterLength != 0 && mMatchFilter != null
+ && mMatchFilter.length > maxMatchFilterLength) {
+ throw new IllegalArgumentException(
+ "Match filter longer than supported by device characteristics");
+ }
+ }
}
/**
diff --git a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
new file mode 100644
index 0000000..e562a00
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nan;
+
+parcelable WifiNanCharacteristics;
diff --git a/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
new file mode 100644
index 0000000..f43ed4d
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/WifiNanCharacteristics.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nan;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The characteristics of the Wi-Fi NAN implementation.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+public class WifiNanCharacteristics implements Parcelable {
+ /** @hide */
+ public static final String KEY_MAX_SERVICE_NAME_LENGTH = "key_max_service_name_length";
+ /** @hide */
+ public static final String KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH =
+ "key_max_service_specific_info_length";
+ /** @hide */
+ public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
+
+ private Bundle mCharacteristics = new Bundle();
+
+ /** @hide : should not be created by apps */
+ public WifiNanCharacteristics(Bundle characteristics) {
+ mCharacteristics = characteristics;
+ }
+
+ /**
+ * Returns the maximum string length that can be used to specify a NAN service name. Restricts
+ * the parameters of the {@link PublishConfig.Builder#setServiceName(String)} and
+ * {@link SubscribeConfig.Builder#setServiceName(String)}.
+ *
+ * @return A positive integer, maximum string length of NAN service name.
+ */
+ public int getMaxServiceNameLength() {
+ return mCharacteristics.getInt(KEY_MAX_SERVICE_NAME_LENGTH);
+ }
+
+ /**
+ * Returns the maximum length of byte array that can be used to specify a NAN service specific
+ * information field: the arbitrary load used in discovery or the message length of NAN
+ * message exchange. Restricts the parameters of the
+ * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
+ * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
+ * {@link WifiNanDiscoveryBaseSession#sendMessage(Object, int, byte[])} variants.
+ *
+ * @return A positive integer, maximum length of byte array for NAN messaging.
+ */
+ public int getMaxServiceSpecificInfoLength() {
+ return mCharacteristics.getInt(KEY_MAX_SERVICE_SPECIFIC_INFO_LENGTH);
+ }
+
+ /**
+ * Returns the maximum length of byte array that can be used to specify a NAN match filter.
+ * Restricts the parameters of the {@link PublishConfig.Builder#setMatchFilter(byte[])} and
+ * {@link SubscribeConfig.Builder#setMatchFilter(byte[])}.
+ *
+ * @return A positive integer, maximum legngth of byte array for NAN discovery match filter.
+ */
+ public int getMaxMatchFilterLength() {
+ return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBundle(mCharacteristics);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<WifiNanCharacteristics> CREATOR =
+ new Creator<WifiNanCharacteristics>() {
+ @Override
+ public WifiNanCharacteristics createFromParcel(Parcel in) {
+ WifiNanCharacteristics c = new WifiNanCharacteristics(in.readBundle());
+ return c;
+ }
+
+ @Override
+ public WifiNanCharacteristics[] newArray(int size) {
+ return new WifiNanCharacteristics[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 705ba4a..002b953 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -201,6 +201,8 @@
* Use the {@link #isAvailable()} to query the current status.
* This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
* the broadcast to check the current state of Wi-Fi NAN.
+ * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+ * components will be launched.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_WIFI_NAN_STATE_CHANGED =
@@ -291,6 +293,20 @@
}
/**
+ * Returns the characteristics of the Wi-Fi NAN interface: a set of parameters which specify
+ * limitations on configurations, e.g. the maximum service name length.
+ *
+ * @return An object specifying configuration limitations of NAN.
+ */
+ public WifiNanCharacteristics getCharacteristics() {
+ try {
+ return mService.getCharacteristics();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Attach to the Wi-Fi NAN service - enabling the application to create discovery sessions or
* create connections to peers. The device will attach to an existing cluster if it can find
* one or create a new cluster (if it is the first to enable NAN in its vicinity). Results
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index 5fb2c06..df5e3c1 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -113,6 +113,8 @@
* An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
* terminate the publish discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
+ * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+ * permission to start a publish discovery session.
*
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
@@ -156,6 +158,8 @@
* An application must use the {@link WifiNanDiscoveryBaseSession#destroy()} to
* terminate the subscribe discovery session once it isn't needed. This will free
* resources as well terminate any on-air transmissions.
+ * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+ * permission to start a subscribe discovery session.
*
* @param handler The Handler on whose thread to execute the callbacks of the {@code
* callback} object. If a null is provided then the application's main thread will be used.
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
new file mode 100644
index 0000000..5850fee
--- /dev/null
+++ b/wifi/tests/Android.mk
@@ -0,0 +1,61 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Make test APK
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+# This list is generated from the java source files in this module
+# The list is a comma separated list of class names with * matching zero or more characters.
+# Example:
+# Input files: src/com/android/server/wifi/Test.java src/com/android/server/wifi/AnotherTest.java
+# Generated exclude list: com.android.server.wifi.Test*,com.android.server.wifi.AnotherTest*
+
+# Filter all src files to just java files
+local_java_files := $(filter %.java,$(LOCAL_SRC_FILES))
+# Transform java file names into full class names.
+# This only works if the class name matches the file name and the directory structure
+# matches the package.
+local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
+# Utility variables to allow replacing a space with a comma
+comma:= ,
+empty:=
+space:= $(empty) $(empty)
+# Convert class name list to jacoco exclude list
+# This appends a * to all classes and replace the space separators with commas.
+# These patterns will match all classes in this module and their inner classes.
+jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
+
+jacoco_include := android.net.wifi.*
+
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include)
+LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test \
+ mockito-target-minus-junit4 \
+ frameworks-base-testutils \
+
+LOCAL_JAVA_LIBRARIES := \
+ android.test.runner \
+
+LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+
+include $(BUILD_PACKAGE)
diff --git a/wifi/tests/AndroidManifest.xml b/wifi/tests/AndroidManifest.xml
new file mode 100644
index 0000000..4eaca2b
--- /dev/null
+++ b/wifi/tests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2016 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.net.wifi.test">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:label="WifiTestDummyLabel"
+ android:name="WifiTestDummyName">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.net.wifi.test"
+ android:label="Frameworks Wifi API Tests">
+ </instrumentation>
+
+</manifest>
diff --git a/wifi/tests/README.md b/wifi/tests/README.md
new file mode 100644
index 0000000..b418abd
--- /dev/null
+++ b/wifi/tests/README.md
@@ -0,0 +1,50 @@
+# Wifi Unit Tests
+This package contains unit tests for the android wifi framework APIs based on the
+[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html).
+The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/)
+libraries.
+
+## Running Tests
+The easiest way to run tests is simply run
+
+```
+frameworks/base/wifi/tests/runtests.sh
+```
+
+`runtests.sh` will build the test project and all of its dependencies and push the APK to the
+connected device. It will then run the tests on the device.
+
+To pick up changes in framework/base, you will need to:
+1. rebuild the framework library 'make -j32'
+2. sync over the updated library to the device 'adb sync'
+3. restart framework on the device 'adb shell stop' then 'adb shell start'
+
+To enable syncing data to the device for first time after clean reflash:
+1. adb disable-verity
+2. adb reboot
+3. adb remount
+
+See below for a few example of options to limit which tests are run.
+See the
+[AndroidJUnitRunner Documentation](https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html)
+for more details on the supported options.
+
+```
+runtests.sh -e package android.net.wifi
+runtests.sh -e class android.net.wifi.WifiScannerTest
+```
+
+If you manually build and push the test APK to the device you can run tests using
+
+```
+adb shell am instrument -w 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
+```
+
+## Adding Tests
+Tests can be added by adding classes to the src directory. JUnit4 style test cases can
+be written by simply annotating test methods with `org.junit.Test`.
+
+## Debugging Tests
+If you are trying to debug why tests are not doing what you expected, you can add android log
+statements and use logcat to view them. The beginning and end of every tests is automatically logged
+with the tag `TestRunner`.
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
new file mode 100755
index 0000000..ebcc2a2
--- /dev/null
+++ b/wifi/tests/runtests.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+
+echo "Running tests"
+
+set -e # fail early
+
+echo "+ mmma -j32 $ANDROID_BUILD_TOP/frameworks/base/wifi/tests"
+# NOTE Don't actually run the command above since this shell doesn't inherit functions from the
+# caller.
+make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk MODULES-IN-frameworks-base-wifi-tests
+
+set -x # print commands
+
+adb root
+adb wait-for-device
+
+adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
+
+adb shell am instrument -w "$@" 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
new file mode 100644
index 0000000..c0d60c3
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net.wifi;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+/**
+ * A class containing test certificates and private keys.
+ */
+public class FakeKeys {
+ private static final String CA_CERT0_STRING = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKDCCAhCgAwIBAgIJAILlFdwzLVurMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" +
+ "BAMTB0VBUCBDQTEwHhcNMTYwMTEyMTE1MDE1WhcNMjYwMTA5MTE1MDE1WjASMRAw\n" +
+ "DgYDVQQDEwdFQVAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" +
+ "znAPUz26Msae4ws43czR41/J2QtrSIZUKmVUsVumDbYHrPNvTXKSMXAcewORDQYX\n" +
+ "RqvHvpn8CscB1+oGXZvHwxj4zV0WKoK2zeXkau3vcyl3HIKupJfq2TEACefVjj0t\n" +
+ "JW+X35PGWp9/H5zIUNVNVjS7Ums84IvKhRB8512PB9UyHagXYVX5GWpAcVpyfrlR\n" +
+ "FI9Qdhh+Pbk0uyktdbf/CdfgHOoebrTtwRljM0oDtX+2Cv6j0wBK7hD8pPvf1+uy\n" +
+ "GzczigAU/4Kw7eZqydf9B+5RupR+IZipX41xEiIrKRwqi517WWzXcjaG2cNbf451\n" +
+ "xpH5PnV3i1tq04jMGQUzFwIDAQABo4GAMH4wHQYDVR0OBBYEFIwX4vs8BiBcScod\n" +
+ "5noZHRM8E4+iMEIGA1UdIwQ7MDmAFIwX4vs8BiBcScod5noZHRM8E4+ioRakFDAS\n" +
+ "MRAwDgYDVQQDEwdFQVAgQ0ExggkAguUV3DMtW6swDAYDVR0TBAUwAwEB/zALBgNV\n" +
+ "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAFfQqOTA7Rv7K+luQ7pnas4BYwHE\n" +
+ "9GEP/uohv6KOy0TGQFbrRTjFoLVNB9BZ1ymMDZ0/TIwIUc7wi7a8t5mEqYH153wW\n" +
+ "aWooiSjyLLhuI4sNrNCOtisdBq2r2MFXt6h0mAQYOPv8R8K7/fgSxGFqzhyNmmVL\n" +
+ "1qBJldx34SpwsTALQVPb4hGwJzZfr1PcpEQx6xMnTl8xEWZE3Ms99uaUxbQqIwRu\n" +
+ "LgAOkNCmY2m89VhzaHJ1uV85AdM/tD+Ysmlnnjt9LRCejbBipjIGjOXrg1JP+lxV\n" +
+ "muM4vH+P/mlmxsPPz0d65b+EGmJZpoLkO/tdNNvCYzjJpTEWpEsO6NMhKYo=\n" +
+ "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CA_CERT0 = loadCertificate(CA_CERT0_STRING);
+
+ private static final String CA_CERT1_STRING = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKDCCAhCgAwIBAgIJAOM5SzKO2pzCMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV\n" +
+ "BAMTB0VBUCBDQTAwHhcNMTYwMTEyMDAxMDQ3WhcNMjYwMTA5MDAxMDQ3WjASMRAw\n" +
+ "DgYDVQQDEwdFQVAgQ0EwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n" +
+ "89ug+IEKVQXnJGKg5g4uVHg6J/8iRUxR5k2eH5o03hrJNMfN2D+cBe/wCiZcnWbI\n" +
+ "GbGZACWm2nQth2wy9Zgm2LOd3b4ocrHYls3XLq6Qb5Dd7a0JKU7pdGufiNVEkrmF\n" +
+ "EB+N64wgwH4COTvCiN4erp5kyJwkfqAl2xLkZo0C464c9XoyQOXbmYD9A8v10wZu\n" +
+ "jyNsEo7Nr2USyw+qhjWSbFbEirP77Tvx+7pJQJwdtk1V9Tn73T2dGF2WHYejei9S\n" +
+ "mcWpdIUqsu9etYH+zDmtu7I1xlkwiaVsNr2+D+qaCJyOYqrDTKVNK5nmbBPXDWZc\n" +
+ "NoDbTOoqquX7xONpq9M6jQIDAQABo4GAMH4wHQYDVR0OBBYEFAZ3A2S4qJZZwuNY\n" +
+ "wkJ6mAdc0gVdMEIGA1UdIwQ7MDmAFAZ3A2S4qJZZwuNYwkJ6mAdc0gVdoRakFDAS\n" +
+ "MRAwDgYDVQQDEwdFQVAgQ0EwggkA4zlLMo7anMIwDAYDVR0TBAUwAwEB/zALBgNV\n" +
+ "HQ8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAHmdMwEhtys4d0E+t7owBmoVR+lU\n" +
+ "hMCcRtWs8YKX5WIM2kTweT0h/O1xwE1mWmRv/IbDAEb8od4BjAQLhIcolStr2JaO\n" +
+ "9ZzyxjOnNzqeErh/1DHDbb/moPpqfeJ8YiEz7nH/YU56Q8iCPO7TsgS0sNNE7PfN\n" +
+ "IUsBW0yHRgpQ4OxWmiZG2YZWiECRzAC0ecPzo59N5iH4vLQIMTMYquiDeMPQnn1e\n" +
+ "NDGxG8gCtDKIaS6tMg3a28MvWB094pr2ETou8O1C8Ji0Y4hE8QJmSdT7I4+GZjgW\n" +
+ "g94DZ5RiL7sdp3vC48CXOmeT61YBIvhGUsE1rPhXqkpqQ3Z3C4TFF0jXZZc=\n" +
+ "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CA_CERT1 = loadCertificate(CA_CERT1_STRING);
+
+ private static final String CLIENT_CERT_STR = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIE/DCCAuQCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxCzAJBgNV\n" +
+ "BAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdUZXN0aW5n\n" +
+ "MB4XDTE2MDkzMDIwNTQyOFoXDTE3MDkzMDIwNTQyOFowRDELMAkGA1UEBhMCVVMx\n" +
+ "CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdU\n" +
+ "ZXN0aW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnpmcbuaeHfnJ\n" +
+ "k+2QNvxmdVFTawyFMNk0USCq5sexscwmxbewG/Rb8YnixwJWS44v2XkSujB67z5C\n" +
+ "s2qudFEhRXKdEuC6idbAuA97KjipHh0AAniWMsyv61fvbgsUC0b0canx3LiDq81p\n" +
+ "y28NNGmAvoazLZUZ4AhBRiwYZY6FKk723gmZoGbEIeG7J1dlXPusc1662rIjz4eU\n" +
+ "zlmmlvqyHfNqnNk8L14Vug6Xh+lOEGN85xhu1YHAEKGrS89kZxs5rum/cZU8KH2V\n" +
+ "v6eKnY03kxjiVLQtnLpm/7VUEoCMGHyruRj+p3my4+DgqMsmsH52RZCBsjyGlpbU\n" +
+ "NOwOTIX6xh+Rqloduz4AnrMYYIiIw2s8g+2zJM7VbcVKx0fGS26BKdrxgrXWfmNE\n" +
+ "nR0/REQ5AxDGw0jfTUvtdTkXAf+K4MDjcNLEZ+MA4rHfAfQWZtUR5BkHCQYxNpJk\n" +
+ "pA0gyk+BpKdC4WdzI14NSWsu5sRCmBCFqH6BTOSEq/V1cNorBxNwLSSTwFFqUDqx\n" +
+ "Y5nQLXygkJf9WHZWtSKeSjtOYgilz7UKzC2s3CsjmIyGFe+SwpuHJnuE4Uc8Z5Cb\n" +
+ "bjNGHPzqL6XnmzZHJp7RF8kBdKdjGC7dCUltzOfICZeKlzOOq+Kw42T/nXjuXvpb\n" +
+ "nkXNxg741Nwd6RecykXJbseFwm3EYxkCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEA\n" +
+ "Ga1mGwI9aXkL2fTPXO9YkAPzoGeX8aeuVYSQaSkNq+5vnogYCyAt3YDHjRG+ewTT\n" +
+ "WbnPA991xRAPac+biJeXWmwvgGj0YuT7e79phAiGkTTnbAjFHGfYnBy/tI/v7btO\n" +
+ "hRNElA5yTJ1m2fVbBEKXzMR83jrT9iyI+YLRN86zUZIaC86xxSbqnrdWN2jOK6MX\n" +
+ "dS8Arp9tPQjC/4gW+2Ilxv68jiYh+5auWHQZVjppWVY//iu4mAbkq1pTwQEhZ8F8\n" +
+ "Zrmh9DHh60hLFcfSuhIAwf/NMzppwdkjy1ruKVrpijhGKGp4OWu8nvOUgHSzxc7F\n" +
+ "PwpVZ5N2Ku4L8MLO6BG2VasRJK7l17TzDXlfLZHJjkuryOFxVaQKt8ZNFgTOaCXS\n" +
+ "E+gpTLksKU7riYckoiP4+H1sn9qcis0e8s4o/uf1UVc8GSdDw61ReGM5oZEDm1u8\n" +
+ "H9x20QU6igLqzyBpqvCKv7JNgU1uB2PAODHH78zJiUfnKd1y+o+J1iWzaGj3EFji\n" +
+ "T8AXksbTP733FeFXfggXju2dyBH+Z1S5BBTEOd1brWgXlHSAZGm97MKZ94r6/tkX\n" +
+ "qfv3fCos0DKz0oV7qBxYS8wiYhzrRVxG6ITAoH8uuUVVQaZF+G4nJ2jEqNbfuKyX\n" +
+ "ATQsVNjNNlDA0J33GobPMjT326wa4YAWMx8PI5PJZ3g=\n" +
+ "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CLIENT_CERT = loadCertificate(CLIENT_CERT_STR);
+
+ private static final byte[] FAKE_RSA_KEY_1 = new byte[] {
+ (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+ (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+ (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+ (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+ (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+ (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+ (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+ (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+ (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+ (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+ (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+ (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+ (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+ (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+ (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+ (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+ (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+ (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+ (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+ (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+ (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+ (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+ (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+ (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+ (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+ (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+ (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+ (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+ (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+ (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+ (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+ (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+ (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+ (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+ (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+ (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+ (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+ (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+ (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+ (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+ (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+ (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+ (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+ (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+ (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+ (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+ (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+ (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+ (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+ (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+ (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+ (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+ (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+ (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+ (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+ (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+ (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+ (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+ (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+ (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+ (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+ (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+ (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+ (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+ (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+ (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+ (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+ (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+ (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+ (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+ (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+ (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+ (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+ (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+ (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+ (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+ (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+ (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+ (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+ (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+ (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+ (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+ (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+ (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+ (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+ (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+ (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+ (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+ (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+ (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+ (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+ (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+ (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+ (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+ (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+ (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+ (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+ (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+ (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+ (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+ (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+ (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+ (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+ (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+ (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+ (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+ };
+ public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1);
+
+ private static X509Certificate loadCertificate(String blob) {
+ try {
+ final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ InputStream stream = new ByteArrayInputStream(blob.getBytes(StandardCharsets.UTF_8));
+
+ return (X509Certificate) certFactory.generateCertificate(stream);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static PrivateKey loadPrivateRSAKey(byte[] fakeKey) {
+ try {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ return kf.generatePrivate(new PKCS8EncodedKeySpec(fakeKey));
+ } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+ return null;
+ }
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/ParcelUtilTest.java b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
new file mode 100644
index 0000000..6787594
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/ParcelUtilTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * Unit tests for {@link android.net.wifi.ParcelUtil}.
+ */
+@SmallTest
+public class ParcelUtilTest {
+ private Parcel mParcel;
+
+ @Before
+ public void setUp() throws Exception {
+ mParcel = Parcel.obtain();
+ }
+
+ @Test
+ public void readWriteNullPrivateKey() throws Exception {
+ ParcelUtil.writePrivateKey(mParcel, null);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ PrivateKey readKey = ParcelUtil.readPrivateKey(mParcel);
+ assertNull(readKey);
+ }
+
+ @Test
+ public void readWriteValidPrivateKey() throws Exception {
+ PrivateKey writeKey = FakeKeys.RSA_KEY1;
+ ParcelUtil.writePrivateKey(mParcel, writeKey);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ PrivateKey readKey = ParcelUtil.readPrivateKey(mParcel);
+ assertNotNull(readKey);
+ assertEquals(writeKey.getAlgorithm(), readKey.getAlgorithm());
+ assertArrayEquals(writeKey.getEncoded(), readKey.getEncoded());
+ }
+
+ @Test
+ public void readWriteNullCertificate() throws Exception {
+ ParcelUtil.writeCertificate(mParcel, null);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ X509Certificate readCert = ParcelUtil.readCertificate(mParcel);
+ assertNull(readCert);
+ }
+
+ @Test
+ public void readWriteValidCertificate() throws Exception {
+ X509Certificate writeCert = FakeKeys.CA_CERT1;
+ ParcelUtil.writeCertificate(mParcel, writeCert);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ X509Certificate readCert = ParcelUtil.readCertificate(mParcel);
+ assertNotNull(readCert);
+ assertArrayEquals(writeCert.getEncoded(), readCert.getEncoded());
+ }
+
+ @Test
+ public void readWriteNullCertificates() throws Exception {
+ ParcelUtil.writeCertificates(mParcel, null);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ X509Certificate[] readCerts = ParcelUtil.readCertificates(mParcel);
+ assertNull(readCerts);
+ }
+
+ @Test
+ public void readWriteValidCertificates() throws Exception {
+ X509Certificate[] writeCerts = new X509Certificate[2];
+ writeCerts[0] = FakeKeys.CA_CERT0;
+ writeCerts[1] = FakeKeys.CA_CERT1;
+ ParcelUtil.writeCertificates(mParcel, writeCerts);
+
+ mParcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ X509Certificate[] readCerts = ParcelUtil.readCertificates(mParcel);
+ assertNotNull(readCerts);
+ assertEquals(writeCerts.length, readCerts.length);
+ for (int i = 0; i < writeCerts.length; i++) {
+ assertNotNull(readCerts[i]);
+ assertArrayEquals(writeCerts[i].getEncoded(), readCerts[i].getEncoded());
+ }
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
new file mode 100644
index 0000000..0e503d5
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.net.wifi.WifiEnterpriseConfig.Eap;
+import android.net.wifi.WifiEnterpriseConfig.Phase2;
+import android.os.Parcel;
+import android.security.Credentials;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiEnterpriseConfig}.
+ */
+@SmallTest
+public class WifiEnterpriseConfigTest {
+ // Maintain a ground truth of the keystore uri prefix which is expected by wpa_supplicant.
+ public static final String KEYSTORE_URI = "keystore://";
+ public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE;
+ public static final String KEYSTORES_URI = "keystores://";
+
+ private WifiEnterpriseConfig mEnterpriseConfig;
+
+ @Before
+ public void setUp() throws Exception {
+ mEnterpriseConfig = new WifiEnterpriseConfig();
+ }
+
+ @Test
+ public void testGetEmptyCaCertificate() {
+ // A newly-constructed WifiEnterpriseConfig object should have no CA certificate.
+ assertNull(mEnterpriseConfig.getCaCertificate());
+ assertNull(mEnterpriseConfig.getCaCertificates());
+ // Setting CA certificate to null explicitly.
+ mEnterpriseConfig.setCaCertificate(null);
+ assertNull(mEnterpriseConfig.getCaCertificate());
+ // Setting CA certificate to null using setCaCertificates().
+ mEnterpriseConfig.setCaCertificates(null);
+ assertNull(mEnterpriseConfig.getCaCertificates());
+ // Setting CA certificate to zero-length array.
+ mEnterpriseConfig.setCaCertificates(new X509Certificate[0]);
+ assertNull(mEnterpriseConfig.getCaCertificates());
+ }
+
+ @Test
+ public void testSetGetSingleCaCertificate() {
+ X509Certificate cert0 = FakeKeys.CA_CERT0;
+ mEnterpriseConfig.setCaCertificate(cert0);
+ assertEquals(mEnterpriseConfig.getCaCertificate(), cert0);
+ }
+
+ @Test
+ public void testSetGetMultipleCaCertificates() {
+ X509Certificate cert0 = FakeKeys.CA_CERT0;
+ X509Certificate cert1 = FakeKeys.CA_CERT1;
+ mEnterpriseConfig.setCaCertificates(new X509Certificate[] {cert0, cert1});
+ X509Certificate[] result = mEnterpriseConfig.getCaCertificates();
+ assertEquals(result.length, 2);
+ assertTrue(result[0] == cert0 && result[1] == cert1);
+ }
+
+ @Test
+ public void testSaveSingleCaCertificateAlias() {
+ final String alias = "single_alias 0";
+ mEnterpriseConfig.setCaCertificateAliases(new String[] {alias});
+ assertEquals(getCaCertField(), CA_CERT_PREFIX + alias);
+ }
+
+ @Test
+ public void testLoadSingleCaCertificateAlias() {
+ final String alias = "single_alias 1";
+ setCaCertField(CA_CERT_PREFIX + alias);
+ String[] aliases = mEnterpriseConfig.getCaCertificateAliases();
+ assertEquals(aliases.length, 1);
+ assertEquals(aliases[0], alias);
+ }
+
+ @Test
+ public void testSaveMultipleCaCertificates() {
+ final String alias0 = "single_alias 0";
+ final String alias1 = "single_alias 1";
+ mEnterpriseConfig.setCaCertificateAliases(new String[] {alias0, alias1});
+ assertEquals(getCaCertField(), String.format("%s%s %s",
+ KEYSTORES_URI,
+ WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0),
+ WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1)));
+ }
+
+ @Test
+ public void testLoadMultipleCaCertificates() {
+ final String alias0 = "single_alias 0";
+ final String alias1 = "single_alias 1";
+ setCaCertField(String.format("%s%s %s",
+ KEYSTORES_URI,
+ WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias0),
+ WifiEnterpriseConfig.encodeCaCertificateAlias(Credentials.CA_CERTIFICATE + alias1)));
+ String[] aliases = mEnterpriseConfig.getCaCertificateAliases();
+ assertEquals(aliases.length, 2);
+ assertEquals(aliases[0], alias0);
+ assertEquals(aliases[1], alias1);
+ }
+
+ private String getCaCertField() {
+ return mEnterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY);
+ }
+
+ private void setCaCertField(String value) {
+ mEnterpriseConfig.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, value);
+ }
+
+ // Retrieves the value for a specific key supplied to wpa_supplicant.
+ private class SupplicantConfigExtractor implements WifiEnterpriseConfig.SupplicantSaver {
+ private String mValue = null;
+ private String mKey;
+
+ SupplicantConfigExtractor(String key) {
+ mKey = key;
+ }
+
+ @Override
+ public boolean saveValue(String key, String value) {
+ if (key.equals(mKey)) {
+ mValue = value;
+ }
+ return true;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+ }
+
+ private String getSupplicantEapMethod() {
+ SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor(
+ WifiEnterpriseConfig.EAP_KEY);
+ mEnterpriseConfig.saveToSupplicant(entryExtractor);
+ return entryExtractor.getValue();
+ }
+
+ private String getSupplicantPhase2Method() {
+ SupplicantConfigExtractor entryExtractor = new SupplicantConfigExtractor(
+ WifiEnterpriseConfig.PHASE2_KEY);
+ mEnterpriseConfig.saveToSupplicant(entryExtractor);
+ return entryExtractor.getValue();
+ }
+
+ /** Verifies the default value for EAP outer and inner methods */
+ @Test
+ public void eapInnerDefault() {
+ assertEquals(null, getSupplicantEapMethod());
+ assertEquals(null, getSupplicantPhase2Method());
+ }
+
+ /** Verifies that the EAP inner method is reset when we switch to TLS */
+ @Test
+ public void eapPhase2MethodForTls() {
+ // Initially select an EAP method that supports an phase2.
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+ assertEquals("PEAP", getSupplicantEapMethod());
+ assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+ // Change the EAP method to another type which supports a phase2.
+ mEnterpriseConfig.setEapMethod(Eap.TTLS);
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+ // Change the EAP method to TLS which does not support a phase2.
+ mEnterpriseConfig.setEapMethod(Eap.TLS);
+ assertEquals(null, getSupplicantPhase2Method());
+ }
+
+ /** Verfies that the EAP inner method is reset when we switch phase2 to NONE */
+ @Test
+ public void eapPhase2None() {
+ // Initially select an EAP method that supports an phase2.
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+ assertEquals("PEAP", getSupplicantEapMethod());
+ assertEquals("\"auth=MSCHAPV2\"", getSupplicantPhase2Method());
+
+ // Change the phase2 method to NONE and ensure the value is cleared.
+ mEnterpriseConfig.setPhase2Method(Phase2.NONE);
+ assertEquals(null, getSupplicantPhase2Method());
+ }
+
+ /** Verfies that the correct "autheap" parameter is supplied for TTLS/GTC. */
+ @Test
+ public void peapGtcToTtls() {
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ mEnterpriseConfig.setPhase2Method(Phase2.GTC);
+ assertEquals("PEAP", getSupplicantEapMethod());
+ assertEquals("\"auth=GTC\"", getSupplicantPhase2Method());
+
+ mEnterpriseConfig.setEapMethod(Eap.TTLS);
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+ }
+
+ /** Verfies that the correct "auth" parameter is supplied for PEAP/GTC. */
+ @Test
+ public void ttlsGtcToPeap() {
+ mEnterpriseConfig.setEapMethod(Eap.TTLS);
+ mEnterpriseConfig.setPhase2Method(Phase2.GTC);
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ assertEquals("PEAP", getSupplicantEapMethod());
+ assertEquals("\"auth=GTC\"", getSupplicantPhase2Method());
+ }
+
+ /** Verfies that the copy constructor preseves the inner method information. */
+ @Test
+ public void copyConstructor() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(Eap.TTLS);
+ enterpriseConfig.setPhase2Method(Phase2.GTC);
+ mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+ }
+
+ /** Verfies that parceling a WifiEnterpriseConfig preseves method information. */
+ @Test
+ public void parcelConstructor() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(Eap.TTLS);
+ enterpriseConfig.setPhase2Method(Phase2.GTC);
+ Parcel parcel = Parcel.obtain();
+ enterpriseConfig.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0); // Allow parcel to be read from the beginning.
+ mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel);
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+ }
+
+ /**
+ * Verifies that parceling a WifiEnterpriseConfig preserves the key
+ * and certificates information.
+ */
+ @Test
+ public void parcelConfigWithKeyAndCerts() throws Exception {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ PrivateKey clientKey = FakeKeys.RSA_KEY1;
+ X509Certificate clientCert = FakeKeys.CLIENT_CERT;
+ X509Certificate[] caCerts = new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1};
+ enterpriseConfig.setClientKeyEntry(clientKey, clientCert);
+ enterpriseConfig.setCaCertificates(caCerts);
+ Parcel parcel = Parcel.obtain();
+ enterpriseConfig.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0); // Allow parcel to be read from the beginning.
+ mEnterpriseConfig = WifiEnterpriseConfig.CREATOR.createFromParcel(parcel);
+ PrivateKey actualClientKey = mEnterpriseConfig.getClientPrivateKey();
+ X509Certificate actualClientCert = mEnterpriseConfig.getClientCertificate();
+ X509Certificate[] actualCaCerts = mEnterpriseConfig.getCaCertificates();
+
+ /* Verify client private key. */
+ assertNotNull(actualClientKey);
+ assertEquals(clientKey.getAlgorithm(), actualClientKey.getAlgorithm());
+ assertArrayEquals(clientKey.getEncoded(), actualClientKey.getEncoded());
+
+ /* Verify client certificate. */
+ assertNotNull(actualClientCert);
+ assertArrayEquals(clientCert.getEncoded(), actualClientCert.getEncoded());
+
+ /* Verify CA certificates. */
+ assertNotNull(actualCaCerts);
+ assertEquals(caCerts.length, actualCaCerts.length);
+ for (int i = 0; i < caCerts.length; i++) {
+ assertNotNull(actualCaCerts[i]);
+ assertArrayEquals(caCerts[i].getEncoded(), actualCaCerts[i].getEncoded());
+ }
+ }
+
+ /** Verifies proper operation of the getKeyId() method. */
+ @Test
+ public void getKeyId() {
+ assertEquals("NULL", mEnterpriseConfig.getKeyId(null));
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(Eap.TTLS);
+ enterpriseConfig.setPhase2Method(Phase2.GTC);
+ assertEquals("TTLS_GTC", mEnterpriseConfig.getKeyId(enterpriseConfig));
+ mEnterpriseConfig.setEapMethod(Eap.PEAP);
+ mEnterpriseConfig.setPhase2Method(Phase2.MSCHAPV2);
+ assertEquals("PEAP_MSCHAPV2", mEnterpriseConfig.getKeyId(enterpriseConfig));
+ }
+
+ /** Verifies that passwords are not displayed in toString. */
+ @Test
+ public void passwordNotInToString() {
+ String password = "supersecret";
+ mEnterpriseConfig.setPassword(password);
+ assertFalse(mEnterpriseConfig.toString().contains(password));
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
new file mode 100644
index 0000000..a829eb9
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.validateMockitoUsage;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.wifi.WifiScanner.BssidInfo;
+import android.net.wifi.WifiScanner.BssidListener;
+import android.os.Handler;
+import android.os.Message;
+import android.os.test.TestLooper;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.util.test.BidirectionalAsyncChannelServer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiScanner}.
+ */
+@SmallTest
+public class WifiScannerTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private IWifiScanner mService;
+ @Mock
+ private BssidListener mBssidListener;
+
+ private WifiScanner mWifiScanner;
+ private TestLooper mLooper;
+ private Handler mHandler;
+
+ /**
+ * Setup before tests.
+ */
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mLooper = new TestLooper();
+ mHandler = mock(Handler.class);
+ BidirectionalAsyncChannelServer server = new BidirectionalAsyncChannelServer(
+ mContext, mLooper.getLooper(), mHandler);
+ when(mService.getMessenger()).thenReturn(server.getMessenger());
+ mWifiScanner = new WifiScanner(mContext, mService, mLooper.getLooper());
+ mLooper.dispatchAll();
+ }
+
+ /**
+ * Clean up after tests.
+ */
+ @After
+ public void cleanup() {
+ validateMockitoUsage();
+ }
+
+ private void verifySetHotlistMessage(Handler handler) {
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture());
+ assertEquals("message.what is not CMD_SET_HOTLIST",
+ WifiScanner.CMD_SET_HOTLIST,
+ messageCaptor.getValue().what);
+ }
+
+ /**
+ * Test duplicate listeners for bssid tracking.
+ */
+ @Test
+ public void testStartTrackingBssidsDuplicateListeners() throws Exception {
+ BssidInfo[] bssids = new BssidInfo[] {
+ new BssidInfo()
+ };
+
+ // First start tracking succeeds.
+ mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
+ mLooper.dispatchAll();
+ verifySetHotlistMessage(mHandler);
+
+ // Second start tracking should fail.
+ mWifiScanner.startTrackingBssids(bssids, -100, mBssidListener);
+ mLooper.dispatchAll();
+ verify(mBssidListener).onFailure(eq(WifiScanner.REASON_DUPLICATE_REQEUST), anyString());
+ }
+}