summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java26
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java61
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl1
-rw-r--r--core/java/android/bluetooth/IBluetoothInputDevice.aidl8
-rw-r--r--core/java/android/net/ConnectivityManager.java30
-rwxr-xr-xcore/java/android/provider/Settings.java3
-rw-r--r--core/java/android/util/MemoryIntArray.java2
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java8
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp4
-rwxr-xr-xcore/res/res/values-mcc311-mnc480/config.xml3
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/utiltests/Android.mk5
-rw-r--r--data/etc/platform.xml1
-rw-r--r--legacy-test/Android.mk21
-rw-r--r--legacy-test/src/com/android/internal/util/Predicate.java (renamed from core/java/com/android/internal/util/Predicate.java)0
-rw-r--r--legacy-test/src/com/android/internal/util/Predicates.java (renamed from core/java/com/android/internal/util/Predicates.java)2
-rw-r--r--legacy-test/tests/com/android/internal/util/PredicatesTest.java (renamed from core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java)0
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java5
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java3
-rw-r--r--services/core/Android.mk12
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java53
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java46
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java53
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java10
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/OffloadController.java37
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java77
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java28
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java29
-rw-r--r--services/core/java/com/android/server/pm/Installer.java16
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java6
-rw-r--r--services/core/jni/Android.mk5
-rw-r--r--services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp146
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java9
-rw-r--r--telephony/java/android/telephony/MbmsStreamingManager.java115
-rw-r--r--telephony/java/android/telephony/NetworkScan.java83
-rw-r--r--telephony/java/android/telephony/NetworkScanRequest.aidl19
-rw-r--r--telephony/java/android/telephony/NetworkScanRequest.java115
-rw-r--r--telephony/java/android/telephony/RadioAccessSpecifier.aidl19
-rw-r--r--telephony/java/android/telephony/RadioAccessSpecifier.java129
-rw-r--r--telephony/java/android/telephony/RadioNetworkConstants.java169
-rw-r--r--telephony/java/android/telephony/SmsMessage.java56
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java109
-rw-r--r--telephony/java/android/telephony/TelephonyScanManager.java186
-rw-r--r--telephony/java/android/telephony/ims/ImsService.java12
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java54
-rwxr-xr-xtelephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl6
-rw-r--r--telephony/java/android/telephony/mbms/MbmsException.java13
-rw-r--r--telephony/java/android/telephony/mbms/ServiceInfo.java27
-rwxr-xr-xtelephony/java/android/telephony/mbms/StreamingService.aidl19
-rw-r--r--telephony/java/android/telephony/mbms/StreamingService.java88
-rw-r--r--telephony/java/android/telephony/mbms/StreamingServiceCallback.java26
-rwxr-xr-xtelephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl34
-rw-r--r--telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java85
-rw-r--r--telephony/java/com/android/ims/internal/IImsServiceController.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl41
-rw-r--r--telephony/java/com/android/internal/telephony/NetworkScanResult.java129
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java6
-rw-r--r--test-runner/src/android/test/AndroidTestRunner.java8
-rw-r--r--test-runner/src/android/test/ClassPathPackageInfo.java7
-rw-r--r--test-runner/src/android/test/ClassPathPackageInfoSource.java10
-rw-r--r--test-runner/src/android/test/DatabaseTestUtils.java5
-rw-r--r--test-runner/src/android/test/IsolatedContext.java7
-rw-r--r--test-runner/src/android/test/RenamingDelegatingContext.java26
-rw-r--r--test-runner/src/android/test/TestCaseUtil.java7
-rw-r--r--test-runner/src/android/test/TestRunner.java3
-rw-r--r--test-runner/src/android/test/mock/MockContentResolver.java5
-rw-r--r--test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java3
-rw-r--r--test-runner/tests/src/android/test/AndroidTestRunnerTest.java11
-rw-r--r--tests/net/java/android/net/ConnectivityManagerTest.java40
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java9
-rw-r--r--tests/net/java/com/android/server/connectivity/TetheringTest.java9
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java132
80 files changed, 2142 insertions, 408 deletions
diff --git a/Android.mk b/Android.mk
index 02caa0ad3866..2571afbf477f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -553,7 +553,6 @@ aidl_files := \
frameworks/base/telephony/java/android/telephony/mbms/FileInfo.aidl \
frameworks/base/telephony/java/android/telephony/mbms/FileServiceInfo.aidl \
frameworks/base/telephony/java/android/telephony/mbms/ServiceInfo.aidl \
- frameworks/base/telephony/java/android/telephony/mbms/StreamingService.aidl \
frameworks/base/telephony/java/android/telephony/mbms/StreamingServiceInfo.aidl \
frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
frameworks/base/telephony/java/android/telephony/SubscriptionInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index 0353a8bd112e..55dda042e19c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37531,6 +37531,7 @@ package android.telephony {
field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+ field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index eb6b7b15c8c7..5e9c7e39bfda 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40702,6 +40702,7 @@ package android.telephony {
field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+ field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
diff --git a/api/test-current.txt b/api/test-current.txt
index 8946dafee8d9..5487a9770fd1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37630,6 +37630,7 @@ package android.telephony {
field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+ field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 3135b30ebcc8..b12ff72a50c6 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.content.Context;
import android.os.Handler;
import android.os.ParcelUuid;
import android.os.RemoteException;
@@ -927,6 +926,31 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
+ * Discovers a service by UUID. This is exposed only for passing PTS tests.
+ * It should never be used by real applications. The service is not searched
+ * for characteristics and descriptors, or returned in any callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @return true, if the remote service discovery has been started
+ * @hide
+ */
+ public boolean discoverServiceByUuid(UUID uuid) {
+ if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
+ if (mService == null || mClientIf == 0) return false;
+
+ mServices.clear();
+
+ try {
+ mService.discoverServiceByUuid(mClientIf, mDevice.getAddress(), new ParcelUuid(uuid));
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Returns a list of GATT services offered by the remote device.
*
* <p>This function requires that service discovery has been completed
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 252e3d28a25e..fccdf14bb9cd 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -96,6 +96,12 @@ public final class BluetoothInputDevice implements BluetoothProfile {
public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
"android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
+ /**
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_IDLE_TIME_CHANGED =
+ "android.bluetooth.input.profile.action.IDLE_TIME_CHANGED";
/**
* Return codes for the connect and disconnect Bluez / Dbus calls.
@@ -199,6 +205,11 @@ public final class BluetoothInputDevice implements BluetoothProfile {
*/
public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_IDLE_TIME = "android.bluetooth.BluetoothInputDevice.extra.IDLE_TIME";
+
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -658,6 +669,56 @@ public final class BluetoothInputDevice implements BluetoothProfile {
if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
+
+ /**
+ * Send Get_Idle_Time command to the connected HID input device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean getIdleTime(BluetoothDevice device) {
+ if (DBG) log("getIdletime(" + device + ")");
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.getIdleTime(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Send Set_Idle_Time command to the connected HID input device.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @param idleTime Idle time to be set on HID Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
+ if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.setIdleTime(device, idleTime);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 63bd94284645..4ff597655767 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -76,6 +76,7 @@ interface IBluetoothGatt {
void clientReadPhy(in int clientIf, in String address);
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
+ void discoverServiceByUuid(in int clientIf, in String address, in ParcelUuid uuid);
void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
in int startHandle, in int endHandle, in int authReq);
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
index 1ebb9ca6eb12..5bd3f7819323 100644
--- a/core/java/android/bluetooth/IBluetoothInputDevice.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
@@ -56,4 +56,12 @@ interface IBluetoothInputDevice {
* @hide
*/
boolean sendData(in BluetoothDevice device, String report);
+ /**
+ * @hide
+ */
+ boolean getIdleTime(in BluetoothDevice device);
+ /**
+ * @hide
+ */
+ boolean setIdleTime(in BluetoothDevice device, byte idleTime);
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index efa195983f94..234bef7483aa 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -39,11 +39,11 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.telephony.ITelephony;
@@ -2701,6 +2701,28 @@ public class ConnectivityManager {
}
}
+ /**
+ * Constant error codes used by ConnectivityService to communicate about failures and errors
+ * across a Binder boundary.
+ * @hide
+ */
+ public interface Errors {
+ static int TOO_MANY_REQUESTS = 1;
+ }
+
+ /** @hide */
+ public static class TooManyRequestsException extends RuntimeException {}
+
+ private static RuntimeException convertServiceException(ServiceSpecificException e) {
+ switch (e.errorCode) {
+ case Errors.TOO_MANY_REQUESTS:
+ return new TooManyRequestsException();
+ default:
+ Log.w(TAG, "Unknown service error code " + e.errorCode);
+ return new RuntimeException(e);
+ }
+ }
+
private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER;
/** @hide */
public static final int CALLBACK_PRECHECK = BASE + 1;
@@ -2892,6 +2914,8 @@ public class ConnectivityManager {
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw convertServiceException(e);
}
return request;
}
@@ -3177,6 +3201,8 @@ public class ConnectivityManager {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw convertServiceException(e);
}
}
@@ -3279,6 +3305,8 @@ public class ConnectivityManager {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw convertServiceException(e);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 35a3c0c0d8c1..2c1796370558 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9114,7 +9114,8 @@ public final class Settings {
CALL_AUTO_RETRY,
DOCK_AUDIO_MEDIA_ENABLED,
ENCODED_SURROUND_OUTPUT,
- LOW_POWER_MODE_TRIGGER_LEVEL
+ LOW_POWER_MODE_TRIGGER_LEVEL,
+ BLUETOOTH_ON
};
// Populated lazily, guarded by class object:
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 0d62054825e8..b72e783c2832 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -53,7 +53,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
private final boolean mIsOwner;
private final long mMemoryAddr;
- private int mFd;
+ private int mFd = -1;
/**
* Creates a new instance.
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 527582be3c02..91429a609288 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -717,14 +717,6 @@ class ZygoteConnection {
public static void applyInvokeWithSystemProperty(Arguments args) {
if (args.invokeWith == null && args.niceName != null) {
String property = "wrap." + args.niceName;
- if (property.length() > 31) {
- // Properties with a trailing "." are illegal.
- if (property.charAt(30) != '.') {
- property = property.substring(0, 31);
- } else {
- property = property.substring(0, 30);
- }
- }
args.invokeWith = SystemProperties.get(property);
if (args.invokeWith != null && args.invokeWith.length() == 0) {
args.invokeWith = null;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 6000fb56299d..d73e7dd50140 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <grp.h>
#include <inttypes.h>
+#include <malloc.h>
#include <mntent.h>
#include <paths.h>
#include <signal.h>
@@ -519,6 +520,9 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
// The child process.
gMallocLeakZygoteChild = 1;
+ // Set the jemalloc decay time to 1.
+ mallopt(M_DECAY_TIME, 1);
+
// Clean up any descriptors which must be closed immediately
DetachDescriptors(env, fdsToClose);
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 10166a545092..0cafed68efed 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -48,9 +48,6 @@
provisioning, availability etc -->
<bool name="config_carrier_vt_available">true</bool>
- <!-- Flag specifying whether VoLTE availability is based on provisioning -->
- <bool name="config_carrier_volte_provisioned">true</bool>
-
<bool name="config_auto_attach_data_on_creation">false</bool>
<!--Thresholds for LTE dbm in status bar-->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 22a1a3663342..37d03ad0ec1d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2328,9 +2328,6 @@
provisioning, availability etc -->
<bool name="config_carrier_volte_available">false</bool>
- <!-- Flag specifying whether VoLTE availability is based on provisioning -->
- <bool name="config_carrier_volte_provisioned">false</bool>
-
<!-- Flag specifying whether VoLTE TTY is supported -->
<bool name="config_carrier_volte_tty_supported">true</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ea89cc15c0b0..f3ce7190ca7f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2262,7 +2262,6 @@
<java-symbol type="bool" name="imsServiceAllowTurnOff" />
<java-symbol type="bool" name="config_device_volte_available" />
<java-symbol type="bool" name="config_carrier_volte_available" />
- <java-symbol type="bool" name="config_carrier_volte_provisioned" />
<java-symbol type="bool" name="config_carrier_volte_tty_supported" />
<java-symbol type="bool" name="config_device_vt_available" />
<java-symbol type="bool" name="config_device_respects_hold_carrier_config" />
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index faf04b119e7b..e69a2cc53f20 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -17,7 +17,8 @@ LOCAL_JNI_SHARED_LIBRARIES := libmemoryintarraytest libcutils libc++
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
frameworks-base-testutils \
- mockito-target
+ mockito-target \
+ legacy-android-tests
LOCAL_JAVA_LIBRARIES := android.test.runner
@@ -27,4 +28,4 @@ LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index e46f1666282e..ae0c8a02b48b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -45,6 +45,7 @@
<permission name="android.permission.BLUETOOTH_STACK" >
<group gid="bluetooth" />
<group gid="wakelock" />
+ <group gid="uhid" />
</permission>
<permission name="android.permission.NET_TUNNELING" >
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index 0835cadbe698..8efda2ad0c20 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -20,9 +20,11 @@ LOCAL_PATH:= $(call my-dir)
# =============================
# This contains the junit.framework and android.test classes that were in
# Android API level 25 excluding those from android.test.runner.
+# Also contains the com.android.internal.util.Predicate[s] classes.
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
LOCAL_MODULE := legacy-test
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
@@ -30,20 +32,35 @@ LOCAL_JAVA_LIBRARIES := core-oj core-libart framework
include $(BUILD_JAVA_LIBRARY)
# Build the legacy-android-test library
-# =============================
+# =====================================
# This contains the android.test classes that were in Android API level 25,
# including those from android.test.runner.
+# Also contains the com.android.internal.util.Predicate[s] classes.
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(call all-java-files-under, src/android) \
- $(call all-java-files-under, ../test-runner/src/android)
+ $(call all-java-files-under, ../test-runner/src/android) \
+ $(call all-java-files-under, src/com)
LOCAL_MODULE := legacy-android-test
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-oj core-libart framework junit
include $(BUILD_STATIC_JAVA_LIBRARY)
+# Build the legacy-android-tests library
+# ======================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, tests)
+LOCAL_MODULE := legacy-android-tests
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj core-libart framework junit
+LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
ifeq ($(HOST_OS),linux)
# Build the legacy-performance-test-hostdex library
# =================================================
diff --git a/core/java/com/android/internal/util/Predicate.java b/legacy-test/src/com/android/internal/util/Predicate.java
index 1b5eaff67b87..1b5eaff67b87 100644
--- a/core/java/com/android/internal/util/Predicate.java
+++ b/legacy-test/src/com/android/internal/util/Predicate.java
diff --git a/core/java/com/android/internal/util/Predicates.java b/legacy-test/src/com/android/internal/util/Predicates.java
index c006564f129a..fe1ff1529138 100644
--- a/core/java/com/android/internal/util/Predicates.java
+++ b/legacy-test/src/com/android/internal/util/Predicates.java
@@ -21,6 +21,8 @@ import java.util.Arrays;
/**
* Predicates contains static methods for creating the standard set of
* {@code Predicate} objects.
+ *
+ * @hide
*/
public class Predicates {
diff --git a/core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java b/legacy-test/tests/com/android/internal/util/PredicatesTest.java
index c46ff051dd33..c46ff051dd33 100644
--- a/core/tests/utiltests/src/com/android/internal/util/PredicatesTest.java
+++ b/legacy-test/tests/com/android/internal/util/PredicatesTest.java
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 6394c64b74cc..34465e92a1ef 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -122,6 +122,11 @@ public class CaptivePortalLoginActivity extends Activity {
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+ webSettings.setUseWideViewPort(true);
+ webSettings.setLoadWithOverviewMode(true);
+ webSettings.setSupportZoom(true);
+ webSettings.setBuiltInZoomControls(true);
+ webSettings.setDisplayZoomControls(false);
mWebViewClient = new MyWebViewClient();
myWebView.setWebViewClient(mWebViewClient);
myWebView.setWebChromeClient(new MyWebChromeClient());
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index ec4c00ed6117..61b3122f5f7d 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -96,6 +96,10 @@ public class CaptivePortalLoginActivity extends Activity {
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+ webSettings.setUseWideViewPort(true);
+ webSettings.setLoadWithOverviewMode(true);
+ webSettings.setSupportZoom(true);
+ webSettings.setBuiltInZoomControls(true);
mWebViewClient = new MyWebViewClient();
mWebView.setWebViewClient(mWebViewClient);
mWebView.setWebChromeClient(new MyWebChromeClient());
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index bf48e5de1da3..75ae835b81cf 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -62,11 +62,12 @@ public class SettingsHelper {
*/
private static final ArraySet<String> sBroadcastOnRestore;
static {
- sBroadcastOnRestore = new ArraySet<String>(4);
+ sBroadcastOnRestore = new ArraySet<String>(5);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_INPUT_METHODS);
+ sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON);
}
private interface SettingsLookup {
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 689c97976cc0..f9b0d2f05c94 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -18,10 +18,18 @@ LOCAL_SRC_FILES += \
LOCAL_AIDL_INCLUDES += \
system/netd/server/binder
-LOCAL_JAVA_LIBRARIES := services.net
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_shared2 tzdata_update2
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_JAVA_LIBRARIES := \
+ services.net \
+ android.hidl.manager-V1.0-java \
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ tzdata_shared2 \
+ tzdata_update2 \
+ android.hidl.base-V1.0-java-static \
+ android.hardware.tetheroffload.control-V1.0-java-static \
+
ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_JACK_ENABLED := incremental
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 1262d88be8e1..ba1befdf8175 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -90,6 +90,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String REASON_SYSTEM_BOOT = "system boot";
private static final String REASON_UNEXPECTED = "unexpected crash";
private static final String REASON_USER_SWITCH = "user switch";
+ private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
//Maximum msec to wait for service restart
@@ -118,6 +119,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int MESSAGE_USER_UNLOCKED = 301;
private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
+ private static final int MESSAGE_RESTORE_USER_SETTING = 500;
+
+ private static final int RESTORE_SETTING_TO_ON = 1;
+ private static final int RESTORE_SETTING_TO_OFF = 0;
private static final int MAX_SAVE_RETRIES = 3;
private static final int MAX_ERROR_RESTART_RETRIES = 6;
@@ -315,6 +320,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
} else {
if (DBG) Slog.e(TAG, "No Bluetooth Adapter address parameter found");
}
+ } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+ final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Settings.Global.BLUETOOTH_ON.equals(name)) {
+ // The Bluetooth On state may be changed during system restore.
+ final String prevValue = intent.getStringExtra(
+ Intent.EXTRA_SETTING_PREVIOUS_VALUE);
+ final String newValue = intent.getStringExtra(
+ Intent.EXTRA_SETTING_NEW_VALUE);
+
+ if (DBG) Slog.d(TAG, "ACTION_SETTING_RESTORED with BLUETOOTH_ON, prevValue=" +
+ prevValue + ", newValue=" + newValue);
+
+ if ((newValue != null) && (prevValue != null) && !prevValue.equals(newValue)) {
+ Message msg = mHandler.obtainMessage(MESSAGE_RESTORE_USER_SETTING,
+ newValue.equals("0") ?
+ RESTORE_SETTING_TO_OFF :
+ RESTORE_SETTING_TO_ON, 0);
+ mHandler.sendMessage(msg);
+ }
+ }
}
}
};
@@ -348,12 +373,14 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
registerForBleScanModeChange();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
- IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(mReceiver, filter);
- filter = new IntentFilter(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+ filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
+ filter.addAction(Intent.ACTION_SETTING_RESTORED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
+
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
if (DBG) Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
@@ -1424,6 +1451,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
break;
+ case MESSAGE_RESTORE_USER_SETTING:
+ try {
+ if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
+ if (DBG) Slog.d(TAG, "Restore Bluetooth state to disabled");
+ disable(REASON_RESTORE_USER_SETTING, true);
+ } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
+ if (DBG) Slog.d(TAG, "Restore Bluetooth state to enabled");
+ enable(REASON_RESTORE_USER_SETTING);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG,"Unable to change Bluetooth On setting", e);
+ }
+ break;
+
case MESSAGE_REGISTER_ADAPTER:
{
IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
@@ -1658,7 +1699,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mHandler.removeMessages(MESSAGE_USER_SWITCHED);
/* disable and enable BT when detect a user switch */
- if (mEnable && mBluetooth != null) {
+ if (mBluetooth != null && isEnabled()) {
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) {
@@ -1727,6 +1768,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mState = BluetoothAdapter.STATE_OFF;
// enable
addActiveLog(REASON_USER_SWITCH, true);
+ // mEnable flag could have been reset on disableBLE. Reenable it.
+ mEnable = true;
handleEnable(mQuietEnable);
} else if (mBinding || mBluetooth != null) {
Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 88bc54d26755..47026d6815f4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -98,6 +98,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
@@ -144,6 +145,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy
import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.Tethering;
+import com.android.server.connectivity.tethering.TetheringDependencies;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker;
@@ -486,7 +488,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
new ArrayDeque<ValidationLog>(MAX_VALIDATION_LOGS);
private void addValidationLogs(ReadOnlyLocalLog log, Network network, String networkExtraInfo) {
- synchronized(mValidationLogs) {
+ synchronized (mValidationLogs) {
while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
mValidationLogs.removeLast();
}
@@ -801,8 +803,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mTestMode = mSystemProperties.get("cm.test.mode").equals("true")
&& mSystemProperties.get("ro.build.type").equals("eng");
- mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
- IoThread.get().getLooper(), new MockableSystemProperties());
+ mTethering = makeTethering();
mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
@@ -852,6 +853,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
mMultinetworkPolicyTracker.start();
}
+ private Tethering makeTethering() {
+ // TODO: Move other elements into @Overridden getters.
+ final TetheringDependencies deps = new TetheringDependencies();
+ return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
+ IoThread.get().getLooper(), new MockableSystemProperties(),
+ deps);
+ }
+
private NetworkRequest createInternetRequestForTransport(
int transportType, NetworkRequest.Type type) {
NetworkCapabilities netCap = new NetworkCapabilities();
@@ -1670,7 +1679,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void sendStickyBroadcast(Intent intent) {
- synchronized(this) {
+ synchronized (this) {
if (!mSystemReady) {
mInitialBroadcast = new Intent(intent);
}
@@ -1711,7 +1720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
void systemReady() {
loadGlobalProxy();
- synchronized(this) {
+ synchronized (this) {
mSystemReady = true;
if (mInitialBroadcast != null) {
mContext.sendStickyBroadcastAsUser(mInitialBroadcast, UserHandle.ALL);
@@ -3493,7 +3502,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
enforceCrossUserPermission(userId);
throwIfLockdownEnabled();
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn vpn = mVpns.get(userId);
if (vpn != null) {
return vpn.prepare(oldPackage, newPackage);
@@ -3520,7 +3529,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) {
enforceCrossUserPermission(userId);
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn vpn = mVpns.get(userId);
if (vpn != null) {
vpn.setPackageAuthorization(packageName, authorized);
@@ -3539,7 +3548,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
public ParcelFileDescriptor establishVpn(VpnConfig config) {
throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid());
- synchronized(mVpns) {
+ synchronized (mVpns) {
return mVpns.get(user).establish(config);
}
}
@@ -3556,7 +3565,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
throw new IllegalStateException("Missing active network connection");
}
int user = UserHandle.getUserId(Binder.getCallingUid());
- synchronized(mVpns) {
+ synchronized (mVpns) {
mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
}
}
@@ -3570,7 +3579,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
public LegacyVpnInfo getLegacyVpnInfo(int userId) {
enforceCrossUserPermission(userId);
- synchronized(mVpns) {
+ synchronized (mVpns) {
return mVpns.get(userId).getLegacyVpnInfo();
}
}
@@ -3586,7 +3595,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return new VpnInfo[0];
}
- synchronized(mVpns) {
+ synchronized (mVpns) {
List<VpnInfo> infoList = new ArrayList<>();
for (int i = 0; i < mVpns.size(); i++) {
VpnInfo info = createVpnInfo(mVpns.valueAt(i));
@@ -3634,7 +3643,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public VpnConfig getVpnConfig(int userId) {
enforceCrossUserPermission(userId);
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn vpn = mVpns.get(userId);
if (vpn != null) {
return vpn.getVpnConfig();
@@ -3668,7 +3677,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return true;
}
int user = UserHandle.getUserId(Binder.getCallingUid());
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn vpn = mVpns.get(user);
if (vpn == null) {
Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
@@ -3903,7 +3912,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void onUserStart(int userId) {
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn userVpn = mVpns.get(userId);
if (userVpn != null) {
loge("Starting user already has a VPN");
@@ -3918,7 +3927,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void onUserStop(int userId) {
- synchronized(mVpns) {
+ synchronized (mVpns) {
Vpn userVpn = mVpns.get(userId);
if (userVpn == null) {
loge("Stopped user has no VPN");
@@ -3930,7 +3939,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void onUserAdded(int userId) {
- synchronized(mVpns) {
+ synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
@@ -3940,7 +3949,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void onUserRemoved(int userId) {
- synchronized(mVpns) {
+ synchronized (mVpns) {
final int vpnsSize = mVpns.size();
for (int i = 0; i < vpnsSize; i++) {
Vpn vpn = mVpns.valueAt(i);
@@ -4064,7 +4073,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized (mUidToNetworkRequestCount) {
int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
- throw new IllegalArgumentException("Too many NetworkRequests filed");
+ throw new ServiceSpecificException(
+ ConnectivityManager.Errors.TOO_MANY_REQUESTS);
}
mUidToNetworkRequestCount.put(mUid, networkRequests);
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index b64c65dd5827..9f7437ec2a3a 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -26,6 +26,8 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -73,6 +75,7 @@ public class NetworkTimeUpdateService extends Binder {
private long mNitzTimeSetTime = NOT_SET;
// TODO: Have a way to look up the timezone we are in
private long mNitzZoneSetTime = NOT_SET;
+ private Network mDefaultNetwork = null;
private Context mContext;
private TrustedTime mTime;
@@ -82,6 +85,8 @@ public class NetworkTimeUpdateService extends Binder {
private AlarmManager mAlarmManager;
private PendingIntent mPendingPollIntent;
private SettingsObserver mSettingsObserver;
+ private ConnectivityManager mCM;
+ private NetworkTimeUpdateCallback mNetworkTimeUpdateCallback;
// The last time that we successfully fetched the NTP time.
private long mLastNtpFetchTime = NOT_SET;
private final PowerManager.WakeLock mWakeLock;
@@ -103,6 +108,7 @@ public class NetworkTimeUpdateService extends Binder {
mContext = context;
mTime = NtpTrustedTime.getInstance(context);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Intent pollIntent = new Intent(ACTION_POLL, null);
mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
@@ -123,13 +129,12 @@ public class NetworkTimeUpdateService extends Binder {
public void systemRunning() {
registerForTelephonyIntents();
registerForAlarms();
- registerForConnectivityIntents();
HandlerThread thread = new HandlerThread(TAG);
thread.start();
mHandler = new MyHandler(thread.getLooper());
- // Check the network time on the new thread
- mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget();
+ mNetworkTimeUpdateCallback = new NetworkTimeUpdateCallback();
+ mCM.registerDefaultNetworkCallback(mNetworkTimeUpdateCallback, mHandler);
mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED);
mSettingsObserver.observe(mContext);
@@ -152,15 +157,10 @@ public class NetworkTimeUpdateService extends Binder {
}, new IntentFilter(ACTION_POLL));
}
- private void registerForConnectivityIntents() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(mConnectivityReceiver, intentFilter);
- }
-
private void onPollNetworkTime(int event) {
- // If Automatic time is not set, don't bother.
- if (!isAutomaticTimeRequested()) return;
+ // If Automatic time is not set, don't bother. Similarly, if we don't
+ // have any default network, don't bother.
+ if (!isAutomaticTimeRequested() || mDefaultNetwork == null) return;
mWakeLock.acquire();
try {
onPollNetworkTimeUnderWakeLock(event);
@@ -262,22 +262,6 @@ public class NetworkTimeUpdateService extends Binder {
}
};
- /** Receiver for ConnectivityManager events */
- private BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
- if (DBG) Log.d(TAG, "Received CONNECTIVITY_ACTION ");
- // Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
- Message message = mHandler.obtainMessage(EVENT_NETWORK_CHANGED);
- // Send with a short delay to make sure the network is ready for use
- mHandler.sendMessageDelayed(message, NETWORK_CHANGE_EVENT_DELAY_MS);
- }
- }
- };
-
/** Handler to do the network accesses on */
private class MyHandler extends Handler {
@@ -297,6 +281,21 @@ public class NetworkTimeUpdateService extends Binder {
}
}
+ private class NetworkTimeUpdateCallback extends NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ Log.d(TAG, String.format("New default network %s; checking time.", network));
+ mDefaultNetwork = network;
+ // Running on mHandler so invoke directly.
+ onPollNetworkTime(EVENT_NETWORK_CHANGED);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ if (network.equals(mDefaultNetwork)) mDefaultNetwork = null;
+ }
+ }
+
/** Observer to watch for changes to the AUTO_TIME setting */
private static class SettingsObserver extends ContentObserver {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 4dae36411844..9c551dda7c71 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -81,6 +81,7 @@ import com.android.server.connectivity.tethering.OffloadController;
import com.android.server.connectivity.tethering.SimChangeListener;
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
import com.android.server.connectivity.tethering.TetheringConfiguration;
+import com.android.server.connectivity.tethering.TetheringDependencies;
import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
import com.android.server.net.BaseNetworkObserver;
@@ -178,7 +179,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
public Tethering(Context context, INetworkManagementService nmService,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
- Looper looper, MockableSystemProperties systemProperties) {
+ Looper looper, MockableSystemProperties systemProperties,
+ TetheringDependencies deps) {
mLocalLog.log("CONSTRUCTED");
mContext = context;
mNMService = nmService;
@@ -194,7 +196,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
mTetherMasterSM.start();
- mOffloadController = new OffloadController(mTetherMasterSM.getHandler());
+ mOffloadController = new OffloadController(mTetherMasterSM.getHandler(),
+ deps.getOffloadHardwareInterface());
mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new HashSet<>();
@@ -1474,7 +1477,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
handleInterfaceServingStateInactive(who);
if (mNotifyList.isEmpty()) {
- // transitions appropriately
+ // This transitions us out of TetherModeAliveState,
+ // either to InitialState or an error state.
turnOffMasterTetherSettings();
break;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 220e7514facc..6c93730974d4 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -18,10 +18,12 @@ package com.android.server.connectivity.tethering;
import android.net.LinkProperties;
import android.os.Handler;
+import android.os.RemoteException;
import android.util.Log;
/**
- * A wrapper around hardware offload interface.
+ * A class to encapsulate the business logic of programming the tethering
+ * hardware offload interface.
*
* @hide
*/
@@ -29,25 +31,48 @@ public class OffloadController {
private static final String TAG = OffloadController.class.getSimpleName();
private final Handler mHandler;
+ private final OffloadHardwareInterface mHwInterface;
+ private boolean mConfigInitialized;
+ private boolean mControlInitialized;
private LinkProperties mUpstreamLinkProperties;
- public OffloadController(Handler h) {
+ public OffloadController(Handler h, OffloadHardwareInterface hwi) {
mHandler = h;
+ mHwInterface = hwi;
}
public void start() {
- // TODO: initOffload() and configure callbacks to be handled on our
- // preferred Handler.
- Log.d(TAG, "tethering offload not supported");
+ if (started()) return;
+
+ if (!mConfigInitialized) {
+ mConfigInitialized = mHwInterface.initOffloadConfig();
+ if (!mConfigInitialized) {
+ Log.d(TAG, "tethering offload config not supported");
+ return;
+ }
+ }
+
+ // TODO: Create and register ITetheringOffloadCallback.
+ mControlInitialized = mHwInterface.initOffloadControl();
}
public void stop() {
- // TODO: stopOffload().
mUpstreamLinkProperties = null;
+ mHwInterface.stopOffloadControl();
+ mControlInitialized = false;
+ mConfigInitialized = false;
}
public void setUpstreamLinkProperties(LinkProperties lp) {
+ if (!started()) return;
+
// TODO: setUpstreamParameters().
mUpstreamLinkProperties = lp;
}
+
+ // TODO: public void addDownStream(...)
+
+ private boolean started() {
+ return mConfigInitialized && mControlInitialized;
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
new file mode 100644
index 000000000000..87fc491b0bdd
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.hardware.tetheroffload.control.V1_0.IOffloadControl;
+import android.hardware.tetheroffload.control.V1_0.IOffloadControl.stopOffloadCallback;
+import android.os.RemoteException;
+import android.util.Log;
+
+
+/**
+ * Capture tethering dependencies, for injection.
+ *
+ * @hide
+ */
+public class OffloadHardwareInterface {
+ private static final String TAG = OffloadHardwareInterface.class.getSimpleName();
+
+ private static native boolean configOffload();
+
+ private IOffloadControl mOffloadControl;
+
+ public OffloadHardwareInterface() {}
+
+ public boolean initOffloadConfig() {
+ return configOffload();
+ }
+
+ // TODO: Extend this to take a TetheringControlCallback for registration.
+ public boolean initOffloadControl() {
+ if (mOffloadControl == null) {
+ try {
+ mOffloadControl = IOffloadControl.getService();
+ } catch (RemoteException e) {
+ Log.d(TAG, "tethering offload control not supported: " + e);
+ return false;
+ }
+ }
+
+ // TODO: call mOffloadControl.initOffload(...callback...);
+
+ return true;
+ }
+
+ public void stopOffloadControl() {
+ if (mOffloadControl == null) return;
+
+ try {
+ final stopOffloadCallback cb = new stopOffloadCallback() {
+ @Override
+ public void onValues(boolean success, String errMsg) {
+ if (success) return;
+
+ Log.e(TAG, "stopOffload failed: " + errMsg);
+ }
+ };
+ mOffloadControl.stopOffload(cb);
+ } catch (RemoteException e) {
+ Log.d(TAG, "failed to stopOffload: " + e);
+ }
+ mOffloadControl = null;
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index d38beb375fa1..44c61f0160e7 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity.tethering;
+import static android.content.Context.TELEPHONY_SERVICE;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -47,9 +48,9 @@ import java.util.StringJoiner;
public class TetheringConfiguration {
private static final String TAG = TetheringConfiguration.class.getSimpleName();
- private static final int DUN_NOT_REQUIRED = 0;
- private static final int DUN_REQUIRED = 1;
- private static final int DUN_UNSPECIFIED = 2;
+ public static final int DUN_NOT_REQUIRED = 0;
+ public static final int DUN_REQUIRED = 1;
+ public static final int DUN_UNSPECIFIED = 2;
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
@@ -81,8 +82,9 @@ public class TetheringConfiguration {
tetherableBluetoothRegexs = ctx.getResources().getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs);
- isDunRequired = checkDunRequired(ctx);
- preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, isDunRequired);
+ final int dunCheck = checkDunRequired(ctx);
+ preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, dunCheck);
+ isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
dhcpRanges = getDhcpRanges(ctx);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
@@ -138,14 +140,12 @@ public class TetheringConfiguration {
pw.println();
}
- private static boolean checkDunRequired(Context ctx) {
- final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
- final int secureSetting =
- (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
- return (secureSetting == DUN_REQUIRED);
+ private static int checkDunRequired(Context ctx) {
+ final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
+ return (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
}
- private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, boolean requiresDun) {
+ private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, int dunCheck) {
final int ifaceTypes[] = ctx.getResources().getIntArray(
com.android.internal.R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
@@ -153,10 +153,10 @@ public class TetheringConfiguration {
switch (i) {
case TYPE_MOBILE:
case TYPE_MOBILE_HIPRI:
- if (requiresDun) continue;
+ if (dunCheck == DUN_REQUIRED) continue;
break;
case TYPE_MOBILE_DUN:
- if (!requiresDun) continue;
+ if (dunCheck == DUN_NOT_REQUIRED) continue;
break;
}
upstreamIfaceTypes.add(i);
@@ -166,7 +166,7 @@ public class TetheringConfiguration {
// of the value of |requiresDun|, cell data of one form or another is
// *always* an upstream, regardless of the upstream interface types
// specified by configuration resources.
- if (requiresDun) {
+ if (dunCheck == DUN_REQUIRED) {
if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
new file mode 100644
index 000000000000..be2cf080b330
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringDependencies.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+
+/**
+ * Capture tethering dependencies, for injection.
+ *
+ * @hide
+ */
+public class TetheringDependencies {
+ public OffloadHardwareInterface getOffloadHardwareInterface() {
+ return new OffloadHardwareInterface();
+ }
+}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 42a0bad302bf..f69fe64c9e49 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -42,22 +42,20 @@ public class Installer extends SystemService {
* **************************************************************************/
/** Application should be visible to everyone */
public static final int DEXOPT_PUBLIC = 1 << 1;
- /** Application wants to run in VM safe mode */
- public static final int DEXOPT_SAFEMODE = 1 << 2;
/** Application wants to allow debugging of its code */
- public static final int DEXOPT_DEBUGGABLE = 1 << 3;
+ public static final int DEXOPT_DEBUGGABLE = 1 << 2;
/** The system boot has finished */
- public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
+ public static final int DEXOPT_BOOTCOMPLETE = 1 << 3;
/** Hint that the dexopt type is profile-guided. */
- public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
+ public static final int DEXOPT_PROFILE_GUIDED = 1 << 4;
/** The compilation is for a secondary dex file. */
- public static final int DEXOPT_SECONDARY_DEX = 1 << 6;
+ public static final int DEXOPT_SECONDARY_DEX = 1 << 5;
/** Ignore the result of dexoptNeeded and force compilation. */
- public static final int DEXOPT_FORCE = 1 << 7;
+ public static final int DEXOPT_FORCE = 1 << 6;
/** Indicates that the dex file passed to dexopt in on CE storage. */
- public static final int DEXOPT_STORAGE_CE = 1 << 8;
+ public static final int DEXOPT_STORAGE_CE = 1 << 7;
/** Indicates that the dex file passed to dexopt in on DE storage. */
- public static final int DEXOPT_STORAGE_DE = 1 << 9;
+ public static final int DEXOPT_STORAGE_DE = 1 << 8;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index ddb36399b8b3..126ad26b909c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -44,7 +44,6 @@ import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
import static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED;
import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
-import static com.android.server.pm.Installer.DEXOPT_SAFEMODE;
import static com.android.server.pm.Installer.DEXOPT_SECONDARY_DEX;
import static com.android.server.pm.Installer.DEXOPT_FORCE;
import static com.android.server.pm.Installer.DEXOPT_STORAGE_CE;
@@ -381,7 +380,6 @@ public class PackageDexOptimizer {
private int getDexFlags(ApplicationInfo info, String compilerFilter) {
int flags = info.flags;
- boolean vmSafeMode = (flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
boolean debuggable = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
// Profile guide compiled oat files should not be public.
boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter);
@@ -389,7 +387,6 @@ public class PackageDexOptimizer {
int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
int dexFlags =
(isPublic ? DEXOPT_PUBLIC : 0)
- | (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
| profileFlag
| DEXOPT_BOOTCOMPLETE;
@@ -508,9 +505,6 @@ public class PackageDexOptimizer {
if ((flags & DEXOPT_PUBLIC) == DEXOPT_PUBLIC) {
flagsList.add("public");
}
- if ((flags & DEXOPT_SAFEMODE) == DEXOPT_SAFEMODE) {
- flagsList.add("safemode");
- }
if ((flags & DEXOPT_SECONDARY_DEX) == DEXOPT_SECONDARY_DEX) {
flagsList.add("secondary");
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 0dbfa5674b5d..10ef1be5703a 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
$(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
+ $(LOCAL_REL_DIR)/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp \
$(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
$(LOCAL_REL_DIR)/com_android_server_HardwarePropertiesManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
@@ -58,6 +59,9 @@ LOCAL_SHARED_LIBRARIES += \
liblog \
libhardware \
libhardware_legacy \
+ libhidlbase \
+ libhidltransport \
+ libhwbinder \
libkeystore_binder \
libnativehelper \
libutils \
@@ -73,4 +77,5 @@ LOCAL_SHARED_LIBRARIES += \
libEGL \
libGLESv2 \
libnetutils \
+ android.hardware.tetheroffload.config@1.0 \
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
new file mode 100644
index 000000000000..241ccf6ed166
--- /dev/null
+++ b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <error.h>
+#include <hidl/HidlSupport.h>
+#include <jni.h>
+#include <JNIHelp.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+
+#define LOG_TAG "OffloadHardwareInterface"
+#include <utils/Log.h>
+
+namespace android {
+
+using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::tetheroffload::config::V1_0::IOffloadConfig;
+
+namespace {
+
+inline const sockaddr * asSockaddr(const sockaddr_nl *nladdr) {
+ return reinterpret_cast<const sockaddr *>(nladdr);
+}
+
+int conntrackSocket(unsigned groups) {
+ base::unique_fd s(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_NETFILTER));
+ if (s.get() < 0) return -errno;
+
+ const struct sockaddr_nl bind_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (bind(s.get(), asSockaddr(&bind_addr), sizeof(bind_addr)) != 0) {
+ return -errno;
+ }
+
+ const struct sockaddr_nl kernel_addr = {
+ .nl_family = AF_NETLINK,
+ .nl_pad = 0,
+ .nl_pid = 0,
+ .nl_groups = groups,
+ };
+ if (connect(s.get(), asSockaddr(&kernel_addr), sizeof(kernel_addr)) != 0) {
+ return -errno;
+ }
+
+ return s.release();
+}
+
+// Return a hidl_handle that owns the file descriptor owned by fd, and will
+// auto-close it (otherwise there would be double-close problems).
+//
+// Rely upon the compiler to eliminate the constexprs used for clarity.
+hidl_handle&& handleFromFileDescriptor(base::unique_fd fd) {
+ hidl_handle h;
+
+ NATIVE_HANDLE_DECLARE_STORAGE(storage, 0, 0);
+ static constexpr int kNumFds = 1;
+ static constexpr int kNumInts = 0;
+ native_handle_t *nh = native_handle_init(storage, kNumFds, kNumInts);
+ nh->data[0] = fd.release();
+
+ static constexpr bool kTakeOwnership = true;
+ h.setTo(nh, kTakeOwnership);
+
+ return std::move(h);
+}
+
+} // namespace
+
+static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_configOffload(
+ JNIEnv* /* env */) {
+ sp<IOffloadConfig> configInterface = IOffloadConfig::getService();
+ if (configInterface.get() == nullptr) {
+ ALOGD("Could not find IOffloadConfig service.");
+ return false;
+ }
+
+ // Per the IConfigOffload definition:
+ //
+ // fd1 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY).
+ //
+ // fd2 A file descriptor bound to the following netlink groups
+ // (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY).
+ base::unique_fd
+ fd1(conntrackSocket(NFNLGRP_CONNTRACK_NEW | NFNLGRP_CONNTRACK_DESTROY)),
+ fd2(conntrackSocket(NFNLGRP_CONNTRACK_UPDATE | NFNLGRP_CONNTRACK_DESTROY));
+ if (fd1.get() < 0 || fd2.get() < 0) {
+ ALOGE("Unable to create conntrack handles: %d/%s", errno, strerror(errno));
+ return false;
+ }
+
+ hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
+ h2(handleFromFileDescriptor(std::move(fd2)));
+
+ bool rval;
+ hidl_string msg;
+ configInterface->setHandles(h1, h2,
+ [&rval, &msg](bool success, const hidl_string& errMsg) {
+ rval = success;
+ msg = errMsg;
+ });
+ if (!rval) {
+ ALOGE("IOffloadConfig::setHandles() error: %s", msg.c_str());
+ }
+
+ return rval;
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "configOffload", "()Z",
+ (void*) android_server_connectivity_tethering_OffloadHardwareInterface_configOffload },
+};
+
+int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv* env) {
+ return jniRegisterNativeMethods(env,
+ "com/android/server/connectivity/tethering/OffloadHardwareInterface",
+ gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index d3341e517eb5..5d7291a9ddb3 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -40,6 +40,7 @@ int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_location_GnssLocationProvider(JNIEnv* env);
int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
+int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
int register_android_server_tv_TvUinputBridge(JNIEnv* env);
int register_android_server_tv_TvInputHal(JNIEnv* env);
@@ -78,6 +79,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_location_GnssLocationProvider(env);
register_android_server_location_FlpHardwareProvider(env);
register_android_server_connectivity_Vpn(env);
+ register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
register_android_server_AssetAtlasService(env);
register_android_server_ConsumerIrService(env);
register_android_server_BatteryStatsService(env);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b9d22e84a88b..24cd3c78ead7 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -682,7 +682,7 @@ public class UsbDeviceManager {
}
// send broadcast intent only if the USB state has changed
- if (!isUsbStateChanged(intent)) {
+ if (!isUsbStateChanged(intent) && !configChanged) {
if (DEBUG) {
Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e1239d08b57f..7d22a2c5f511 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -57,6 +57,13 @@ public class CarrierConfigManager {
// system image, that can be added in packages/apps/CarrierConfig.
/**
+ * This flag specifies whether VoLTE availability is based on provisioning. By default this is
+ * false.
+ */
+ public static final String
+ KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+
+ /**
* Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
* events from the Sim.
* If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
@@ -1376,6 +1383,8 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
+
+ sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
index fc406ee54ce8..251d5bb561d9 100644
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ b/telephony/java/android/telephony/MbmsStreamingManager.java
@@ -22,13 +22,12 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.DeadObjectException;
import android.os.IBinder;
import android.os.RemoteException;
-import android.telephony.mbms.IMbmsStreamingManagerCallback;
-import android.telephony.mbms.IStreamingServiceCallback;
import android.telephony.mbms.MbmsException;
+import android.telephony.mbms.MbmsStreamingManagerCallback;
import android.telephony.mbms.StreamingService;
+import android.telephony.mbms.StreamingServiceCallback;
import android.telephony.mbms.StreamingServiceInfo;
import android.telephony.mbms.vendor.IMbmsStreamingService;
import android.util.Log;
@@ -78,14 +77,14 @@ public class MbmsStreamingManager {
};
private List<ServiceListener> mServiceListeners = new LinkedList<>();
- private IMbmsStreamingManagerCallback mCallbackToApp;
+ private MbmsStreamingManagerCallback mCallbackToApp;
private final String mAppName;
private final Context mContext;
private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
/** @hide */
- private MbmsStreamingManager(Context context, IMbmsStreamingManagerCallback listener,
+ private MbmsStreamingManager(Context context, MbmsStreamingManagerCallback listener,
String streamingAppName, int subscriptionId) {
mContext = context;
mAppName = streamingAppName;
@@ -96,18 +95,18 @@ public class MbmsStreamingManager {
/**
* Create a new MbmsStreamingManager using the given subscription ID.
*
- * Note that this call will bind a remote service and that may take a bit. This
- * may throw an {@link MbmsException}, indicating errors that may happen during
- * the initialization or binding process.
+ * Note that this call will bind a remote service. You may not call this method on your app's
+ * main thread. This may throw an {@link MbmsException}, indicating errors that may happen
+ * during the initialization or binding process.
*
- * @param context
- * @param listener
- * @param streamingAppName
- * @param subscriptionId
- * @return
+ * @param context The {@link Context} to use.
+ * @param listener A callback object on which you wish to receive results of asynchronous
+ * operations.
+ * @param streamingAppName The name of the streaming app, as specified by the carrier.
+ * @param subscriptionId The subscription ID to use.
*/
public static MbmsStreamingManager create(Context context,
- IMbmsStreamingManagerCallback listener, String streamingAppName, int subscriptionId)
+ MbmsStreamingManagerCallback listener, String streamingAppName, int subscriptionId)
throws MbmsException {
MbmsStreamingManager manager = new MbmsStreamingManager(context, listener,
streamingAppName, subscriptionId);
@@ -117,12 +116,10 @@ public class MbmsStreamingManager {
/**
* Create a new MbmsStreamingManager using the system default data subscription ID.
- *
- * Note that this call will bind a remote service and that may take a bit. This
- * may throw an IllegalArgumentException or RemoteException.
+ * See {@link #create(Context, MbmsStreamingManagerCallback, String, int)}.
*/
public static MbmsStreamingManager create(Context context,
- IMbmsStreamingManagerCallback listener, String streamingAppName)
+ MbmsStreamingManagerCallback listener, String streamingAppName)
throws MbmsException {
int subId = SubscriptionManager.getDefaultSubscriptionId();
MbmsStreamingManager manager = new MbmsStreamingManager(context, listener,
@@ -156,53 +153,63 @@ public class MbmsStreamingManager {
*
* Multiple calls replace the list of serviceClasses of interest.
*
- * May throw an IllegalArgumentException or RemoteException.
- *
- * Synchronous responses include
- * <li>SUCCESS</li>
- * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+ * This may throw an {@link MbmsException} containing one of the following errors:
+ * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
+ * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
+ * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
*
- * Asynchronous errors through the listener include any of the errors except
- * <li>ERROR_MSDC_UNABLE_TO_)START_SERVICE</li>
- * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
- * <li>ERROR_MSDC_END_OF_SESSION</li>
+ * Asynchronous error codes via the {@link MbmsStreamingManagerCallback#error(int, String)}
+ * callback can include any of the errors except:
+ * {@link MbmsException#ERROR_UNABLE_TO_START_SERVICE}
+ * {@link MbmsException#ERROR_END_OF_SESSION}
*/
- public int getStreamingServices(List<String> classList) {
- return 0;
+ public void getStreamingServices(List<String> classList) throws MbmsException {
+ if (mService == null) {
+ throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
+ }
+ try {
+ int returnCode = mService.getStreamingServices(mAppName, mSubscriptionId, classList);
+ if (returnCode != MbmsException.SUCCESS) {
+ throw new MbmsException(returnCode);
+ }
+ } catch (RemoteException e) {
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ }
}
/**
* Starts streaming a requested service, reporting status to the indicated listener.
- * Returns an object used to control that stream.
+ * Returns an object used to control that stream. The stream may not be ready for consumption
+ * immediately upon return from this method -- wait until the streaming state has been
+ * reported via {@link android.telephony.mbms.StreamingServiceCallback#streamStateChanged(int)}.
+ *
+ * May throw an {@link MbmsException} containing any of the following error codes:
+ * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
+ * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
+ * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
*
- * May throw an IllegalArgumentException or RemoteException.
+ * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
*
* Asynchronous errors through the listener include any of the errors
*/
public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
- IStreamingServiceCallback listener) {
- return null;
- }
+ StreamingServiceCallback listener) throws MbmsException {
+ if (mService == null) {
+ throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
+ }
- /**
- * Lists all the services currently being streamed to the device by this application
- * on this given subId. Results are returned asynchronously through the previously
- * registered callback.
- *
- * May throw a RemoteException.
- *
- * The return value is a success/error-code with the following possible values:
- * <li>SUCCESS</li>
- * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
- *
- * Asynchronous errors through the listener include any of the errors except
- * <li>ERROR_UNABLED_TO_START_SERVICE</li>
- * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
- * <li>ERROR_MSDC_END_OF_SESSION</li>
- *
- */
- public int getActiveStreamingServices() {
- return 0;
+ try {
+ int returnCode = mService.startStreaming(
+ mAppName, mSubscriptionId, serviceInfo.getServiceId(), listener);
+ if (returnCode != MbmsException.SUCCESS) {
+ throw new MbmsException(returnCode);
+ }
+ } catch (RemoteException e) {
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ }
+
+ return new StreamingService(
+ mAppName, mSubscriptionId, mService, serviceInfo, listener);
}
private void bindAndInitialize() throws MbmsException {
@@ -262,7 +269,7 @@ public class MbmsStreamingManager {
} catch (RemoteException e) {
mService = null;
Log.e(LOG_TAG, "Service died before initialization");
- throw new MbmsException(MbmsException.ERROR_INITIALIZATION_REMOTE_EXCEPTION);
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
}
}
}
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
new file mode 100644
index 000000000000..0cb4cff0858e
--- /dev/null
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.telephony;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.telephony.ITelephony;
+
+/**
+ * Allows applications to request the system to perform a network scan.
+ *
+ * The caller of {@link #requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} will
+ * receive a NetworkScan which contains the callback method to stop the scan requested.
+ * @hide
+ */
+public class NetworkScan {
+
+ public static final String TAG = "NetworkScan";
+
+ public static final int SUCCESS = 0;
+ public static final int ERROR_INVALID_SCAN = 1;
+ public static final int ERROR_UNSUPPORTED = 2;
+ public static final int ERROR_INTERRUPTED = 3;
+ public static final int ERROR_CANCELLED = 4;
+
+ private final int mScanId;
+ private final int mSubId;
+
+ /**
+ * Stops the network scan
+ *
+ * This is the callback method to stop an ongoing scan. When user requests a new scan,
+ * a NetworkScan object will be returned, and the user can stop the scan by calling this
+ * method.
+ */
+ public void stop() throws RemoteException {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.stopNetworkScan(mSubId, mScanId);
+ } else {
+ throw new RemoteException("Failed to get the ITelephony instance.");
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
+ throw new RemoteException("Failed to stop the network scan with id " + mScanId);
+ }
+ }
+
+ /**
+ * Creates a new NetworkScan with scanId
+ *
+ * @param scanId The id of the scan
+ * @param subId the id of the subscription
+ * @hide
+ */
+ public NetworkScan(int scanId, int subId) {
+ mScanId = scanId;
+ mSubId = subId;
+ }
+
+ private ITelephony getITelephony() {
+ return ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ }
+}
diff --git a/telephony/java/android/telephony/NetworkScanRequest.aidl b/telephony/java/android/telephony/NetworkScanRequest.aidl
new file mode 100644
index 000000000000..5addb1cd7c59
--- /dev/null
+++ b/telephony/java/android/telephony/NetworkScanRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.telephony;
+
+parcelable NetworkScanRequest;
diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java
new file mode 100644
index 000000000000..0a542a7aacef
--- /dev/null
+++ b/telephony/java/android/telephony/NetworkScanRequest.java
@@ -0,0 +1,115 @@
+/*
+ * 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 android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * Defines a request to peform a network scan.
+ *
+ * This class defines whether the network scan will be performed only once or periodically until
+ * cancelled, when the scan is performed periodically, the time interval is not controlled by the
+ * user but defined by the modem vendor.
+ * @hide
+ */
+public final class NetworkScanRequest implements Parcelable {
+
+ /** Performs the scan only once */
+ public static final int SCAN_TYPE_ONE_SHOT = 0;
+ /**
+ * Performs the scan periodically until cancelled
+ *
+ * The modem will start new scans periodically, and the interval between two scans is usually
+ * multiple minutes.
+ * */
+ public static final int SCAN_TYPE_PERIODIC = 1;
+
+ /** Defines the type of the scan. */
+ public int scanType;
+
+ /** Describes the radio access technologies with bands or channels that need to be scanned. */
+ public RadioAccessSpecifier[] specifiers;
+
+ /**
+ * Creates a new NetworkScanRequest with scanType and network specifiers
+ *
+ * @param scanType The type of the scan
+ * @param specifiers the radio network with bands / channels to be scanned
+ */
+ public NetworkScanRequest(int scanType, RadioAccessSpecifier[] specifiers) {
+ this.scanType = scanType;
+ this.specifiers = specifiers;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(scanType);
+ dest.writeParcelableArray(specifiers, flags);
+ }
+
+ private NetworkScanRequest(Parcel in) {
+ scanType = in.readInt();
+ specifiers = (RadioAccessSpecifier[]) in.readParcelableArray(
+ Object.class.getClassLoader(),
+ RadioAccessSpecifier.class);
+ }
+
+ @Override
+ public boolean equals (Object o) {
+ NetworkScanRequest nsr;
+
+ try {
+ nsr = (NetworkScanRequest) o;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ return (scanType == nsr.scanType
+ && Arrays.equals(specifiers, nsr.specifiers));
+ }
+
+ @Override
+ public int hashCode () {
+ return ((scanType * 31)
+ + (Arrays.hashCode(specifiers)) * 37);
+ }
+
+ public static final Creator<NetworkScanRequest> CREATOR =
+ new Creator<NetworkScanRequest>() {
+ @Override
+ public NetworkScanRequest createFromParcel(Parcel in) {
+ return new NetworkScanRequest(in);
+ }
+
+ @Override
+ public NetworkScanRequest[] newArray(int size) {
+ return new NetworkScanRequest[size];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/RadioAccessSpecifier.aidl b/telephony/java/android/telephony/RadioAccessSpecifier.aidl
new file mode 100644
index 000000000000..7e09e0b4f74c
--- /dev/null
+++ b/telephony/java/android/telephony/RadioAccessSpecifier.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.telephony;
+
+parcelable RadioAccessSpecifier;
diff --git a/telephony/java/android/telephony/RadioAccessSpecifier.java b/telephony/java/android/telephony/RadioAccessSpecifier.java
new file mode 100644
index 000000000000..33ce8b4212bc
--- /dev/null
+++ b/telephony/java/android/telephony/RadioAccessSpecifier.java
@@ -0,0 +1,129 @@
+/*
+ * 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 android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * Describes a particular radio access network to be scanned.
+ *
+ * The scan can be performed on either bands or channels for a specific radio access network type.
+ * @hide
+ */
+public final class RadioAccessSpecifier implements Parcelable {
+
+ /**
+ * The radio access network that needs to be scanned
+ *
+ * See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
+ */
+ public int radioAccessNetwork;
+
+ /**
+ * The frequency bands that need to be scanned
+ *
+ * bands must be used together with radioAccessNetwork
+ *
+ * See {@link RadioNetworkConstants} for details.
+ */
+ public int[] bands;
+
+ /**
+ * The frequency channels that need to be scanned
+ *
+ * channels must be used together with radioAccessNetwork
+ *
+ * See {@link RadioNetworkConstants.RadioAccessNetworks} for details.
+ */
+ public int[] channels;
+
+ /**
+ * Creates a new RadioAccessSpecifier with radio network, bands and channels
+ *
+ * The user must specify the radio network type, and at least specify either of frequency
+ * bands or channels.
+ *
+ * @param ran The type of the radio access network
+ * @param bands the frequency bands to be scanned
+ * @param channels the frequency bands to be scanned
+ */
+ public RadioAccessSpecifier(int ran, int[] bands, int[] channels) {
+ this.radioAccessNetwork = ran;
+ this.bands = bands;
+ this.channels = channels;
+ }
+
+ public static final Parcelable.Creator<RadioAccessSpecifier> CREATOR =
+ new Parcelable.Creator<RadioAccessSpecifier> (){
+ @Override
+ public RadioAccessSpecifier createFromParcel(Parcel in) {
+ return new RadioAccessSpecifier(in);
+ }
+
+ @Override
+ public RadioAccessSpecifier[] newArray(int size) {
+ return new RadioAccessSpecifier[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(radioAccessNetwork);
+ dest.writeIntArray(bands);
+ dest.writeIntArray(channels);
+ }
+
+ private RadioAccessSpecifier(Parcel in) {
+ radioAccessNetwork = in.readInt();
+ bands = in.createIntArray();
+ channels = in.createIntArray();
+ }
+
+ @Override
+ public boolean equals (Object o) {
+ RadioAccessSpecifier ras;
+
+ try {
+ ras = (RadioAccessSpecifier) o;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ return (radioAccessNetwork == ras.radioAccessNetwork
+ && Arrays.equals(bands, ras.bands)
+ && Arrays.equals(channels, ras.channels));
+ }
+
+ @Override
+ public int hashCode () {
+ return ((radioAccessNetwork * 31)
+ + (Arrays.hashCode(bands) * 37)
+ + (Arrays.hashCode(channels)) * 39);
+ }
+}
diff --git a/telephony/java/android/telephony/RadioNetworkConstants.java b/telephony/java/android/telephony/RadioNetworkConstants.java
new file mode 100644
index 000000000000..1a9072d3eb0a
--- /dev/null
+++ b/telephony/java/android/telephony/RadioNetworkConstants.java
@@ -0,0 +1,169 @@
+/*
+ * 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 android.telephony;
+
+/**
+ * Contains radio access network related constants.
+ * @hide
+ */
+public final class RadioNetworkConstants {
+
+ public static final class RadioAccessNetworks {
+ public static final int GERAN = 1;
+ public static final int UTRAN = 2;
+ public static final int EUTRAN = 3;
+ /** @hide */
+ public static final int CDMA2000 = 4;
+ }
+
+ /**
+ * Frenquency bands for GERAN.
+ * http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
+ */
+ public static final class GeranBands {
+ public static final int BAND_T380 = 1;
+ public static final int BAND_T410 = 2;
+ public static final int BAND_450 = 3;
+ public static final int BAND_480 = 4;
+ public static final int BAND_710 = 5;
+ public static final int BAND_750 = 6;
+ public static final int BAND_T810 = 7;
+ public static final int BAND_850 = 8;
+ public static final int BAND_P900 = 9;
+ public static final int BAND_E900 = 10;
+ public static final int BAND_R900 = 11;
+ public static final int BAND_DCS1800 = 12;
+ public static final int BAND_PCS1900 = 13;
+ public static final int BAND_ER900 = 14;
+ }
+
+ /**
+ * Frenquency bands for UTRAN.
+ * http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
+ */
+ public static final class UtranBands {
+ public static final int BAND_1 = 1;
+ public static final int BAND_2 = 2;
+ public static final int BAND_3 = 3;
+ public static final int BAND_4 = 4;
+ public static final int BAND_5 = 5;
+ public static final int BAND_6 = 6;
+ public static final int BAND_7 = 7;
+ public static final int BAND_8 = 8;
+ public static final int BAND_9 = 9;
+ public static final int BAND_10 = 10;
+ public static final int BAND_11 = 11;
+ public static final int BAND_12 = 12;
+ public static final int BAND_13 = 13;
+ public static final int BAND_14 = 14;
+ /** band 15, 16, 17, 18 are reserved */
+ public static final int BAND_19 = 19;
+ public static final int BAND_20 = 20;
+ public static final int BAND_21 = 21;
+ public static final int BAND_22 = 22;
+ /** band 23, 24 are reserved */
+ public static final int BAND_25 = 25;
+ public static final int BAND_26 = 26;
+ }
+
+ /**
+ * Frenquency bands for EUTRAN.
+ * http://www.etsi.org/deliver/etsi_ts/136100_136199/136101/14.03.00_60/ts_136101v140p.pdf
+ */
+ public static final class EutranBands {
+ public static final int BAND_1 = 1;
+ public static final int BAND_2 = 2;
+ public static final int BAND_3 = 3;
+ public static final int BAND_4 = 4;
+ public static final int BAND_5 = 5;
+ public static final int BAND_6 = 6;
+ public static final int BAND_7 = 7;
+ public static final int BAND_8 = 8;
+ public static final int BAND_9 = 9;
+ public static final int BAND_10 = 10;
+ public static final int BAND_11 = 11;
+ public static final int BAND_12 = 12;
+ public static final int BAND_13 = 13;
+ public static final int BAND_14 = 14;
+ public static final int BAND_17 = 17;
+ public static final int BAND_18 = 18;
+ public static final int BAND_19 = 19;
+ public static final int BAND_20 = 20;
+ public static final int BAND_21 = 21;
+ public static final int BAND_22 = 22;
+ public static final int BAND_23 = 23;
+ public static final int BAND_24 = 24;
+ public static final int BAND_25 = 25;
+ public static final int BAND_26 = 26;
+ public static final int BAND_27 = 27;
+ public static final int BAND_28 = 28;
+ public static final int BAND_30 = 30;
+ public static final int BAND_31 = 31;
+ public static final int BAND_33 = 33;
+ public static final int BAND_34 = 34;
+ public static final int BAND_35 = 35;
+ public static final int BAND_36 = 36;
+ public static final int BAND_37 = 37;
+ public static final int BAND_38 = 38;
+ public static final int BAND_39 = 39;
+ public static final int BAND_40 = 40;
+ public static final int BAND_41 = 41;
+ public static final int BAND_42 = 42;
+ public static final int BAND_43 = 43;
+ public static final int BAND_44 = 44;
+ public static final int BAND_45 = 45;
+ public static final int BAND_46 = 46;
+ public static final int BAND_47 = 47;
+ public static final int BAND_48 = 48;
+ public static final int BAND_65 = 65;
+ public static final int BAND_66 = 66;
+ public static final int BAND_68 = 68;
+ public static final int BAND_70 = 70;
+ }
+
+ /**
+ * Frenquency bands for CDMA2000.
+ * http://www.3gpp2.org/Public_html/Specs/C.S0057-E_v1.0_Bandclass_Specification.pdf
+ * @hide
+ *
+ * TODO(yinxu): Check with the nexus team about the definition of CDMA bands.
+ */
+ public static final class CdmaBands {
+ public static final int BAND_0 = 1;
+ public static final int BAND_1 = 2;
+ public static final int BAND_2 = 3;
+ public static final int BAND_3 = 4;
+ public static final int BAND_4 = 5;
+ public static final int BAND_5 = 6;
+ public static final int BAND_6 = 7;
+ public static final int BAND_7 = 8;
+ public static final int BAND_8 = 9;
+ public static final int BAND_9 = 10;
+ public static final int BAND_10 = 11;
+ public static final int BAND_11 = 12;
+ public static final int BAND_12 = 13;
+ public static final int BAND_13 = 14;
+ public static final int BAND_14 = 15;
+ public static final int BAND_15 = 16;
+ public static final int BAND_16 = 17;
+ public static final int BAND_17 = 18;
+ public static final int BAND_18 = 19;
+ public static final int BAND_19 = 20;
+ public static final int BAND_20 = 21;
+ public static final int BAND_21 = 22;
+ }
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index d6e74cf5ede9..dcdda8685e02 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -463,9 +463,28 @@ public class SmsMessage {
*/
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message, boolean statusReportRequested) {
- SubmitPduBase spb;
+ return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested,
+ SubscriptionManager.getDefaultSmsSubscriptionId());
+ }
- if (useCdmaFormatForMoSms()) {
+ /**
+ * Get an SMS-SUBMIT PDU for a destination address and a message.
+ * This method will not attempt to use any GSM national language 7 bit encodings.
+ *
+ * @param scAddress Service Centre address. Null means use default.
+ * @param destinationAddress the address of the destination for the message.
+ * @param message String representation of the message payload.
+ * @param statusReportRequested Indicates whether a report is requested for this message.
+ * @param subId Subscription of the message
+ * @return a <code>SubmitPdu</code> containing the encoded SC
+ * address, if applicable, and the encoded message.
+ * Returns null on encode error.
+ * @hide
+ */
+ public static SubmitPdu getSubmitPdu(String scAddress,
+ String destinationAddress, String message, boolean statusReportRequested, int subId) {
+ SubmitPduBase spb;
+ if (useCdmaFormatForMoSms(subId)) {
spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
destinationAddress, message, statusReportRequested, null);
} else {
@@ -758,12 +777,27 @@ public class SmsMessage {
* @return true if Cdma format should be used for MO SMS, false otherwise.
*/
private static boolean useCdmaFormatForMoSms() {
- if (!SmsManager.getDefault().isImsSmsSupported()) {
+ // IMS is registered with SMS support, check the SMS format supported
+ return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
+ }
+
+ /**
+ * Determines whether or not to use CDMA format for MO SMS.
+ * If SMS over IMS is supported, then format is based on IMS SMS format,
+ * otherwise format is based on current phone type.
+ *
+ * @param subId Subscription for which phone type is returned.
+ *
+ * @return true if Cdma format should be used for MO SMS, false otherwise.
+ */
+ private static boolean useCdmaFormatForMoSms(int subId) {
+ SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+ if (!smsManager.isImsSmsSupported()) {
// use Voice technology to determine SMS format.
- return isCdmaVoice();
+ return isCdmaVoice(subId);
}
// IMS is registered with SMS support, check the SMS format supported
- return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
+ return (SmsConstants.FORMAT_3GPP2.equals(smsManager.getImsSmsFormat()));
}
/**
@@ -772,10 +806,18 @@ public class SmsMessage {
* @return true if current phone type is cdma, false otherwise.
*/
private static boolean isCdmaVoice() {
- int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
- return (PHONE_TYPE_CDMA == activePhone);
+ return isCdmaVoice(SubscriptionManager.getDefaultSmsSubscriptionId());
}
+ /**
+ * Determines whether or not to current phone type is cdma
+ *
+ * @return true if current phone type is cdma, false otherwise.
+ */
+ private static boolean isCdmaVoice(int subId) {
+ int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(subId);
+ return (PHONE_TYPE_CDMA == activePhone);
+ }
/**
* Decide if the carrier supports long SMS.
* {@hide}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 32536fc77343..3fcb2806bad4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -39,6 +39,11 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -144,6 +149,7 @@ public class TelephonyManager {
private final Context mContext;
private final int mSubId;
private SubscriptionManager mSubscriptionManager;
+ private TelephonyScanManager mTelephonyScanManager;
private static String multiSimConfig =
SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
@@ -4573,6 +4579,32 @@ public class TelephonyManager {
}
/**
+ * Request a network scan.
+ *
+ * This method is asynchronous, so the network scan results will be returned by callback.
+ * The returned NetworkScan will contain a callback method which can be used to stop the scan.
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param request Contains all the RAT with bands/channels that need to be scanned.
+ * @param callback Returns network scan results or errors.
+ * @return A NetworkScan obj which contains a callback which can stop the scan.
+ * @hide
+ */
+ public NetworkScan requestNetworkScan(
+ NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+ synchronized (this) {
+ if (mTelephonyScanManager == null) {
+ mTelephonyScanManager = new TelephonyScanManager();
+ }
+ }
+ return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
+ }
+
+ /**
* Ask the radio to connect to the input network and change selection mode to manual.
*
* <p>
@@ -5696,35 +5728,75 @@ public class TelephonyManager {
}
/**
- * Set SIM card power state. Request is equivalent to inserting or removing the card.
+ * Requested state of SIM
+ *
+ * CARD_POWER_DOWN
+ * Powers down the SIM. SIM must be up prior.
*
- * @param powerUp True if powering up the SIM, otherwise powering down
+ * CARD_POWER_UP
+ * Powers up the SIM normally. SIM must be down prior.
+ *
+ * CARD_POWER_UP_PASS_THROUGH
+ * Powers up the SIM in PASS_THROUGH mode. SIM must be down prior.
+ * When SIM is powered up in PASS_THOUGH mode, the modem does not send
+ * any command to it (for example SELECT of MF, or TERMINAL CAPABILITY),
+ * and the SIM card is controlled completely by Telephony sending APDUs
+ * directly. The SIM card state will be RIL_CARDSTATE_PRESENT and the
+ * number of card apps will be 0.
+ * No new error code is generated. Emergency calls are supported in the
+ * same way as if the SIM card is absent.
+ * The PASS_THROUGH mode is valid only for the specific card session where it
+ * is activated, and normal behavior occurs at the next SIM initialization,
+ * unless PASS_THROUGH mode is requested again. Hence, the last power-up mode
+ * is NOT persistent across boots. On reboot, SIM will power up normally.
+ */
+ /** @hide */
+ public static final int CARD_POWER_DOWN = 0;
+ /** @hide */
+ public static final int CARD_POWER_UP = 1;
+ /** @hide */
+ public static final int CARD_POWER_UP_PASS_THROUGH = 2;
+
+ /**
+ * Set SIM card power state.
+ *
+ * @param state State of SIM (power down, power up, pass through)
+ * @see #CARD_POWER_DOWN
+ * @see #CARD_POWER_UP
+ * @see #CARD_POWER_UP_PASS_THROUGH
+ * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
+ * broadcasts to determine success or failure and timeout if needed.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
* @hide
**/
- public void setSimPowerState(boolean powerUp) {
- setSimPowerStateForSlot(getSlotIndex(), powerUp);
+ public void setSimPowerState(int state) {
+ setSimPowerStateForSlot(getSlotIndex(), state);
}
/**
- * Set SIM card power state. Request is equivalent to inserting or removing the card.
+ * Set SIM card power state.
*
* @param slotIndex SIM slot id
- * @param powerUp True if powering up the SIM, otherwise powering down
+ * @param state State of SIM (power down, power up, pass through)
+ * @see #CARD_POWER_DOWN
+ * @see #CARD_POWER_UP
+ * @see #CARD_POWER_UP_PASS_THROUGH
+ * Callers should monitor for {@link TelephonyIntents#ACTION_SIM_STATE_CHANGED}
+ * broadcasts to determine success or failure and timeout if needed.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
*
* @hide
**/
- public void setSimPowerStateForSlot(int slotIndex, boolean powerUp) {
+ public void setSimPowerStateForSlot(int slotIndex, int state) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.setSimPowerStateForSlot(slotIndex, powerUp);
+ telephony.setSimPowerStateForSlot(slotIndex, state);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
@@ -6442,5 +6514,26 @@ public class TelephonyManager {
}
return false;
}
+
+ /**
+ * Get the most recently available signal strength information.
+ *
+ * Get the most recent SignalStrength information reported by the modem. Due
+ * to power saving this information may not always be current.
+ * @return the most recent cached signal strength info from the modem
+ * @hide
+ */
+ @Nullable
+ public SignalStrength getSignalStrength() {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getSignalStrength(getSubId());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#getSignalStrength", e);
+ }
+ return null;
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
new file mode 100644
index 000000000000..c905d3a433f3
--- /dev/null
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -0,0 +1,186 @@
+/*
+ * 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 android.telephony;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.SparseArray;
+import java.util.List;
+
+import com.android.internal.telephony.ITelephony;
+
+/**
+ * Manages the radio access network scan requests and callbacks.
+ * @hide
+ */
+public final class TelephonyScanManager {
+
+ private static final String TAG = "TelephonyScanManager";
+
+ /** @hide */
+ public static final int CALLBACK_SCAN_RESULTS = 1;
+ /** @hide */
+ public static final int CALLBACK_SCAN_ERROR = 2;
+ /** @hide */
+ public static final int CALLBACK_SCAN_COMPLETE = 3;
+
+ /**
+ * The caller of {@link #requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
+ * implement and provide this callback so that the scan results or errors can be returned.
+ */
+ public static abstract class NetworkScanCallback {
+ /** Returns the scan results to the user, this callback will be called multiple times. */
+ public void onResults(List<CellInfo> results) {}
+
+ /**
+ * Informs the user that the scan has stopped.
+ *
+ * This callback will be called when the scan is finished or cancelled by the user.
+ * The related NetworkScanRequest will be deleted after this callback.
+ */
+ public void onComplete() {}
+
+ /**
+ * Informs the user that there is some error about the scan.
+ *
+ * This callback will be called whenever there is any error about the scan, but the scan
+ * won't stop unless the onComplete() callback is called.
+ */
+ public void onError(int error) {}
+ }
+
+ private static class NetworkScanInfo {
+ private final NetworkScanRequest mRequest;
+ private final NetworkScanCallback mCallback;
+
+ NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
+ mRequest = request;
+ mCallback = callback;
+ }
+ }
+
+ private final Looper mLooper;
+ private final Messenger mMessenger;
+ private SparseArray<NetworkScanInfo> mScanInfo = new SparseArray<NetworkScanInfo>();
+
+ public TelephonyScanManager() {
+ HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ mLooper = thread.getLooper();
+ mMessenger = new Messenger(new Handler(mLooper) {
+ @Override
+ public void handleMessage(Message message) {
+ checkNotNull(message, "message cannot be null");
+ NetworkScanInfo nsi;
+ synchronized (mScanInfo) {
+ nsi = mScanInfo.get(message.arg2);
+ }
+ if (nsi == null) {
+ throw new RuntimeException(
+ "Failed to find NetworkScanInfo with id " + message.arg2);
+ }
+ NetworkScanCallback callback = nsi.mCallback;
+ if (callback == null) {
+ throw new RuntimeException(
+ "Failed to find NetworkScanCallback with id " + message.arg2);
+ }
+
+ switch (message.what) {
+ case CALLBACK_SCAN_RESULTS:
+ try {
+ callback.onResults((List<CellInfo>) message.obj);
+ } catch (Exception e) {
+ Rlog.e(TAG, "Exception in networkscan callback onResults", e);
+ }
+ break;
+ case CALLBACK_SCAN_ERROR:
+ try {
+ callback.onError(message.arg1);
+ } catch (Exception e) {
+ Rlog.e(TAG, "Exception in networkscan callback onError", e);
+ }
+ break;
+ case CALLBACK_SCAN_COMPLETE:
+ try {
+ callback.onComplete();
+ mScanInfo.remove(message.arg2);
+ } catch (Exception e) {
+ Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
+ }
+ break;
+ default:
+ Rlog.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
+ break;
+ }
+ }
+ });
+ }
+
+ /**
+ * Request a network scan.
+ *
+ * This method is asynchronous, so the network scan results will be returned by callback.
+ * The returned NetworkScan will contain a callback method which can be used to stop the scan.
+ *
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param request Contains all the RAT with bands/channels that need to be scanned.
+ * @param callback Returns network scan results or errors.
+ * @return A NetworkScan obj which contains a callback which can stop the scan.
+ * @hide
+ */
+ public NetworkScan requestNetworkScan(int subId,
+ NetworkScanRequest request, NetworkScanCallback callback) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
+ saveScanInfo(scanId, request, callback);
+ return new NetworkScan(scanId, subId);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "requestNetworkScan RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "requestNetworkScan NPE", ex);
+ }
+ return null;
+ }
+
+ private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
+ synchronized (mScanInfo) {
+ mScanInfo.put(id, new NetworkScanInfo(request, callback));
+ }
+ }
+
+ private ITelephony getITelephony() {
+ return ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ }
+}
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index f1f683c70735..511ac3833701 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -105,10 +105,11 @@ public abstract class ImsService extends ImsServiceBase {
}
@Override
- public void removeImsFeature(int slotId, int feature) throws RemoteException {
+ public void removeImsFeature(int slotId, int feature, IImsFeatureStatusCallback c)
+ throws RemoteException {
synchronized (mFeatures) {
enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, "removeImsFeature");
- onRemoveImsFeatureInternal(slotId, feature);
+ onRemoveImsFeatureInternal(slotId, feature, c);
}
}
@@ -355,7 +356,7 @@ public abstract class ImsService extends ImsServiceBase {
if (f != null) {
f.setContext(this);
f.setSlotId(slotId);
- f.setImsFeatureStatusCallback(c);
+ f.addImsFeatureStatusCallback(c);
featureMap.put(featureType, f);
}
@@ -368,7 +369,8 @@ public abstract class ImsService extends ImsServiceBase {
* defined in {@link ImsFeature}.
*/
// Be sure to lock on mFeatures before accessing this method
- private void onRemoveImsFeatureInternal(int slotId, int featureType) {
+ private void onRemoveImsFeatureInternal(int slotId, int featureType,
+ IImsFeatureStatusCallback c) {
SparseArray<ImsFeature> featureMap = mFeatures.get(slotId);
if (featureMap == null) {
return;
@@ -379,7 +381,7 @@ public abstract class ImsService extends ImsServiceBase {
featureMap.remove(featureType);
featureToRemove.notifyFeatureRemoved(slotId);
// Remove reference to Binder
- featureToRemove.setImsFeatureStatusCallback(null);
+ featureToRemove.removeImsFeatureStatusCallback(c);
}
}
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 395f1ccc7a29..9d880b7395ef 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -28,7 +28,11 @@ import com.android.ims.internal.IImsFeatureStatusCallback;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import java.util.WeakHashMap;
/**
* Base class for all IMS features that are supported by the framework.
@@ -88,7 +92,8 @@ public abstract class ImsFeature {
public static final int STATE_READY = 2;
private List<INotifyFeatureRemoved> mRemovedListeners = new ArrayList<>();
- private IImsFeatureStatusCallback mStatusCallback;
+ private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
+ new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
private @ImsState int mState = STATE_NOT_AVAILABLE;
private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private Context mContext;
@@ -136,11 +141,29 @@ public abstract class ImsFeature {
}
}
- // Not final for testing.
- public void setImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
- mStatusCallback = c;
- // If we have just connected, send queued status.
- notifyFeatureState(mState);
+ public void addImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ try {
+ // If we have just connected, send queued status.
+ c.notifyImsFeatureStatus(mState);
+ // Add the callback if the callback completes successfully without a RemoteException.
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.add(c);
+ }
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
+ }
+
+ public void removeImsFeatureStatusCallback(IImsFeatureStatusCallback c) {
+ if (c == null) {
+ return;
+ }
+ synchronized (mStatusCallbacks) {
+ mStatusCallbacks.remove(c);
+ }
}
/**
@@ -148,13 +171,18 @@ public abstract class ImsFeature {
* @param state
*/
private void notifyFeatureState(@ImsState int state) {
- if (mStatusCallback != null) {
- try {
- Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
- mStatusCallback.notifyImsFeatureStatus(state);
- } catch (RemoteException e) {
- mStatusCallback = null;
- Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ synchronized (mStatusCallbacks) {
+ for (Iterator<IImsFeatureStatusCallback> iter = mStatusCallbacks.iterator();
+ iter.hasNext(); ) {
+ IImsFeatureStatusCallback callback = iter.next();
+ try {
+ Log.i(LOG_TAG, "notifying ImsFeatureState=" + state);
+ callback.notifyImsFeatureStatus(state);
+ } catch (RemoteException e) {
+ // remove if the callback is no longer alive.
+ iter.remove();
+ Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage());
+ }
}
}
sendImsServiceIntent(state);
diff --git a/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl b/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
index 7b4ecf25ea9c..891edad8c9bf 100755
--- a/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
+++ b/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
@@ -17,15 +17,13 @@
package android.telephony.mbms;
import android.net.Uri;
-import android.telephony.SignalStrength;
-import android.telephony.mbms.StreamingService;
/**
* @hide
*/
oneway interface IStreamingServiceCallback {
void error(int errorCode, String message);
- void streamStateChanged(in StreamingService service, int state);
+ void streamStateChanged(int state);
void uriUpdated(in Uri uri);
- void signalStrengthUpdated(in SignalStrength signalStrength);
+ void broadcastSignalStrengthUpdated(int signalStrength);
}
diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsException.java
index cc4a02a13717..a0ded9bd565b 100644
--- a/telephony/java/android/telephony/mbms/MbmsException.java
+++ b/telephony/java/android/telephony/mbms/MbmsException.java
@@ -16,22 +16,25 @@
package android.telephony.mbms;
-import android.os.RemoteException;
-
/** @hide */
-public class MbmsException extends RemoteException {
+public class MbmsException extends Exception {
public static final int SUCCESS = 0;
public static final int ERROR_NO_SERVICE_INSTALLED = 1;
public static final int ERROR_MULTIPLE_SERVICES_INSTALLED = 2;
public static final int ERROR_BIND_TIMEOUT_OR_FAILURE = 3;
- public static final int ERROR_INITIALIZATION_REMOTE_EXCEPTION = 4;
+ public static final int ERROR_UNKNOWN_REMOTE_EXCEPTION = 4;
public static final int ERROR_ALREADY_INITIALIZED = 5;
+ public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 6;
+ public static final int ERROR_MIDDLEWARE_NOT_BOUND = 7;
+ public static final int ERROR_UNABLE_TO_START_SERVICE = 8;
+ public static final int ERROR_STREAM_ALREADY_STARTED = 9;
+ public static final int ERROR_END_OF_SESSION = 10;
private final int mErrorCode;
/** @hide
* TODO: future systemapi
- * */
+ */
public MbmsException(int errorCode) {
super();
mErrorCode = errorCode;
diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java
index cb621c8bbfd0..f167f0ab228e 100644
--- a/telephony/java/android/telephony/mbms/ServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/ServiceInfo.java
@@ -114,6 +114,7 @@ public class ServiceInfo implements Parcelable {
sessionEndTime = (java.util.Date) in.readSerializable();
}
+ @Override
public void writeToParcel(Parcel dest, int flags) {
Set<Locale> keySet = names.keySet();
dest.writeInt(keySet.size());
@@ -128,7 +129,33 @@ public class ServiceInfo implements Parcelable {
dest.writeSerializable(sessionEndTime);
}
+ @Override
public int describeContents() {
return 0;
}
+
+ public Map<Locale, String> getNames() {
+ return names;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public Date getSessionStartTime() {
+ return sessionStartTime;
+ }
+
+ public Date getSessionEndTime() {
+ return sessionEndTime;
+ }
+
}
diff --git a/telephony/java/android/telephony/mbms/StreamingService.aidl b/telephony/java/android/telephony/mbms/StreamingService.aidl
deleted file mode 100755
index 0c286f3a0502..000000000000
--- a/telephony/java/android/telephony/mbms/StreamingService.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-** Copyright 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 android.telephony.mbms;
-
-parcelable StreamingService;
diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java
index 8cc604356bad..ac5fbdf62666 100644
--- a/telephony/java/android/telephony/mbms/StreamingService.java
+++ b/telephony/java/android/telephony/mbms/StreamingService.java
@@ -19,46 +19,60 @@ package android.telephony.mbms;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.SignalStrength;
+import android.os.RemoteException;
+import android.telephony.mbms.vendor.IMbmsStreamingService;
+import android.util.Log;
/**
* @hide
*/
public class StreamingService {
-
+ private static final String LOG_TAG = "MbmsStreamingService";
public final static int STATE_STOPPED = 1;
public final static int STATE_STARTED = 2;
public final static int STATE_STALLED = 3;
+ private final String mAppName;
+ private final int mSubscriptionId;
+ private final IMbmsStreamingService mService;
+ private final StreamingServiceInfo mServiceInfo;
+ private final IStreamingServiceCallback mCallback;
/**
+ * @hide
*/
- StreamingService(StreamingServiceInfo streamingServiceInfo,
- IStreamingServiceCallback listener) {
+ public StreamingService(String appName,
+ int subscriptionId,
+ IMbmsStreamingService service,
+ StreamingServiceInfo streamingServiceInfo,
+ IStreamingServiceCallback callback) {
+ mAppName = appName;
+ mSubscriptionId = subscriptionId;
+ mService = service;
+ mServiceInfo = streamingServiceInfo;
+ mCallback = callback;
}
/**
* Retreive the Uri used to play this stream.
*
- * This may throw a RemoteException.
+ * This may throw a {@link MbmsException} with the error code
+ * {@link MbmsException#ERROR_UNKNOWN_REMOTE_EXCEPTION}
+ * @return The {@link Uri} to pass to the streaming client.
*/
- public Uri getPlaybackUri() {
- return null;
+ public Uri getPlaybackUri() throws MbmsException {
+ try {
+ return mService.getPlaybackUri(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Caught remote exception calling getPlaybackUri: " + e);
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+ }
}
/**
* Retreive the info for this StreamingService.
*/
public StreamingServiceInfo getInfo() {
- return null;
- }
-
- /**
- * Retreive the current state of this stream.
- *
- * This may throw a RemoteException.
- */
- public int getState() {
- return STATE_STOPPED;
+ return mServiceInfo;
}
/**
@@ -69,41 +83,13 @@ public class StreamingService {
public void stopStreaming() {
}
- /**
- * Switch this stream to a different service. Used for smooth transitions.
- *
- * This may throw a RemoteException.
- *
- * Asynchronous errors through the listener include any of the errors except
- * <li>ERROR_MSDC_UNABLE_TO_INITIALIZE</li>
- */
- public void switchStream(StreamingServiceInfo streamingServiceInfo) {
- }
-
- public void dispose() {
- }
-
- public static final Parcelable.Creator<StreamingService> CREATOR =
- new Parcelable.Creator<StreamingService>() {
- @Override
- public StreamingService createFromParcel(Parcel in) {
- return new StreamingService(in);
- }
-
- @Override
- public StreamingService[] newArray(int size) {
- return new StreamingService[size];
+ public void dispose() throws MbmsException {
+ try {
+ mService.disposeStream(mAppName, mSubscriptionId, mServiceInfo.getServiceId());
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Caught remote exception calling disposeStream: " + e);
+ throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
}
- };
-
- private StreamingService(Parcel in) {
- }
-
- public void writeToParcel(Parcel dest, int flags) {
- }
-
- public int describeContents() {
- return 0;
}
}
diff --git a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
index 7f5c486f8d90..bd0a1b3bd7d9 100644
--- a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
+++ b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
@@ -17,14 +17,21 @@
package android.telephony.mbms;
import android.net.Uri;
-import android.telephony.SignalStrength;
/**
- * A Callback class for use when the applicaiton is actively streaming content.
+ * A Callback class for use when the application is actively streaming content.
* @hide
*/
public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
+ /**
+ * Indicates broadcast signal strength is not available for this service.
+ *
+ * This may be due to the service no longer being available due to geography
+ * or timing (end of service) or because lack of demand has caused the service
+ * to be delivered via unicast.
+ */
+ public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
public void error(int errorCode, String message) {
// default implementation empty
@@ -36,7 +43,7 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
* See {@link StreamingService#STATE_STOPPED}, {@link StreamingService#STATE_STARTED}
* and {@link StreamingService#STATE_STALLED}.
*/
- public void streamStateChanged(StreamingService service, int state) {
+ public void streamStateChanged(int state) {
// default implementation empty
}
@@ -51,19 +58,16 @@ public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
}
/**
- * Signal Strength updated.
+ * Broadcast Signal Strength updated.
*
* This signal strength is the BROADCAST signal strength which,
* depending on technology in play and it's deployment, may be
* stronger or weaker than the traditional UNICAST signal
- * strength.
- *
- * A {@link android.telephony.SignalStrength#getLevel} result of 0 means
- * you don't have coverage for this stream, either due to geographic
- * restrictions, poor tower coverage or something (yards of concrete?)
- * interferring with the signal.
+ * strength. It a simple int from 0-4 for valid levels or
+ * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
+ * for this service due to timing, geography or popularity.
*/
- public void signalStrengthUpdated(SignalStrength signalStrength) {
+ public void broadcastSignalStrengthUpdated(int signalStrength) {
// default implementation empty
}
}
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
index ddc661df8c91..8ff7fa7c54f3 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
@@ -19,9 +19,7 @@ package android.telephony.mbms.vendor;
import android.net.Uri;
import android.telephony.mbms.IMbmsStreamingManagerCallback;
import android.telephony.mbms.IStreamingServiceCallback;
-import android.telephony.mbms.StreamingService;
import android.telephony.mbms.StreamingServiceInfo;
-import android.telephony.SignalStrength;
/**
* The interface the opaque MbmsStreamingService will satisfy.
@@ -29,55 +27,23 @@ import android.telephony.SignalStrength;
*/
interface IMbmsStreamingService
{
- /**
- * Initialize streaming service
- * Registers this listener, subId with this appName
- *
- */
int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId);
-
- /**
- * - Registers serviceClasses of interest with the uid/appName/subId key.
- * - Starts asynch fetching data on streaming services of matching classes to be reported
- * later by callback.
- *
- * Note that subsequent calls with the same callback, appName, subId and uid will replace
- * the service class list.
- */
int getStreamingServices(String appName, int subId, in List<String> serviceClasses);
- /**
- * - Starts streaming the serviceId given.
- * - if the uid/appName/subId don't match a previously registered callback an error will
- * be returned
- * - Streaming status will be sent via the included listener, including an initial
- * URL-change and State-change pair.
- */
int startStreaming(String appName, int subId, String serviceId,
IStreamingServiceCallback listener);
/**
- * Asynchronously fetches all Services being streamed by this uid/appName/subId.
- */
- int getActiveStreamingServices(String appName, int subId);
-
-
- /**
* Per-stream api. Note each specifies what stream they apply to.
*/
Uri getPlaybackUri(String appName, int subId, String serviceId);
- void switchStreams(String appName, int subId, String oldServiceId, String newServiceId);
-
- int getState(String appName, int subId, String serviceId);
-
void stopStreaming(String appName, int subId, String serviceId);
void disposeStream(String appName, int subId, String serviceId);
-
/**
* End of life for all MbmsStreamingManager's created by this uid/appName/subId.
* Ends any streams run under this uid/appname/subId and calls the disposed methods
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index 9f0c0e94d66b..37f47ffb52f2 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -16,11 +16,12 @@
package android.telephony.mbms.vendor;
+import android.annotation.Nullable;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.mbms.IMbmsStreamingManagerCallback;
import android.telephony.mbms.IStreamingServiceCallback;
-import android.telephony.mbms.StreamingService;
+import android.telephony.mbms.MbmsException;
import java.util.List;
@@ -29,43 +30,81 @@ import java.util.List;
* TODO: future systemapi
*/
public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
-
+ /**
+ * Initialize streaming service for this app and subId, registering the listener.
+ *
+ * May throw an {@link IllegalArgumentException} or a {@link SecurityException}
+ *
+ * @param listener The callback to use to communicate with the app.
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription ID to use.
+ * @return {@link MbmsException#SUCCESS} or {@link MbmsException#ERROR_ALREADY_INITIALIZED}
+ */
@Override
- public int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId)
- throws RemoteException {
+ public int initialize(IMbmsStreamingManagerCallback listener, String appName,
+ int subscriptionId) throws RemoteException {
return 0;
}
+ /**
+ * Registers serviceClasses of interest with the appName/subId key.
+ * Starts async fetching data on streaming services of matching classes to be reported
+ * later via {@link IMbmsStreamingManagerCallback#streamingServicesUpdated(List)}
+ *
+ * Note that subsequent calls with the same uid, appName and subId will replace
+ * the service class list.
+ *
+ * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+ *
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ * @param serviceClasses The service classes that the app wishes to get info on. The strings
+ * may contain arbitrary data as negotiated between the app and the
+ * carrier.
+ * @return One of {@link MbmsException#SUCCESS},
+ * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND},
+ * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+ */
@Override
- public int getStreamingServices(String appName, int subId, List<String> serviceClasses)
- throws RemoteException {
+ public int getStreamingServices(String appName, int subscriptionId,
+ List<String> serviceClasses) throws RemoteException {
return 0;
}
+ /**
+ * Starts streaming on a particular service. This method may perform asynchronous work. When
+ * the middleware is ready to send bits to the frontend, it should inform the app via
+ * {@link IStreamingServiceCallback#streamStateChanged(int)}.
+ *
+ * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+ *
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ * @param serviceId The ID of the streaming service that the app has requested.
+ * @param listener The listener object on which the app wishes to receive updates.
+ * @return TODO: document possible errors
+ */
@Override
- public int startStreaming(String appName, int subId,
+ public int startStreaming(String appName, int subscriptionId,
String serviceId, IStreamingServiceCallback listener) throws RemoteException {
return 0;
}
+ /**
+ * Retrieves the streaming URI for a particular service. If the middleware is not yet ready to
+ * stream the service, this method may return null.
+ *
+ * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+ *
+ * @param appName The app name as negotiated with the wireless carrier.
+ * @param subscriptionId The subscription id to use.
+ * @param serviceId The ID of the streaming service that the app has requested.
+ * @return An opaque {@link Uri} to be passed to a video player that understands the format.
+ */
@Override
- public int getActiveStreamingServices(String appName, int subId) throws RemoteException {
- return 0;
- }
-
- @Override
- public Uri getPlaybackUri(String appName, int subId, String serviceId) throws RemoteException {
- return null;
- }
-
- @Override
- public void switchStreams(String appName, int subId, String oldServiceId, String newServiceId)
+ public @Nullable Uri getPlaybackUri(String appName, int subscriptionId, String serviceId)
throws RemoteException {
- }
-
- @Override
- public int getState(String appName, int subId, String serviceId) throws RemoteException {
- return 0;
+ return null;
}
@Override
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
index 712816f9d20c..bb06d7e085a7 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceController.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -37,7 +37,7 @@ import android.os.Message;
interface IImsServiceController {
// ImsService Control
void createImsFeature(int slotId, int feature, IImsFeatureStatusCallback c);
- void removeImsFeature(int slotId, int feature);
+ void removeImsFeature(int slotId, int feature, IImsFeatureStatusCallback c);
// MMTel Feature
int startSession(int slotId, int featureType, in PendingIntent incomingCallIntent,
in IImsRegistrationListener listener);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f2e1e2691c8f..c5428791de6f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -19,6 +19,8 @@ package com.android.internal.telephony;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Messenger;
import android.os.ResultReceiver;
import android.net.Uri;
import android.service.carrier.CarrierIdentifier;
@@ -29,8 +31,10 @@ import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
+import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyHistogram;
import android.telephony.VisualVoicemailSmsFilterSettings;
import com.android.ims.internal.IImsServiceController;
@@ -794,6 +798,26 @@ interface ITelephony {
CellNetworkScanResult getCellNetworkScanResults(int subId);
/**
+ * Perform a radio network scan and return the id of this scan.
+ *
+ * @param subId the id of the subscription.
+ * @param request Defines all the configs for network scan.
+ * @param messenger Callback messages will be sent using this messenger.
+ * @param binder the binder object instantiated in TelephonyManager.
+ * @return An id for this scan.
+ */
+ int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
+ in IBinder binder);
+
+ /**
+ * Stop an existing radio network scan.
+ *
+ * @param subId the id of the subscription.
+ * @param scanId The id of the scan that is going to be stopped.
+ */
+ void stopNetworkScan(int subId, int scanId);
+
+ /**
* Ask the radio to connect to the input network and change selection mode to manual.
*
* @param subId the id of the subscription.
@@ -1267,12 +1291,12 @@ interface ITelephony {
List<ClientRequestStats> getClientRequestStats(String callingPackage, int subid);
/**
- * Set SIM card power state. Request is equivalent to inserting or removing the card.
+ * Set SIM card power state.
* @param slotIndex SIM slot id
- * @param powerUp True if powering up the SIM, otherwise powering down
+ * @param state State of SIM (power down, power up, pass through)
* @hide
* */
- void setSimPowerStateForSlot(int slotIndex, boolean powerUp);
+ void setSimPowerStateForSlot(int slotIndex, int state);
/**
* Returns a list of Forbidden PLMNs from the specified SIM App
@@ -1293,4 +1317,15 @@ interface ITelephony {
* @hide
*/
boolean getEmergencyCallbackMode(int subId);
+
+ /**
+ * Get the most recently available signal strength information.
+ *
+ * Get the most recent SignalStrength information reported by the modem. Due
+ * to power saving this information may not always be current.
+ * @param subId Subscription index
+ * @return the most recent cached signal strength info from the modem
+ * @hide
+ */
+ SignalStrength getSignalStrength(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/NetworkScanResult.java b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
new file mode 100644
index 000000000000..0099961190e1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
@@ -0,0 +1,129 @@
+/*
+ * 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.internal.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.CellInfo;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Defines the incremental network scan result.
+ *
+ * This class contains the network scan results. When the user starts a new scan, multiple
+ * NetworkScanResult may be returned, containing either the scan result or error. When the user
+ * stops an ongoing scan, only one NetworkScanResult will be returned to indicate either the scan
+ * is now complete or there is some error stopping it.
+ * @hide
+ */
+public final class NetworkScanResult implements Parcelable {
+
+ // Contains only part of the scan result and more are coming.
+ public static final int SCAN_STATUS_PARTIAL = 0;
+
+ // Contains the last part of the scan result and the scan is now complete.
+ public static final int SCAN_STATUS_COMPLETE = 1;
+
+ // The status of the scan, only valid when scanError = SUCCESS.
+ public int scanStatus;
+
+ /**
+ * The error code of the scan
+ *
+ * This is the error code returned from the RIL, see {@link RILConstants} for more details
+ */
+ public int scanError;
+
+ // The scan results, only valid when scanError = SUCCESS.
+ public List<CellInfo> networkInfos;
+
+ /**
+ * Creates a new NetworkScanResult with scanStatus, scanError and networkInfos
+ *
+ * @param scanStatus The status of the scan.
+ * @param scanError The error code of the scan.
+ * @param networkInfos List of the CellInfo.
+ */
+ public NetworkScanResult(int scanStatus, int scanError, List<CellInfo> networkInfos) {
+ this.scanStatus = scanStatus;
+ this.scanError = scanError;
+ this.networkInfos = networkInfos;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(scanStatus);
+ dest.writeInt(scanError);
+ CellInfo[] ci = networkInfos.toArray(new CellInfo[networkInfos.size()]);
+ dest.writeParcelableArray(ci, flags);
+ }
+
+ private NetworkScanResult(Parcel in) {
+ scanStatus = in.readInt();
+ scanError = in.readInt();
+ CellInfo[] ci = (CellInfo[]) in.readParcelableArray(
+ Object.class.getClassLoader(),
+ CellInfo.class);
+ networkInfos = Arrays.asList(ci);
+ }
+
+ @Override
+ public boolean equals (Object o) {
+ NetworkScanResult nsr;
+
+ try {
+ nsr = (NetworkScanResult) o;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ if (o == null) {
+ return false;
+ }
+
+ return (scanStatus == nsr.scanStatus
+ && scanError == nsr.scanError
+ && networkInfos.equals(nsr.networkInfos));
+ }
+
+ @Override
+ public int hashCode () {
+ return ((scanStatus * 31)
+ + (scanError * 23)
+ + (networkInfos.hashCode() * 37));
+ }
+
+ public static final Creator<NetworkScanResult> CREATOR =
+ new Creator<NetworkScanResult>() {
+ @Override
+ public NetworkScanResult createFromParcel(Parcel in) {
+ return new NetworkScanResult(in);
+ }
+
+ @Override
+ public NetworkScanResult[] newArray(int size) {
+ return new NetworkScanResult[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 954b17f744f2..e2d25b8e352c 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -415,6 +415,8 @@ cat include/telephony/ril.h | \
int RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER = 139;
int RIL_REQUEST_SET_SIM_CARD_POWER = 140;
int RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION = 141;
+ int RIL_REQUEST_START_NETWORK_SCAN = 142;
+ int RIL_REQUEST_STOP_NETWORK_SCAN = 143;
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -466,5 +468,7 @@ cat include/telephony/ril.h | \
int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1044;
int RIL_UNSOL_LCEDATA_RECV = 1045;
int RIL_UNSOL_PCO_DATA = 1046;
- int RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION = 1047;
+ int RIL_UNSOL_MODEM_RESTART = 1047;
+ int RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION = 1048;
+ int RIL_UNSOL_NETWORK_SCAN_RESULT = 1049;
}
diff --git a/test-runner/src/android/test/AndroidTestRunner.java b/test-runner/src/android/test/AndroidTestRunner.java
index 50eaafbae39d..7313a2880ea2 100644
--- a/test-runner/src/android/test/AndroidTestRunner.java
+++ b/test-runner/src/android/test/AndroidTestRunner.java
@@ -20,8 +20,7 @@ import android.app.Instrumentation;
import android.content.Context;
import android.os.PerformanceCollector.PerformanceResultsWriter;
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestListener;
@@ -48,7 +47,7 @@ public class AndroidTestRunner extends BaseTestRunner {
private Context mContext;
private boolean mSkipExecution = false;
- private List<TestListener> mTestListeners = Lists.newArrayList();
+ private List<TestListener> mTestListeners = new ArrayList<>();
private Instrumentation mInstrumentation;
private PerformanceResultsWriter mPerfWriter;
@@ -58,7 +57,8 @@ public class AndroidTestRunner extends BaseTestRunner {
if (shouldRunSingleTestMethod(testMethodName, testClass)) {
TestCase testCase = buildSingleTestMethod(testClass, testMethodName);
- mTestCases = Lists.newArrayList(testCase);
+ mTestCases = new ArrayList<>();
+ mTestCases.add(testCase);
mTestClassName = testClass.getSimpleName();
} else {
setTest(getTest(testClass), testClass);
diff --git a/test-runner/src/android/test/ClassPathPackageInfo.java b/test-runner/src/android/test/ClassPathPackageInfo.java
index 1ab7c7faeca4..2cf76afa1d94 100644
--- a/test-runner/src/android/test/ClassPathPackageInfo.java
+++ b/test-runner/src/android/test/ClassPathPackageInfo.java
@@ -16,9 +16,8 @@
package android.test;
-import com.google.android.collect.Sets;
-
import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
/**
@@ -44,7 +43,7 @@ public class ClassPathPackageInfo {
}
public Set<ClassPathPackageInfo> getSubpackages() {
- Set<ClassPathPackageInfo> info = Sets.newHashSet();
+ Set<ClassPathPackageInfo> info = new HashSet<>();
for (String name : subpackageNames) {
info.add(source.getPackageInfo(name));
}
@@ -52,7 +51,7 @@ public class ClassPathPackageInfo {
}
public Set<Class<?>> getTopLevelClassesRecursive() {
- Set<Class<?>> set = Sets.newHashSet();
+ Set<Class<?>> set = new HashSet<>();
addTopLevelClassesTo(set);
return set;
}
diff --git a/test-runner/src/android/test/ClassPathPackageInfoSource.java b/test-runner/src/android/test/ClassPathPackageInfoSource.java
index 89bb494e02dd..9bcc25adf8d3 100644
--- a/test-runner/src/android/test/ClassPathPackageInfoSource.java
+++ b/test-runner/src/android/test/ClassPathPackageInfoSource.java
@@ -17,13 +17,13 @@
package android.test;
import android.util.Log;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
import dalvik.system.DexFile;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@@ -57,7 +57,7 @@ public class ClassPathPackageInfoSource {
private static String[] apkPaths;
// A cache of jar file contents
- private final Map<File, Set<String>> jarFiles = Maps.newHashMap();
+ private final Map<File, Set<String>> jarFiles = new HashMap<>();
private ClassLoader classLoader;
ClassPathPackageInfoSource() {
@@ -76,7 +76,7 @@ public class ClassPathPackageInfoSource {
private ClassPathPackageInfo createPackageInfo(String packageName) {
Set<String> subpackageNames = new TreeSet<String>();
Set<String> classNames = new TreeSet<String>();
- Set<Class<?>> topLevelClasses = Sets.newHashSet();
+ Set<Class<?>> topLevelClasses = new HashSet<>();
findClasses(packageName, classNames, subpackageNames);
for (String className : classNames) {
if (className.endsWith(".R") || className.endsWith(".Manifest")) {
@@ -248,7 +248,7 @@ public class ClassPathPackageInfoSource {
throws IOException {
Set<String> entryNames = jarFiles.get(jarFile);
if (entryNames == null) {
- entryNames = Sets.newHashSet();
+ entryNames = new HashSet<>();
ZipFile zipFile = new ZipFile(jarFile);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
diff --git a/test-runner/src/android/test/DatabaseTestUtils.java b/test-runner/src/android/test/DatabaseTestUtils.java
index 42ef48b38a24..1980d921664d 100644
--- a/test-runner/src/android/test/DatabaseTestUtils.java
+++ b/test-runner/src/android/test/DatabaseTestUtils.java
@@ -16,11 +16,10 @@
package android.test;
-import com.google.android.collect.Sets;
-
import android.database.sqlite.SQLiteDatabase;
import android.database.Cursor;
+import java.util.HashSet;
import java.util.Set;
/**
@@ -42,7 +41,7 @@ public class DatabaseTestUtils {
}
private static Set<String> getSchemaSet(SQLiteDatabase db) {
- Set<String> schemaSet = Sets.newHashSet();
+ Set<String> schemaSet = new HashSet<>();
Cursor entityCursor = db.rawQuery("SELECT sql FROM sqlite_master", null);
try {
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 3abf38f3b224..0b77c0062dfb 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -16,8 +16,6 @@
package android.test;
-import com.google.android.collect.Lists;
-
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
@@ -38,6 +36,7 @@ import android.os.Handler;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.List;
@@ -55,7 +54,7 @@ public class IsolatedContext extends ContextWrapper {
private ContentResolver mResolver;
private final MockAccountManager mMockAccountManager;
- private List<Intent> mBroadcastIntents = Lists.newArrayList();
+ private List<Intent> mBroadcastIntents = new ArrayList<>();
public IsolatedContext(
ContentResolver resolver, Context targetContext) {
@@ -67,7 +66,7 @@ public class IsolatedContext extends ContextWrapper {
/** Returns the list of intents that were broadcast since the last call to this method. */
public List<Intent> getAndClearBroadcastIntents() {
List<Intent> intents = mBroadcastIntents;
- mBroadcastIntents = Lists.newArrayList();
+ mBroadcastIntents = new ArrayList<>();
return intents;
}
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index 36786b09df26..fd3332154611 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -16,20 +16,24 @@
package android.test;
-import com.google.android.collect.Sets;
-
import android.content.Context;
import android.content.ContextWrapper;
import android.content.ContentProvider;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
-import android.os.FileUtils;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.EnumSet;
+import java.util.HashSet;
import java.util.Set;
/**
@@ -48,8 +52,8 @@ public class RenamingDelegatingContext extends ContextWrapper {
private File mCacheDir;
private final Object mSync = new Object();
- private Set<String> mDatabaseNames = Sets.newHashSet();
- private Set<String> mFileNames = Sets.newHashSet();
+ private Set<String> mDatabaseNames = new HashSet<>();
+ private Set<String> mFileNames = new HashSet<>();
public static <T extends ContentProvider> T providerWithRenamedContext(
Class<T> contentProvider, Context c, String filePrefix)
@@ -237,10 +241,14 @@ public class RenamingDelegatingContext extends ContextWrapper {
Log.w("RenamingDelegatingContext", "Unable to create cache directory");
return null;
}
- FileUtils.setPermissions(
- mCacheDir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
+ try {
+ // Give the directory all possible permissions.
+ Files.setPosixFilePermissions(mCacheDir.toPath(),
+ EnumSet.allOf(PosixFilePermission.class));
+ } catch (IOException e) {
+ Log.e("RenamingDelegatingContext",
+ "Could not set permissions of test cacheDir", e);
+ }
}
}
return mCacheDir;
diff --git a/test-runner/src/android/test/TestCaseUtil.java b/test-runner/src/android/test/TestCaseUtil.java
index c46d403f1350..dc053a2359a0 100644
--- a/test-runner/src/android/test/TestCaseUtil.java
+++ b/test-runner/src/android/test/TestCaseUtil.java
@@ -16,8 +16,7 @@
package android.test;
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
@@ -44,7 +43,7 @@ public class TestCaseUtil {
@SuppressWarnings("unchecked")
public static List<String> getTestCaseNames(Test test, boolean flatten) {
List<Test> tests = (List<Test>) getTests(test, flatten);
- List<String> testCaseNames = Lists.newArrayList();
+ List<String> testCaseNames = new ArrayList<>();
for (Test aTest : tests) {
testCaseNames.add(getTestName(aTest));
}
@@ -57,7 +56,7 @@ public class TestCaseUtil {
private static List<? extends Test> getTests(Test test, boolean flatten,
Set<Class<?>> seen) {
- List<Test> testCases = Lists.newArrayList();
+ List<Test> testCases = new ArrayList<>();
if (test != null) {
Test workingTest = null;
diff --git a/test-runner/src/android/test/TestRunner.java b/test-runner/src/android/test/TestRunner.java
index beecc6fdd9de..ff045c3b4072 100644
--- a/test-runner/src/android/test/TestRunner.java
+++ b/test-runner/src/android/test/TestRunner.java
@@ -32,7 +32,6 @@ import junit.framework.TestSuite;
import junit.framework.TestListener;
import junit.framework.Test;
import junit.framework.TestResult;
-import com.google.android.collect.Lists;
/**
* Support class that actually runs a test. Android uses this class,
@@ -54,7 +53,7 @@ public class TestRunner implements PerformanceTestCase.Intermediates {
private int mMode = REGRESSION;
- private List<Listener> mListeners = Lists.newArrayList();
+ private List<Listener> mListeners = new ArrayList<>();
private int mPassed;
private int mFailed;
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index d8e097756c66..a70152c8b732 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -23,8 +23,7 @@ import android.content.IContentProvider;
import android.database.ContentObserver;
import android.net.Uri;
-import com.google.android.collect.Maps;
-
+import java.util.HashMap;
import java.util.Map;
/**
@@ -67,7 +66,7 @@ public class MockContentResolver extends ContentResolver {
*/
public MockContentResolver(Context context) {
super(context);
- mProviders = Maps.newHashMap();
+ mProviders = new HashMap<>();
}
/**
diff --git a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
index 3b920cff30e0..cf6936bee643 100644
--- a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
+++ b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
@@ -21,7 +21,6 @@ import android.test.AndroidTestRunner;
import android.test.TestCaseUtil;
import android.util.Log;
import com.android.internal.util.Predicate;
-import com.google.android.collect.Lists;
import static android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME;
import static android.test.suitebuilder.TestPredicates.REJECT_SUPPRESSED;
@@ -69,7 +68,7 @@ public class TestSuiteBuilder {
public TestSuiteBuilder(String name, ClassLoader classLoader) {
this.suiteName = name;
this.testGrouping.setClassLoader(classLoader);
- this.testCases = Lists.newArrayList();
+ this.testCases = new ArrayList<>();
addRequirements(REJECT_SUPPRESSED);
}
diff --git a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
index 05747049dd21..67235480fa6d 100644
--- a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
+++ b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
@@ -19,8 +19,7 @@ package android.test;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
import junit.framework.TestCase;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
@@ -140,7 +139,7 @@ public class AndroidTestRunnerTest extends TestCase {
public void testSetTestClassWithTestSuiteProvider() throws Exception {
mAndroidTestRunner.setTestClassName(SampleTestSuiteProvider.class.getName(), null);
List<TestCase> testCases = mAndroidTestRunner.getTestCases();
- List<String> testNames = Lists.newArrayList();
+ List<String> testNames = new ArrayList<>();
for (TestCase testCase : testCases) {
testNames.add(testCase.getName());
}
@@ -152,7 +151,7 @@ public class AndroidTestRunnerTest extends TestCase {
public void testSetTestClassWithTestSuite() throws Exception {
mAndroidTestRunner.setTestClassName(SampleTestSuite.class.getName(), null);
List<TestCase> testCases = mAndroidTestRunner.getTestCases();
- List<String> testNames = Lists.newArrayList();
+ List<String> testNames = new ArrayList<>();
for (TestCase testCase : testCases) {
testNames.add(testCase.getName());
}
@@ -163,7 +162,7 @@ public class AndroidTestRunnerTest extends TestCase {
String testMethodName = "testTwo";
mAndroidTestRunner.setTestClassName(TwoTestTestCase.class.getName(), testMethodName);
List<TestCase> testCases = mAndroidTestRunner.getTestCases();
- List<String> testNames = Lists.newArrayList();
+ List<String> testNames = new ArrayList<>();
for (TestCase testCase : testCases) {
testNames.add(testCase.getName());
}
@@ -255,7 +254,7 @@ public class AndroidTestRunnerTest extends TestCase {
}
private static class TestListenerStub implements TestListener {
- List<String> testNames = Lists.newArrayList();
+ List<String> testNames = new ArrayList<>();
public void addError(Test test, Throwable t) {
}
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index ceb0135727de..cc792cc749d9 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -45,6 +45,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.PendingIntent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.content.Context;
@@ -66,8 +67,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectivityManagerTest {
@@ -296,6 +295,43 @@ public class ConnectivityManagerTest {
manager.requestNetwork(request, callback);
}
+ @Test
+ public void testArgumentValidation() throws Exception {
+ ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+
+ NetworkRequest request = mock(NetworkRequest.class);
+ NetworkCallback callback = mock(NetworkCallback.class);
+ Handler handler = mock(Handler.class);
+ NetworkCallback nullCallback = null;
+ PendingIntent nullIntent = null;
+
+ mustFail(() -> { manager.requestNetwork(null, callback); });
+ mustFail(() -> { manager.requestNetwork(request, nullCallback); });
+ mustFail(() -> { manager.requestNetwork(request, callback, null); });
+ mustFail(() -> { manager.requestNetwork(request, callback, -1); });
+ mustFail(() -> { manager.requestNetwork(request, nullIntent); });
+
+ mustFail(() -> { manager.registerNetworkCallback(null, callback, handler); });
+ mustFail(() -> { manager.registerNetworkCallback(request, null, handler); });
+ mustFail(() -> { manager.registerNetworkCallback(request, callback, null); });
+ mustFail(() -> { manager.registerNetworkCallback(request, nullIntent); });
+
+ mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); });
+ mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); });
+
+ mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); });
+ mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); });
+ mustFail(() -> { manager.releaseNetworkRequest(nullIntent); });
+ }
+
+ static void mustFail(Runnable fn) {
+ try {
+ fn.run();
+ fail();
+ } catch (Exception expected) {
+ }
+ }
+
static Message makeMessage(NetworkRequest req, int messageType) {
Bundle bundle = new Bundle();
bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 517327882bfa..3c0b8aa7c59d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -43,6 +43,7 @@ import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
+import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.IpPrefix;
@@ -2981,7 +2982,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
networkCallbacks.add(networkCallback);
}
fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
- } catch (IllegalArgumentException expected) {}
+ } catch (TooManyRequestsException expected) {}
for (NetworkCallback networkCallback : networkCallbacks) {
mCm.unregisterNetworkCallback(networkCallback);
}
@@ -2994,7 +2995,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
networkCallbacks.add(networkCallback);
}
fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
- } catch (IllegalArgumentException expected) {}
+ } catch (TooManyRequestsException expected) {}
for (NetworkCallback networkCallback : networkCallbacks) {
mCm.unregisterNetworkCallback(networkCallback);
}
@@ -3010,7 +3011,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
fail("Registering " + MAX_REQUESTS +
" PendingIntent NetworkRequests did not throw exception");
- } catch (IllegalArgumentException expected) {}
+ } catch (TooManyRequestsException expected) {}
for (PendingIntent pendingIntent : pendingIntents) {
mCm.unregisterNetworkCallback(pendingIntent);
}
@@ -3025,7 +3026,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
fail("Registering " + MAX_REQUESTS +
" PendingIntent NetworkCallbacks did not throw exception");
- } catch (IllegalArgumentException expected) {}
+ } catch (TooManyRequestsException expected) {}
for (PendingIntent pendingIntent : pendingIntents) {
mCm.unregisterNetworkCallback(pendingIntent);
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 3172c6ec856a..bc89c0f4f71f 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -56,6 +56,8 @@ import android.support.test.runner.AndroidJUnit4;
import android.telephony.CarrierConfigManager;
import com.android.internal.util.test.BroadcastInterceptingContext;
+import com.android.server.connectivity.tethering.OffloadHardwareInterface;
+import com.android.server.connectivity.tethering.TetheringDependencies;
import org.junit.After;
import org.junit.Before;
@@ -78,7 +80,9 @@ public class TetheringTest {
@Mock private INetworkStatsService mStatsService;
@Mock private INetworkPolicyManager mPolicyManager;
@Mock private MockableSystemProperties mSystemProperties;
+ @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
@Mock private Resources mResources;
+ @Mock private TetheringDependencies mTetheringDependencies;
@Mock private UsbManager mUsbManager;
@Mock private WifiManager mWifiManager;
@Mock private CarrierConfigManager mCarrierConfigManager;
@@ -138,8 +142,11 @@ public class TetheringTest {
};
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
+ when(mTetheringDependencies.getOffloadHardwareInterface())
+ .thenReturn(mOffloadHardwareInterface);
mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
- mLooper.getLooper(), mSystemProperties);
+ mLooper.getLooper(), mSystemProperties,
+ mTetheringDependencies);
}
@After
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
new file mode 100644
index 000000000000..9fcd1b52b8fe
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TetheringConfigurationTest {
+ @Mock private Context mContext;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private Resources mResources;
+ private Context mMockContext;
+ private boolean mHasTelephonyManager;
+
+ private class MockContext extends BroadcastInterceptingContext {
+ MockContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Resources getResources() { return mResources; }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (Context.TELEPHONY_SERVICE.equals(name)) {
+ return mHasTelephonyManager ? mTelephonyManager : null;
+ }
+ return super.getSystemService(name);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
+ .thenReturn(new String[0]);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
+ .thenReturn(new String[0]);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
+ .thenReturn(new String[]{ "test_wlan\\d" });
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
+ .thenReturn(new String[0]);
+ mMockContext = new MockContext(mContext);
+ }
+
+ @Test
+ public void testDunFromTelephonyManagerMeansDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
+ mHasTelephonyManager = true;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertTrue(cfg.isDunRequired);
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+
+ @Test
+ public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+ mHasTelephonyManager = true;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertFalse(cfg.isDunRequired);
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+
+ @Test
+ public void testDunFromUpstreamConfigMeansDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+ mHasTelephonyManager = false;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertTrue(cfg.isDunRequired);
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+}