Merge "Move tests added in n-mr2 into new aosp location."
diff --git a/api/system-current.txt b/api/system-current.txt
index a2bd6c5..920780f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40771,6 +40771,8 @@
method public java.lang.String getDeviceSoftwareVersion();
method public java.lang.String getGroupIdLevel1();
method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+ method public java.lang.String getImei();
+ method public java.lang.String getImei(int);
method public java.lang.String getLine1Number();
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index c7612d1..a265dd0 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -212,7 +212,7 @@
public native final HwBlob readBuffer();
public native final HwBlob readEmbeddedBuffer(
- long parentHandle, long offset);
+ long parentHandle, long offset, boolean nullable);
public native final void writeBuffer(HwBlob blob);
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index c5ceecd..1ee83ae 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -25,5 +25,5 @@
boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
boolean setupBcb(in String command);
boolean clearBcb();
- void rebootRecoveryWithCommand(in String command);
+ void rebootRecoveryWithCommand(in String command, in boolean update);
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index d48431a..7f9ea438 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -491,15 +491,10 @@
command += securityArg;
}
+ // RECOVERY_SERVICE writes to BCB (bootloader control block) and triggers the reboot.
RecoverySystem rs = (RecoverySystem) context.getSystemService(
Context.RECOVERY_SERVICE);
- if (!rs.setupBcb(command)) {
- throw new IOException("Setup BCB failed");
- }
-
- // Having set up the BCB (bootloader control block), go ahead and reboot
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY_UPDATE);
+ rs.rebootRecoveryWithCommand(command, true /* update */);
throw new IOException("Reboot failed (no permissions?)");
}
@@ -713,7 +708,7 @@
// 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());
+ rs.rebootRecoveryWithCommand(command.toString(), false);
throw new IOException("Reboot failed (no permissions?)");
}
@@ -913,9 +908,9 @@
* Talks to RecoverySystemService via Binder to set up the BCB command and
* reboot into recovery accordingly.
*/
- private void rebootRecoveryWithCommand(String command) {
+ private void rebootRecoveryWithCommand(String command, boolean update) {
try {
- mService.rebootRecoveryWithCommand(command);
+ mService.rebootRecoveryWithCommand(command, update);
} catch (RemoteException ignored) {
}
}
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index aefdc84..1bd2333 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -822,7 +822,8 @@
}
static jobject JHwParcel_native_readEmbeddedBuffer(
- JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
+ JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset,
+ jboolean nullable) {
hardware::Parcel *parcel =
JHwParcel::GetNativeContext(env, thiz)->getParcel();
@@ -830,11 +831,15 @@
const void *ptr;
status_t status =
- parcel->readEmbeddedBuffer(&childHandle, parentHandle, offset, &ptr);
+ parcel->readNullableEmbeddedBuffer(&childHandle, parentHandle, offset,
+ &ptr);
if (status != OK) {
jniThrowException(env, "java/util/NoSuchElementException", NULL);
return 0;
+ } else if (status == OK && !nullable && ptr == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return 0;
}
return JHwBlob::NewObject(env, ptr, childHandle);
@@ -945,7 +950,7 @@
{ "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
(void *)JHwParcel_native_readBuffer },
- { "readEmbeddedBuffer", "(JJ)L" PACKAGE_PATH "/HwBlob;",
+ { "readEmbeddedBuffer", "(JJZ)L" PACKAGE_PATH "/HwBlob;",
(void *)JHwParcel_native_readEmbeddedBuffer },
{ "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 66f5c4d..b3627adc 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -883,7 +883,7 @@
private void handleMobileDataAlwaysOn() {
final boolean enable = (Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1);
+ mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1) == 1);
final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
if (enable == isEnabled) {
return; // Nothing to do.
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 3c8c699..2010e64 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -181,7 +181,7 @@
}
@Override // Binder call
- public void rebootRecoveryWithCommand(String command) {
+ public void rebootRecoveryWithCommand(String command, boolean update) {
if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");
synchronized (sRequestLock) {
if (!setupOrClearBcb(true, command)) {
@@ -190,7 +190,10 @@
// Having set up the BCB, go ahead and reboot.
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- pm.reboot(PowerManager.REBOOT_RECOVERY);
+ // PowerManagerService may additionally request uncrypting the package when it's
+ // to install an update (REBOOT_RECOVERY_UPDATE).
+ pm.reboot(update ? PowerManager.REBOOT_RECOVERY_UPDATE :
+ PowerManager.REBOOT_RECOVERY);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index afc6247..a5876dd 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1586,9 +1586,6 @@
public void exit() {
// We assume that everything is reset after stopping the daemons.
interrupt();
- for (LocalSocket socket : mSockets) {
- IoUtils.closeQuietly(socket);
- }
agentDisconnect();
try {
mContext.unregisterReceiver(mBroadcastReceiver);
@@ -1601,8 +1598,26 @@
Log.v(TAG, "Waiting");
synchronized (TAG) {
Log.v(TAG, "Executing");
- execute();
- monitorDaemons();
+ try {
+ execute();
+ monitorDaemons();
+ interrupted(); // Clear interrupt flag if execute called exit.
+ } catch (InterruptedException e) {
+ } finally {
+ for (LocalSocket socket : mSockets) {
+ IoUtils.closeQuietly(socket);
+ }
+ // This sleep is necessary for racoon to successfully complete sending delete
+ // message to server.
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ for (String daemon : mDaemons) {
+ SystemService.stop(daemon);
+ }
+ }
+ agentDisconnect();
}
}
@@ -1801,18 +1816,6 @@
Log.i(TAG, "Aborting", e);
updateState(DetailedState.FAILED, e.getMessage());
exit();
- } finally {
- // Kill the daemons if they fail to stop.
- if (!initFinished) {
- for (String daemon : mDaemons) {
- SystemService.stop(daemon);
- }
- }
-
- // Do not leave an unstable state.
- if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
- agentDisconnect();
- }
}
}
@@ -1820,28 +1823,17 @@
* Monitor the daemons we started, moving to disconnected state if the
* underlying services fail.
*/
- private void monitorDaemons() {
+ private void monitorDaemons() throws InterruptedException{
if (!mNetworkInfo.isConnected()) {
return;
}
-
- try {
- while (true) {
- Thread.sleep(2000);
- for (int i = 0; i < mDaemons.length; i++) {
- if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
- return;
- }
+ while (true) {
+ Thread.sleep(2000);
+ for (int i = 0; i < mDaemons.length; i++) {
+ if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
+ return;
}
}
- } catch (InterruptedException e) {
- Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
- } finally {
- for (String daemon : mDaemons) {
- SystemService.stop(daemon);
- }
-
- agentDisconnect();
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index eb79211..927dfd5 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -26,6 +26,7 @@
import android.net.NetworkState;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
import java.util.HashMap;
@@ -72,6 +73,12 @@
mWhat = what;
}
+ @VisibleForTesting
+ public UpstreamNetworkMonitor(StateMachine tgt, int what, ConnectivityManager cm) {
+ this(null, tgt, what);
+ mCM = cm;
+ }
+
public void start() {
stop();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 45d0576..6a0aa84 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -904,8 +904,10 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ *
+ * @hide
*/
- /** {@hide} */
+ @SystemApi
public String getImei() {
return getImei(getDefaultSim());
}
@@ -917,8 +919,10 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @param slotId of which deviceID is returned
+ *
+ * @hide
*/
- /** {@hide} */
+ @SystemApi
public String getImei(int slotId) {
ITelephony telephony = getITelephony();
if (telephony == null) return null;
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
new file mode 100644
index 0000000..b2a9a49
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2017 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.connectivity.tethering;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.reset;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.IConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UpstreamNetworkMonitorTest {
+ private static final int EVENT_UNM_UPDATE = 1;
+
+ @Mock private Context mContext;
+ @Mock private IConnectivityManager mCS;
+
+ private TestConnectivityManager mCM;
+ private UpstreamNetworkMonitor mUNM;
+
+ @Before public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ reset(mContext);
+ reset(mCS);
+
+ mCM = new TestConnectivityManager(mContext, mCS);
+ mUNM = new UpstreamNetworkMonitor(null, EVENT_UNM_UPDATE, (ConnectivityManager) mCM);
+ }
+
+ @Test
+ public void testDoesNothingBeforeStarted() {
+ UpstreamNetworkMonitor unm = new UpstreamNetworkMonitor(null, null, EVENT_UNM_UPDATE);
+ assertFalse(unm.mobileNetworkRequested());
+ // Given a null Context, and therefore a null ConnectivityManager,
+ // these would cause an exception, if they actually attempted anything.
+ unm.mobileUpstreamRequiresDun(true);
+ unm.mobileUpstreamRequiresDun(false);
+ }
+
+ @Test
+ public void testDefaultNetworkIsTracked() throws Exception {
+ assertEquals(0, mCM.trackingDefault.size());
+
+ mUNM.start();
+ assertEquals(1, mCM.trackingDefault.size());
+
+ mUNM.stop();
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testListensForDunNetworks() throws Exception {
+ assertTrue(mCM.listening.isEmpty());
+
+ mUNM.start();
+ assertFalse(mCM.listening.isEmpty());
+ assertTrue(mCM.isListeningForDun());
+
+ mUNM.stop();
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testCanRequestMobileNetwork() throws Exception {
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.start();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.mobileUpstreamRequiresDun(false);
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.registerMobileNetworkRequest();
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertEquals(1, mCM.requested.size());
+ assertFalse(mCM.isDunRequested());
+
+ mUNM.stop();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertTrue(mCM.isEmpty());
+ }
+
+ @Test
+ public void testCanRequestDunNetwork() throws Exception {
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.start();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.mobileUpstreamRequiresDun(true);
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertEquals(0, mCM.requested.size());
+
+ mUNM.registerMobileNetworkRequest();
+ assertTrue(mUNM.mobileNetworkRequested());
+ assertEquals(1, mCM.requested.size());
+ assertTrue(mCM.isDunRequested());
+
+ mUNM.stop();
+ assertFalse(mUNM.mobileNetworkRequested());
+ assertTrue(mCM.isEmpty());
+ }
+
+ private static class TestConnectivityManager extends ConnectivityManager {
+ public Set<NetworkCallback> trackingDefault = new HashSet<>();
+ public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
+ public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
+
+ public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
+ super(ctx, svc);
+ }
+
+ boolean isEmpty() {
+ return trackingDefault.isEmpty() &&
+ listening.isEmpty() &&
+ requested.isEmpty();
+ }
+
+ boolean isListeningForDun() {
+ for (NetworkRequest req : listening.values()) {
+ if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean isDunRequested() {
+ for (NetworkRequest req : requested.values()) {
+ if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void requestNetwork(NetworkRequest req, NetworkCallback cb) {
+ assertFalse(requested.containsKey(cb));
+ requested.put(cb, req);
+ }
+
+ @Override
+ public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb) {
+ assertFalse(listening.containsKey(cb));
+ listening.put(cb, req);
+ }
+
+ @Override
+ public void registerDefaultNetworkCallback(NetworkCallback cb) {
+ assertFalse(trackingDefault.contains(cb));
+ trackingDefault.add(cb);
+ }
+
+ @Override
+ public void unregisterNetworkCallback(NetworkCallback cb) {
+ if (trackingDefault.contains(cb)) {
+ trackingDefault.remove(cb);
+ } else if (listening.containsKey(cb)) {
+ listening.remove(cb);
+ } else if (requested.containsKey(cb)) {
+ requested.remove(cb);
+ }
+
+ assertFalse(trackingDefault.contains(cb));
+ assertFalse(listening.containsKey(cb));
+ assertFalse(requested.containsKey(cb));
+ }
+ }
+}