Merge "Revert "OMS: fix listener callbacks triggered by changes to target package""
diff --git a/Android.bp b/Android.bp
index 9e8c384..6b61467 100644
--- a/Android.bp
+++ b/Android.bp
@@ -51,6 +51,7 @@
}
subdirs = [
+ "cmds/*",
"core/jni",
"libs/*",
"media/*",
diff --git a/api/current.txt b/api/current.txt
index b218165..bab4a8b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39347,6 +39347,7 @@
method public boolean isInManagedCall();
method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
+ method public boolean isTtySupported();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
@@ -40110,6 +40111,7 @@
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -40135,7 +40137,7 @@
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
- method public boolean isTtyModeSupported();
+ method public deprecated boolean isTtyModeSupported();
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
diff --git a/api/system-current.txt b/api/system-current.txt
index 928346b..4ecaec6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -43531,8 +43531,8 @@
}
public class TelephonyManager {
- method public void answerRingingCall();
- method public void call(java.lang.String, java.lang.String);
+ method public deprecated void answerRingingCall();
+ method public deprecated void call(java.lang.String, java.lang.String);
method public boolean canChangeDtmfToneLength();
method public int checkCarrierPrivilegesForPackage(java.lang.String);
method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
@@ -43542,7 +43542,7 @@
method public boolean disableDataConnectivity();
method public boolean enableDataConnectivity();
method public void enableVideoCalling(boolean);
- method public boolean endCall();
+ method public deprecated boolean endCall();
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method public int getCallState();
@@ -43583,6 +43583,7 @@
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -43617,7 +43618,7 @@
method public boolean isRadioOn();
method public boolean isRinging();
method public boolean isSmsCapable();
- method public boolean isTtyModeSupported();
+ method public deprecated boolean isTtyModeSupported();
method public boolean isVideoCallingEnabled();
method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean isVoiceCapable();
@@ -43642,7 +43643,7 @@
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
- method public void silenceRinger();
+ method public deprecated void silenceRinger();
method public boolean supplyPin(java.lang.String);
method public int[] supplyPinReportResult(java.lang.String);
method public boolean supplyPuk(java.lang.String, java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 1dfca8e..f2490a5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -39569,6 +39569,7 @@
method public boolean isInManagedCall();
method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
+ method public boolean isTtySupported();
method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
method public void placeCall(android.net.Uri, android.os.Bundle);
method public void registerPhoneAccount(android.telecom.PhoneAccount);
@@ -40332,6 +40333,7 @@
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -40357,7 +40359,7 @@
method public boolean isHearingAidCompatibilitySupported();
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
- method public boolean isTtyModeSupported();
+ method public deprecated boolean isTtyModeSupported();
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
diff --git a/cmds/am/Android.bp b/cmds/am/Android.bp
new file mode 100644
index 0000000..7eb4edf
--- /dev/null
+++ b/cmds/am/Android.bp
@@ -0,0 +1,11 @@
+// Copyright 2008 The Android Open Source Project
+//
+
+cc_library_host_static {
+ name: "libinstrumentation",
+ srcs: ["**/*.proto"],
+ proto: {
+ type: "full",
+ export_proto_headers: true,
+ },
+}
diff --git a/cmds/am/Android.mk b/cmds/am/Android.mk
index 5586dd4..9411c32 100644
--- a/cmds/am/Android.mk
+++ b/cmds/am/Android.mk
@@ -16,14 +16,3 @@
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
-
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- $(call all-proto-files-under, proto)
-LOCAL_MODULE := libinstrumentation
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,libinstrumentation,HOST,,,)/proto/$(LOCAL_PATH)/proto
-include $(BUILD_HOST_STATIC_LIBRARY)
-
diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp
new file mode 100644
index 0000000..2b7963a
--- /dev/null
+++ b/cmds/hid/Android.bp
@@ -0,0 +1 @@
+subdirs = ["jni"]
diff --git a/cmds/hid/jni/Android.bp b/cmds/hid/jni/Android.bp
new file mode 100644
index 0000000..05c3099
--- /dev/null
+++ b/cmds/hid/jni/Android.bp
@@ -0,0 +1,18 @@
+cc_library_shared {
+ name: "libhidcommand_jni",
+
+ srcs: ["com_android_commands_hid_Device.cpp"],
+
+ shared_libs: [
+ "libandroid_runtime",
+ "liblog",
+ "libnativehelper",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
diff --git a/cmds/hid/jni/Android.mk b/cmds/hid/jni/Android.mk
deleted file mode 100644
index d41d39d..0000000
--- a/cmds/hid/jni/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- com_android_commands_hid_Device.cpp
-
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- frameworks/base/core/jni
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid_runtime \
- liblog \
- libnativehelper \
- libutils
-
-LOCAL_MODULE := libhidcommand_jni
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
index 524db14..f415f8f 100644
--- a/cmds/idmap/create.cpp
+++ b/cmds/idmap/create.cpp
@@ -104,13 +104,17 @@
}
}
- uint32_t cached_target_crc, cached_overlay_crc;
+ uint32_t version, cached_target_crc, cached_overlay_crc;
String8 cached_target_path, cached_overlay_path;
- if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc,
+ if (!ResTable::getIdmapInfo(buf, N, &version, &cached_target_crc, &cached_overlay_crc,
&cached_target_path, &cached_overlay_path)) {
return true;
}
+ if (version != ResTable::IDMAP_CURRENT_VERSION) {
+ return true;
+ }
+
if (cached_target_path != target_apk_path) {
return true;
}
diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp
index 154cb25..20005e27 100644
--- a/cmds/idmap/inspect.cpp
+++ b/cmds/idmap/inspect.cpp
@@ -284,7 +284,9 @@
if (err != NO_ERROR) {
return err;
}
- print("", "entry", data32, "%s/%s", type.string(), name.string());
+ if (data32 != ResTable_type::NO_ENTRY) {
+ print("", "entry", data32, "%s/%s", type.string(), name.string());
+ }
}
}
diff --git a/cmds/interrupter/Android.bp b/cmds/interrupter/Android.bp
new file mode 100644
index 0000000..d68e7fe
--- /dev/null
+++ b/cmds/interrupter/Android.bp
@@ -0,0 +1,11 @@
+cc_library_shared {
+ name: "interrupter",
+ host_supported: true,
+ srcs: ["interrupter.c"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+}
diff --git a/cmds/interrupter/Android.mk b/cmds/interrupter/Android.mk
deleted file mode 100644
index 97a96bf..0000000
--- a/cmds/interrupter/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- interrupter.c
-LOCAL_MODULE := interrupter
-LOCAL_MODULE_TAGS := eng tests
-LOCAL_LDFLAGS := -ldl
-LOCAL_CFLAGS := -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- interrupter.c
-LOCAL_MODULE := interrupter
-LOCAL_MODULE_TAGS := eng tests
-LOCAL_LDFLAGS := -ldl
-LOCAL_CFLAGS := -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 6f326de..80554ff 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -961,7 +961,7 @@
// TODO(adamlesinski): Make this accept more than just overlay directories.
final void applyNewResourceDirsLocked(@NonNull final String baseCodePath,
- @NonNull final String[] newResourceDirs) {
+ @Nullable final String[] newResourceDirs) {
try {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
"ResourcesManager#applyNewResourceDirsLocked");
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 611531c..faab000 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -125,7 +125,7 @@
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothA2dpSink mService;
+ private volatile IBluetoothA2dpSink mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -240,15 +240,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -279,15 +280,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -297,15 +299,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -315,15 +318,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -333,16 +337,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -359,16 +363,16 @@
*/
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
if (VDBG) log("getAudioConfig(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getAudioConfig(device);
+ return service.getAudioConfig(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return null;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -389,20 +393,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -421,16 +425,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
}
@@ -442,16 +446,16 @@
* @param device BluetoothDevice device
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothA2dpSink service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.isA2dpPlaying(device);
+ return service.isA2dpPlaying(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -485,7 +489,6 @@
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
-
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
BluetoothA2dpSink.this);
@@ -502,15 +505,11 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index 7528aa9..5f0e5d9 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -81,7 +81,7 @@
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothAvrcpController mService;
+ private volatile IBluetoothAvrcpController mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -179,15 +179,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -197,15 +198,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -215,16 +217,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -236,9 +238,10 @@
public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getPlayerSettings");
BluetoothAvrcpPlayerSettings settings = null;
- if (mService != null && isEnabled()) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled()) {
try {
- settings = mService.getPlayerSettings(device);
+ settings = service.getPlayerSettings(device);
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getMetadata() " + e);
return null;
@@ -253,15 +256,16 @@
*/
public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
- if (mService != null && isEnabled()) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.setPlayerApplicationSetting(plAppSetting);
+ return service.setPlayerApplicationSetting(plAppSetting);
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e);
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -272,23 +276,23 @@
public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
+ keyState);
- if (mService != null && isEnabled()) {
+ final IBluetoothAvrcpController service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.sendGroupNavigationCmd(device, keyCode, keyState);
+ service.sendGroupNavigationCmd(device, keyCode, keyState);
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e);
return;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
-
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
BluetoothAvrcpController.this);
@@ -305,15 +309,11 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 3ab2c4a..d982bb7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -712,7 +712,7 @@
* getService() called.
* TODO: Unify implementation of sService amongst BluetoothFoo API's
*/
- private static IBluetooth sService;
+ private static volatile IBluetooth sService;
private final String mAddress;
@@ -839,12 +839,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public String getName() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
return null;
}
try {
- return sService.getRemoteName(this);
+ return service.getRemoteName(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -859,12 +860,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getType() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
return DEVICE_TYPE_UNKNOWN;
}
try {
- return sService.getRemoteType(this);
+ return service.getRemoteType(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -879,12 +881,13 @@
* @hide
*/
public String getAlias() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
return null;
}
try {
- return sService.getRemoteAlias(this);
+ return service.getRemoteAlias(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -902,12 +905,13 @@
* @hide
*/
public boolean setAlias(String alias) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
return false;
}
try {
- return sService.setRemoteAlias(this, alias);
+ return service.setRemoteAlias(this, alias);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -942,12 +946,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getBatteryLevel() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
return BATTERY_LEVEL_UNKNOWN;
}
try {
- return sService.getBatteryLevel(this);
+ return service.getBatteryLevel(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -966,7 +971,8 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
return false;
}
@@ -974,7 +980,7 @@
Log.i(TAG, "createBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return sService.createBond(this, TRANSPORT_AUTO);
+ return service.createBond(this, TRANSPORT_AUTO);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -998,7 +1004,8 @@
* @hide
*/
public boolean createBond(int transport) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
return false;
}
@@ -1009,7 +1016,7 @@
Log.i(TAG, "createBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return sService.createBond(this, transport);
+ return service.createBond(this, transport);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1035,8 +1042,13 @@
* @hide
*/
public boolean createBondOutOfBand(int transport, OobData oobData) {
+ final IBluetooth service = sService;
+ if (service == null) {
+ Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
+ return false;
+ }
try {
- return sService.createBondOutOfBand(this, transport, oobData);
+ return service.createBondOutOfBand(this, transport, oobData);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1045,8 +1057,13 @@
/** @hide */
public boolean isBondingInitiatedLocally() {
+ final IBluetooth service = sService;
+ if (service == null) {
+ Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
+ return false;
+ }
try {
- return sService.isBondingInitiatedLocally(this);
+ return service.isBondingInitiatedLocally(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1082,7 +1099,8 @@
* @hide
*/
public boolean cancelBondProcess() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
return false;
}
@@ -1090,7 +1108,7 @@
Log.i(TAG, "cancelBondProcess() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return sService.cancelBondProcess(this);
+ return service.cancelBondProcess(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1108,7 +1126,8 @@
* @hide
*/
public boolean removeBond() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
return false;
}
@@ -1116,7 +1135,7 @@
Log.i(TAG, "removeBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return sService.removeBond(this);
+ return service.removeBond(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1134,19 +1153,15 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getBondState() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot get bond state");
return BOND_NONE;
}
try {
- return sService.getBondState(this);
+ return service.getBondState(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
- } catch (NullPointerException npe) {
- // Handle case where bluetooth service proxy
- // is already null.
- Log.e(TAG, "NullPointerException for getBondState() of device ("
- + getAddress() + ")", npe);
}
return BOND_NONE;
}
@@ -1160,12 +1175,13 @@
*/
@SystemApi
public boolean isConnected() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
// BT is not enabled, we cannot be connected.
return false;
}
try {
- return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
+ return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
@@ -1182,12 +1198,13 @@
*/
@SystemApi
public boolean isEncrypted() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
// BT is not enabled, we cannot be connected.
return false;
}
try {
- return sService.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
+ return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
@@ -1201,12 +1218,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothClass getBluetoothClass() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
return null;
}
try {
- int classInt = sService.getRemoteClass(this);
+ int classInt = service.getRemoteClass(this);
if (classInt == BluetoothClass.ERROR) return null;
return new BluetoothClass(classInt);
} catch (RemoteException e) {
@@ -1227,12 +1245,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public ParcelUuid[] getUuids() {
- if (sService == null || !isBluetoothEnabled()) {
+ final IBluetooth service = sService;
+ if (service == null || !isBluetoothEnabled()) {
Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
return null;
}
try {
- return sService.getRemoteUuids(this);
+ return service.getRemoteUuids(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1254,7 +1273,7 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean fetchUuidsWithSdp() {
- IBluetooth service = sService;
+ final IBluetooth service = sService;
if (service == null || !isBluetoothEnabled()) {
Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
return false;
@@ -1289,12 +1308,13 @@
*/
/** @hide */
public boolean sdpSearch(ParcelUuid uuid) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
return false;
}
try {
- return sService.sdpSearch(this, uuid);
+ return service.sdpSearch(this, uuid);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1308,12 +1328,13 @@
* @return true pin has been set false for error
*/
public boolean setPin(byte[] pin) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
return false;
}
try {
- return sService.setPin(this, true, pin.length, pin);
+ return service.setPin(this, true, pin.length, pin);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1337,12 +1358,13 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
public boolean setPairingConfirmation(boolean confirm) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
return false;
}
try {
- return sService.setPairingConfirmation(this, confirm);
+ return service.setPairingConfirmation(this, confirm);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1361,12 +1383,13 @@
/** @hide */
public boolean cancelPairingUserInput() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
Log.e(TAG, "BT not enabled. Cannot create pairing user input");
return false;
}
try {
- return sService.cancelBondProcess(this);
+ return service.cancelBondProcess(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1400,11 +1423,12 @@
* @hide
*/
public int getPhonebookAccessPermission() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return sService.getPhonebookAccessPermission(this);
+ return service.getPhonebookAccessPermission(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1421,11 +1445,12 @@
* @hide
*/
public boolean setPhonebookAccessPermission(int value) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return false;
}
try {
- return sService.setPhonebookAccessPermission(this, value);
+ return service.setPhonebookAccessPermission(this, value);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1440,11 +1465,12 @@
* @hide
*/
public int getMessageAccessPermission() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return sService.getMessageAccessPermission(this);
+ return service.getMessageAccessPermission(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1461,11 +1487,12 @@
* @hide
*/
public boolean setMessageAccessPermission(int value) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return false;
}
try {
- return sService.setMessageAccessPermission(this, value);
+ return service.setMessageAccessPermission(this, value);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1480,11 +1507,12 @@
* @hide
*/
public int getSimAccessPermission() {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return sService.getSimAccessPermission(this);
+ return service.getSimAccessPermission(this);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1501,11 +1529,12 @@
* @hide
*/
public boolean setSimAccessPermission(int value) {
- if (sService == null) {
+ final IBluetooth service = sService;
+ if (service == null) {
return false;
}
try {
- return sService.setSimAccessPermission(this, value);
+ return service.setSimAccessPermission(this, value);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index be1ce63..85550c7 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -306,7 +306,7 @@
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothHeadset mService;
+ private volatile IBluetoothHeadset mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -418,15 +418,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -457,15 +458,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -475,15 +477,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -493,15 +496,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -511,15 +515,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -540,19 +545,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -571,15 +577,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
}
@@ -605,14 +612,15 @@
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.startVoiceRecognition(device);
+ return service.startVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -627,14 +635,15 @@
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.stopVoiceRecognition(device);
+ return service.stopVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -648,14 +657,15 @@
*/
public boolean isAudioConnected(BluetoothDevice device) {
if (VDBG) log("isAudioConnected()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.isAudioConnected(device);
+ return service.isAudioConnected(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -674,14 +684,15 @@
*/
public int getBatteryUsageHint(BluetoothDevice device) {
if (VDBG) log("getBatteryUsageHint()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getBatteryUsageHint(device);
+ return service.getBatteryUsageHint(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return -1;
}
@@ -704,9 +715,10 @@
*/
public boolean acceptIncomingConnect(BluetoothDevice device) {
if (DBG) log("acceptIncomingConnect");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.acceptIncomingConnect(device);
+ return service.acceptIncomingConnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -724,9 +736,10 @@
*/
public boolean rejectIncomingConnect(BluetoothDevice device) {
if (DBG) log("rejectIncomingConnect");
- if (mService != null) {
+ final IBluetoothHeadset service = mService;
+ if (service != null) {
try {
- return mService.rejectIncomingConnect(device);
+ return service.rejectIncomingConnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -745,9 +758,10 @@
*/
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
- if (mService != null && !isDisabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && !isDisabled()) {
try {
- return mService.getAudioState(device);
+ return service.getAudioState(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -770,9 +784,10 @@
*/
public void setAudioRouteAllowed(boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.setAudioRouteAllowed(allowed);
+ service.setAudioRouteAllowed(allowed);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -790,9 +805,10 @@
*/
public boolean getAudioRouteAllowed() {
if (VDBG) log("getAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getAudioRouteAllowed();
+ return service.getAudioRouteAllowed();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -812,9 +828,10 @@
*/
public void setForceScoAudio(boolean forced) {
if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.setForceScoAudio(forced);
+ service.setForceScoAudio(forced);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -834,14 +851,15 @@
*/
public boolean isAudioOn() {
if (VDBG) log("isAudioOn()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.isAudioOn();
+ return service.isAudioOn();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -855,9 +873,10 @@
* @hide
*/
public boolean connectAudio() {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.connectAudio();
+ return service.connectAudio();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -877,9 +896,10 @@
* @hide
*/
public boolean disconnectAudio() {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.disconnectAudio();
+ return service.disconnectAudio();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -903,9 +923,10 @@
*/
public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
if (DBG) log("startScoUsingVirtualVoiceCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.startScoUsingVirtualVoiceCall(device);
+ return service.startScoUsingVirtualVoiceCall(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -926,9 +947,10 @@
*/
public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
if (DBG) log("stopScoUsingVirtualVoiceCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.stopScoUsingVirtualVoiceCall(device);
+ return service.stopScoUsingVirtualVoiceCall(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -949,9 +971,10 @@
*/
public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
int type) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.phoneStateChanged(numActive, numHeld, callState, number, type);
+ service.phoneStateChanged(numActive, numHeld, callState, number, type);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -968,9 +991,10 @@
*/
public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
String number, int type) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.clccResponse(index, direction, status, mode, mpty, number, type);
+ service.clccResponse(index, direction, status, mode, mpty, number, type);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1006,14 +1030,15 @@
if (command == null) {
throw new IllegalArgumentException("command is null");
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.sendVendorSpecificResultCode(device, command, arg);
+ return service.sendVendorSpecificResultCode(device, command, arg);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return false;
@@ -1027,9 +1052,10 @@
* @hide
*/
public boolean enableWBS() {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.enableWBS();
+ return service.enableWBS();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1048,9 +1074,10 @@
* @hide
*/
public boolean disableWBS() {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.disableWBS();
+ return service.disableWBS();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1083,9 +1110,10 @@
* @hide
*/
public void bindResponse(int indId, boolean indStatus) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadset service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.bindResponse(indId, indStatus);
+ service.bindResponse(indId, indStatus);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1115,20 +1143,15 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
private boolean isDisabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_OFF;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 7ed2d2e..031287f 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -76,8 +76,8 @@
* Intent sent whenever audio state changes.
*
* <p>It includes two mandatory extras:
- * {@link BluetoothProfile.EXTRA_STATE},
- * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE},
+ * {@link BluetoothProfile#EXTRA_STATE},
+ * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
* with possible values:
* {@link #STATE_AUDIO_CONNECTING},
* {@link #STATE_AUDIO_CONNECTED},
@@ -367,7 +367,7 @@
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothHeadsetClient mService;
+ private volatile IBluetoothHeadsetClient mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -478,15 +478,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -499,15 +500,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -519,15 +521,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -541,15 +544,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -562,15 +566,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -581,19 +586,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -602,15 +608,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
}
@@ -627,14 +634,15 @@
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.startVoiceRecognition(device);
+ return service.startVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -651,14 +659,15 @@
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.stopVoiceRecognition(device);
+ return service.stopVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -670,14 +679,15 @@
*/
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getCurrentCalls(device);
+ return service.getCurrentCalls(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -689,14 +699,15 @@
*/
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getCurrentAgEvents(device);
+ return service.getCurrentAgEvents(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -711,14 +722,15 @@
*/
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.acceptCall(device, flag);
+ return service.acceptCall(device, flag);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -731,14 +743,15 @@
*/
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.holdCall(device);
+ return service.holdCall(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -755,14 +768,15 @@
*/
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.rejectCall(device);
+ return service.rejectCall(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -784,14 +798,15 @@
*/
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.terminateCall(device, call);
+ return service.terminateCall(device, call);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -811,14 +826,15 @@
*/
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.enterPrivateMode(device, index);
+ return service.enterPrivateMode(device, index);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -837,14 +853,15 @@
*/
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.explicitCallTransfer(device);
+ return service.explicitCallTransfer(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -859,14 +876,15 @@
*/
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.dial(device, number);
+ return service.dial(device, number);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -882,14 +900,15 @@
*/
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.sendDTMF(device, code);
+ return service.sendDTMF(device, code);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -907,14 +926,15 @@
*/
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
if (DBG) log("getLastVoiceTagNumber()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getLastVoiceTagNumber(device);
+ return service.getLastVoiceTagNumber(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -925,9 +945,10 @@
*/
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getAudioState(device);
+ return service.getAudioState(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -947,9 +968,10 @@
*/
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.setAudioRouteAllowed(device, allowed);
+ service.setAudioRouteAllowed(device, allowed);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -968,9 +990,10 @@
*/
public boolean getAudioRouteAllowed(BluetoothDevice device) {
if (VDBG) log("getAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getAudioRouteAllowed(device);
+ return service.getAudioRouteAllowed(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -991,9 +1014,10 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean connectAudio(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.connectAudio(device);
+ return service.connectAudio(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1014,9 +1038,10 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean disconnectAudio(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.disconnectAudio(device);
+ return service.disconnectAudio(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1034,9 +1059,10 @@
* @return bundle of AG features; null if no service or AG not connected
*/
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getCurrentAgFeatures(device);
+ return service.getCurrentAgFeatures(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1048,7 +1074,7 @@
}
- private ServiceConnection mConnection = new ServiceConnection() {
+ private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
@@ -1071,15 +1097,11 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index dc5f381..57a0197 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -176,9 +176,10 @@
BluetoothHealthAppConfiguration config =
new BluetoothHealthAppConfiguration(name, dataType, role, channelType);
- if (mService != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null) {
try {
- result = mService.registerAppConfiguration(config, wrapper);
+ result = service.registerAppConfiguration(config, wrapper);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -200,9 +201,10 @@
*/
public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
boolean result = false;
- if (mService != null && isEnabled() && config != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && config != null) {
try {
- result = mService.unregisterAppConfiguration(config);
+ result = service.unregisterAppConfiguration(config);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -228,9 +230,10 @@
*/
public boolean connectChannelToSource(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
- if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && isValidDevice(device) && config != null) {
try {
- return mService.connectChannelToSource(device, config);
+ return service.connectChannelToSource(device, config);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -256,9 +259,10 @@
*/
public boolean connectChannelToSink(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int channelType) {
- if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && isValidDevice(device) && config != null) {
try {
- return mService.connectChannelToSink(device, config, channelType);
+ return service.connectChannelToSink(device, config, channelType);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -284,9 +288,10 @@
*/
public boolean disconnectChannel(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int channelId) {
- if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && isValidDevice(device) && config != null) {
try {
- return mService.disconnectChannel(device, config, channelId);
+ return service.disconnectChannel(device, config, channelId);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -312,9 +317,10 @@
*/
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
- if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && isValidDevice(device) && config != null) {
try {
- return mService.getMainChannelFd(device, config);
+ return service.getMainChannelFd(device, config);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -341,9 +347,10 @@
*/
@Override
public int getConnectionState(BluetoothDevice device) {
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getHealthDeviceConnectionState(device);
+ return service.getHealthDeviceConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -370,15 +377,16 @@
*/
@Override
public List<BluetoothDevice> getConnectedDevices() {
- if (mService != null && isEnabled()) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedHealthDevices();
+ return service.getConnectedHealthDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -401,15 +409,16 @@
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHealth service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getHealthDevicesMatchingConnectionStates(states);
+ return service.getHealthDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -455,7 +464,7 @@
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothHealth mService;
+ private volatile IBluetoothHealth mService;
BluetoothAdapter mAdapter;
/**
@@ -540,11 +549,8 @@
return false;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private boolean checkAppParam(String name, int role, int channelType,
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index a9a9010..3261576 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -222,7 +222,7 @@
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private IBluetoothInputDevice mService;
+ private volatile IBluetoothInputDevice mService;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
@@ -331,15 +331,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -370,15 +371,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -388,15 +390,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -406,15 +409,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -424,15 +428,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -453,19 +458,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -484,15 +490,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
}
@@ -517,18 +524,13 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
-
/**
* Initiate virtual unplug for a HID input device.
*
@@ -540,16 +542,17 @@
*/
public boolean virtualUnplug(BluetoothDevice device) {
if (DBG) log("virtualUnplug(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.virtualUnplug(device);
+ return service.virtualUnplug(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -565,15 +568,16 @@
*/
public boolean getProtocolMode(BluetoothDevice device) {
if (VDBG) log("getProtocolMode(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getProtocolMode(device);
+ return service.getProtocolMode(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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -588,15 +592,16 @@
*/
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
if (DBG) log("setProtocolMode(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.setProtocolMode(device, protocolMode);
+ return service.setProtocolMode(device, protocolMode);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -615,19 +620,19 @@
public boolean getReport(BluetoothDevice device, byte reportType, byte reportId,
int bufferSize) {
if (VDBG) {
- log(
- "getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
- + "bufferSize=" + bufferSize);
+ log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+ + "bufferSize=" + bufferSize);
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getReport(device, reportType, reportId, bufferSize);
+ return service.getReport(device, reportType, reportId, bufferSize);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -644,15 +649,16 @@
*/
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.setReport(device, reportType, report);
+ return service.setReport(device, reportType, report);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -668,15 +674,16 @@
*/
public boolean sendData(BluetoothDevice device, String report) {
if (DBG) log("sendData(" + device + "), report=" + report);
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.sendData(device, report);
+ return service.sendData(device, report);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -691,15 +698,16 @@
*/
public boolean getIdleTime(BluetoothDevice device) {
if (DBG) log("getIdletime(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getIdleTime(device);
+ return service.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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -715,15 +723,16 @@
*/
public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothInputDevice service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.setIdleTime(device, idleTime);
+ return service.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");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 15303dc..37f0427 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -113,7 +113,7 @@
private ServiceListener mServiceListener;
- private IBluetoothInputHost mService;
+ private volatile IBluetoothInputHost mService;
private BluetoothAdapter mAdapter;
@@ -202,24 +202,18 @@
}
};
- private ServiceConnection mConnection = new ServiceConnection() {
-
+ private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d(TAG, "onServiceConnected()");
-
mService = IBluetoothInputHost.Stub.asInterface(service);
-
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
BluetoothInputHost.this);
}
}
-
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, "onServiceDisconnected()");
-
mService = null;
-
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
}
@@ -291,9 +285,10 @@
public List<BluetoothDevice> getConnectedDevices() {
Log.v(TAG, "getConnectedDevices()");
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -311,9 +306,10 @@
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -331,9 +327,10 @@
public int getConnectionState(BluetoothDevice device) {
Log.v(TAG, "getConnectionState(): device=" + device);
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -370,13 +367,14 @@
return false;
}
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
BluetoothHidDeviceAppConfiguration config =
new BluetoothHidDeviceAppConfiguration();
BluetoothHidDeviceCallbackWrapper cbw =
new BluetoothHidDeviceCallbackWrapper(callback);
- result = mService.registerApp(config, sdp, inQos, outQos, cbw);
+ result = service.registerApp(config, sdp, inQos, outQos, cbw);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -403,9 +401,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.unregisterApp(config);
+ result = service.unregisterApp(config);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -427,9 +426,10 @@
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.sendReport(device, id, data);
+ result = service.sendReport(device, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -454,9 +454,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.replyReport(device, type, id, data);
+ result = service.replyReport(device, type, id, data);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -479,9 +480,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.reportError(device, error);
+ result = service.reportError(device, error);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -502,9 +504,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.unplug(device);
+ result = service.unplug(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -526,9 +529,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.connect(device);
+ result = service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -549,9 +553,10 @@
boolean result = false;
- if (mService != null) {
+ final IBluetoothInputHost service = mService;
+ if (service != null) {
try {
- result = mService.disconnect(device);
+ result = service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 26a9106..5b55b23 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -43,7 +43,7 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
- private IBluetoothMap mService;
+ private volatile IBluetoothMap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -161,9 +161,10 @@
*/
public int getState() {
if (VDBG) log("getState()");
- if (mService != null) {
+ final IBluetoothMap service = mService;
+ if (service != null) {
try {
- return mService.getState();
+ return service.getState();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -182,9 +183,10 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- if (mService != null) {
+ final IBluetoothMap service = mService;
+ if (service != null) {
try {
- return mService.getClient();
+ return service.getClient();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -202,9 +204,10 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- if (mService != null) {
+ final IBluetoothMap service = mService;
+ if (service != null) {
try {
- return mService.isConnected(device);
+ return service.isConnected(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -232,15 +235,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -272,15 +276,16 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -291,15 +296,16 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -310,15 +316,16 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -335,19 +342,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -363,15 +371,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
}
@@ -403,13 +412,8 @@
log("Bluetooth is Not enabled");
return false;
}
-
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
-
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 3e0c365..af3b662 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -59,7 +59,7 @@
public static final String EXTRA_SENDER_CONTACT_NAME =
"android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
- private IBluetoothMapClient mService;
+ private volatile IBluetoothMapClient mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -176,9 +176,10 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
- if (mService != null) {
+ final IBluetoothMapClient service = mService;
+ if (service != null) {
try {
- return mService.isConnected(device);
+ return service.isConnected(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -195,9 +196,10 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
- if (mService != null) {
+ final IBluetoothMapClient service = mService;
+ if (service != null) {
try {
- return mService.connect(device);
+ return service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -216,14 +218,15 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -235,15 +238,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<>();
}
@@ -255,15 +259,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<>();
}
@@ -275,15 +280,16 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -298,19 +304,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -326,15 +333,16 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
}
@@ -353,9 +361,10 @@
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
PendingIntent sentIntent, PendingIntent deliveredIntent) {
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+ return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -372,9 +381,10 @@
*/
public boolean getUnreadMessages(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothMapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getUnreadMessages(device);
+ return service.getUnreadMessages(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
@@ -409,12 +419,8 @@
return false;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
-
}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 63e83d2..866b063 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -123,7 +123,7 @@
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private IBluetoothPan mPanService;
+ private volatile IBluetoothPan mPanService;
/**
* Create a BluetoothPan proxy object for interacting with the local
@@ -238,15 +238,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mPanService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mPanService.connect(device);
+ return service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -277,15 +278,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mPanService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mPanService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -295,15 +297,16 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mPanService != null && isEnabled()) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled()) {
try {
- return mPanService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -313,15 +316,16 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mPanService != null && isEnabled()) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled()) {
try {
- return mPanService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -331,25 +335,25 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- if (mPanService != null && isEnabled()
- && isValidDevice(device)) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mPanService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
public void setBluetoothTethering(boolean value) {
if (DBG) log("setBluetoothTethering(" + value + ")");
-
- if (mPanService != null && isEnabled()) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled()) {
try {
- mPanService.setBluetoothTethering(value);
+ service.setBluetoothTethering(value);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
}
@@ -358,10 +362,10 @@
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
-
- if (mPanService != null && isEnabled()) {
+ final IBluetoothPan service = mPanService;
+ if (service != null && isEnabled()) {
try {
- return mPanService.isTetheringOn();
+ return service.isTetheringOn();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
}
@@ -373,7 +377,6 @@
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
-
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.PAN,
BluetoothPan.this);
@@ -390,15 +393,11 @@
};
private boolean isEnabled() {
- if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
- return false;
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) return false;
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 78b7c7b..19f5198 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -68,7 +68,7 @@
public static final String PBAP_STATE_CHANGED_ACTION =
"android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
- private IBluetoothPbap mService;
+ private volatile IBluetoothPbap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -214,9 +214,10 @@
*/
public int getState() {
if (VDBG) log("getState()");
- if (mService != null) {
+ final IBluetoothPbap service = mService;
+ if (service != null) {
try {
- return mService.getState();
+ return service.getState();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -235,9 +236,10 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- if (mService != null) {
+ final IBluetoothPbap service = mService;
+ if (service != null) {
try {
- return mService.getClient();
+ return service.getClient();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -255,9 +257,10 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- if (mService != null) {
+ final IBluetoothPbap service = mService;
+ if (service != null) {
try {
- return mService.isConnected(device);
+ return service.isConnected(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -275,9 +278,10 @@
*/
public boolean disconnect() {
if (DBG) log("disconnect()");
- if (mService != null) {
+ final IBluetoothPbap service = mService;
+ if (service != null) {
try {
- mService.disconnect();
+ service.disconnect();
return true;
} catch (RemoteException e) {
Log.e(TAG, e.toString());
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index b9b372c..00a15f3 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -42,7 +42,7 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
- private IBluetoothPbapClient mService;
+ private volatile IBluetoothPbapClient mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -173,15 +173,16 @@
if (DBG) {
log("connect(" + device + ") for PBAP Client.");
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return false;
@@ -197,16 +198,17 @@
if (DBG) {
log("disconnect(" + device + ")" + new Exception());
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- mService.disconnect(device);
+ service.disconnect(device);
return true;
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return false;
@@ -223,15 +225,16 @@
if (DBG) {
log("getConnectedDevices()");
}
- if (mService != null && isEnabled()) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return new ArrayList<BluetoothDevice>();
@@ -247,15 +250,16 @@
if (DBG) {
log("getDevicesMatchingStates()");
}
- if (mService != null && isEnabled()) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return new ArrayList<BluetoothDevice>();
@@ -271,15 +275,16 @@
if (DBG) {
log("getConnectionState(" + device + ")");
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return BluetoothProfile.STATE_DISCONNECTED;
@@ -321,14 +326,8 @@
return false;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) {
- return false;
- }
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- return true;
- }
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
/**
@@ -339,26 +338,27 @@
* {@link #PRIORITY_OFF},
*
* @param device Paired bluetooth device
- * @param priority
+ * @param priority Priority of this profile
* @return true if priority is set, false on error
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) {
log("setPriority(" + device + ", " + priority + ")");
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return false;
@@ -378,15 +378,16 @@
if (VDBG) {
log("getPriority(" + device + ")");
}
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothPbapClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return PRIORITY_OFF;
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index bcdf493..4848162 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -68,7 +68,7 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
- private IBluetoothSap mService;
+ private volatile IBluetoothSap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
@@ -202,9 +202,10 @@
*/
public int getState() {
if (VDBG) log("getState()");
- if (mService != null) {
+ final IBluetoothSap service = mService;
+ if (service != null) {
try {
- return mService.getState();
+ return service.getState();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -224,9 +225,10 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- if (mService != null) {
+ final IBluetoothSap service = mService;
+ if (service != null) {
try {
- return mService.getClient();
+ return service.getClient();
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -246,9 +248,10 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- if (mService != null) {
+ final IBluetoothSap service = mService;
+ if (service != null) {
try {
- return mService.isConnected(device);
+ return service.isConnected(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -279,15 +282,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.disconnect(device);
+ return service.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -299,15 +303,16 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getConnectedDevices();
+ return service.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -319,15 +324,16 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getDevicesMatchingConnectionStates(states);
+ return service.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>();
}
@@ -339,15 +345,16 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED;
}
@@ -363,19 +370,20 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
try {
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return false;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -388,19 +396,20 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothSap service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getPriority(device);
+ return service.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
return PRIORITY_OFF;
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return PRIORITY_OFF;
}
- private ServiceConnection mConnection = new ServiceConnection() {
+ private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) log("Proxy object connected");
mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
@@ -432,15 +441,8 @@
return false;
}
- private boolean isValidDevice(BluetoothDevice device) {
- if (device == null) {
- return false;
- }
-
- if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- return true;
- }
- return false;
+ private static boolean isValidDevice(BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index ad9e20b9..dd1a61c 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -99,7 +99,9 @@
/**
* Start Bluetooth LE scan with default parameters and no filters. The scan results will be
- * delivered through {@code callback}.
+ * delivered through {@code callback}. For unfiltered scans, scanning is stopped on screen
+ * off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
+ * {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
* <p>
* An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
@@ -116,6 +118,9 @@
/**
* Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
+ * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
+ * resumed when screen is turned on again. To avoid this, do filetered scanning by
+ * using proper {@link ScanFilter}.
* <p>
* An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 35ed424..8fdcba8 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -35,7 +35,7 @@
/**
* Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the
- * least power.
+ * least power. This mode is enforced if the scanning application is not in foreground.
*/
public static final int SCAN_MODE_LOW_POWER = 0;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1bb0fbb..f527f77 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,14 +18,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.ProxyInfo;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
-import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
@@ -504,11 +503,22 @@
}
/**
+ * Make sure this LinkProperties instance contains routes that cover the local subnet
+ * of its link addresses. Add any route that is missing.
+ * @hide
+ */
+ public void ensureDirectlyConnectedRoutes() {
+ for (LinkAddress addr: mLinkAddresses) {
+ addRoute(new RouteInfo(addr, null, mIfaceName));
+ }
+ }
+
+ /**
* Returns all the routes on this link and all the links stacked above it.
* @hide
*/
public List<RouteInfo> getAllRoutes() {
- List<RouteInfo> routes = new ArrayList();
+ List<RouteInfo> routes = new ArrayList<>();
routes.addAll(mRoutes);
for (LinkProperties stacked: mStackedLinks.values()) {
routes.addAll(stacked.getAllRoutes());
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 0780af6..171adc0 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -677,36 +677,33 @@
entry.tag = left.tag[i];
entry.metered = left.metered[i];
entry.roaming = left.roaming[i];
+ entry.rxBytes = left.rxBytes[i];
+ entry.rxPackets = left.rxPackets[i];
+ entry.txBytes = left.txBytes[i];
+ entry.txPackets = left.txPackets[i];
+ entry.operations = left.operations[i];
// find remote row that matches, and subtract
final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
entry.metered, entry.roaming, i);
- if (j == -1) {
- // newly appearing row, return entire value
- entry.rxBytes = left.rxBytes[i];
- entry.rxPackets = left.rxPackets[i];
- entry.txBytes = left.txBytes[i];
- entry.txPackets = left.txPackets[i];
- entry.operations = left.operations[i];
- } else {
- // existing row, subtract remote value
- entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
- entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
- entry.txBytes = left.txBytes[i] - right.txBytes[j];
- entry.txPackets = left.txPackets[i] - right.txPackets[j];
- entry.operations = left.operations[i] - right.operations[j];
+ if (j != -1) {
+ // Found matching row, subtract remote value.
+ entry.rxBytes -= right.rxBytes[j];
+ entry.rxPackets -= right.rxPackets[j];
+ entry.txBytes -= right.txBytes[j];
+ entry.txPackets -= right.txPackets[j];
+ entry.operations -= right.operations[j];
+ }
- if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
- || entry.txPackets < 0 || entry.operations < 0) {
- if (observer != null) {
- observer.foundNonMonotonic(left, i, right, j, cookie);
- }
- entry.rxBytes = Math.max(entry.rxBytes, 0);
- entry.rxPackets = Math.max(entry.rxPackets, 0);
- entry.txBytes = Math.max(entry.txBytes, 0);
- entry.txPackets = Math.max(entry.txPackets, 0);
- entry.operations = Math.max(entry.operations, 0);
+ if (entry.isNegative()) {
+ if (observer != null) {
+ observer.foundNonMonotonic(left, i, right, j, cookie);
}
+ entry.rxBytes = Math.max(entry.rxBytes, 0);
+ entry.rxPackets = Math.max(entry.rxPackets, 0);
+ entry.txBytes = Math.max(entry.txBytes, 0);
+ entry.txPackets = Math.max(entry.txPackets, 0);
+ entry.operations = Math.max(entry.operations, 0);
}
result.addValues(entry);
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 1e41eea..535bf67 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -21,25 +21,24 @@
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
import android.annotation.SdkConstant;
-import android.annotation.SystemService;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemService;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.os.RemoteException;
import android.os.Messenger;
-import android.text.TextUtils;
+import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
-import java.util.concurrent.CountDownLatch;
-
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import java.util.concurrent.CountDownLatch;
+
/**
* The Network Service Discovery Manager class provides the API to discover services
* on a network. As an example, if device A and device B are connected over a Wi-Fi
@@ -244,7 +243,7 @@
return name;
}
- private static int FIRST_LISTENER_KEY = 1;
+ private static final int FIRST_LISTENER_KEY = 1;
private final INsdManager mService;
private final Context mContext;
@@ -278,6 +277,7 @@
@VisibleForTesting
public void disconnect() {
mAsyncChannel.disconnect();
+ mHandler.getLooper().quitSafely();
}
/**
@@ -650,7 +650,7 @@
private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
checkNotNull(serviceInfo, "NsdServiceInfo cannot be null");
- checkStringNotEmpty(serviceInfo.getServiceName(),"Service name cannot be empty");
+ checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty");
checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty");
}
}
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 8632194..560b4b3 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -16,6 +16,8 @@
package android.os;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import android.util.MutableInt;
@@ -43,17 +45,12 @@
public static final int PROP_VALUE_MAX = 91;
+ @GuardedBy("sChangeCallbacks")
private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
@GuardedBy("sRoReads")
- private static final HashMap<String, MutableInt> sRoReads;
- static {
- if (TRACK_KEY_ACCESS) {
- sRoReads = new HashMap<>();
- } else {
- sRoReads = null;
- }
- }
+ private static final HashMap<String, MutableInt> sRoReads =
+ TRACK_KEY_ACCESS ? new HashMap<>() : null;
private static void onKeyAccess(String key) {
if (!TRACK_KEY_ACCESS) return;
@@ -85,77 +82,102 @@
private static native void native_report_sysprop_change();
/**
- * Get the value for the given key.
- * @return an empty string if the key isn't found
+ * Get the String value for the given {@code key}.
+ *
+ * <b>WARNING:</b> Do not use this method if the value may not be a valid UTF string! This
+ * method will crash in native code.
+ *
+ * @param key the key to lookup
+ * @return an empty string if the {@code key} isn't found
*/
- public static String get(String key) {
+ @NonNull
+ public static String get(@NonNull String key) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key);
}
/**
- * Get the value for the given key.
- * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
+ * Get the String value for the given {@code key}.
+ *
+ * <b>WARNING:</b> Do not use this method if the value may not be a valid UTF string! This
+ * method will crash in native code.
+ *
+ * @param key the key to lookup
+ * @param def the default value in case the property is not set or empty
+ * @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty
+ * string otherwise
*/
- public static String get(String key, String def) {
+ @NonNull
+ public static String get(@NonNull String key, @Nullable String def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get(key, def);
}
/**
- * Get the value for the given key, and return as an integer.
+ * Get the value for the given {@code key}, and return as an integer.
+ *
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
*/
- public static int getInt(String key, int def) {
+ public static int getInt(@NonNull String key, int def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_int(key, def);
}
/**
- * Get the value for the given key, and return as a long.
+ * Get the value for the given {@code key}, and return as a long.
+ *
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a long, or def if the key isn't found or
* cannot be parsed
*/
- public static long getLong(String key, long def) {
+ public static long getLong(@NonNull String key, long def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_long(key, def);
}
/**
- * Get the value for the given key, returned as a boolean.
+ * Get the value for the given {@code key}, returned as a boolean.
* Values 'n', 'no', '0', 'false' or 'off' are considered false.
* Values 'y', 'yes', '1', 'true' or 'on' are considered true.
* (case sensitive).
* If the key does not exist, or has any other value, then the default
* result is returned.
+ *
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
*/
- public static boolean getBoolean(String key, boolean def) {
+ public static boolean getBoolean(@NonNull String key, boolean def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_boolean(key, def);
}
/**
- * Set the value for the given key.
- * @throws IllegalArgumentException if the value exceeds 92 characters
+ * Set the value for the given {@code key} to {@code val}.
+ *
+ * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
*/
- public static void set(String key, String val) {
+ public static void set(@NonNull String key, @Nullable String val) {
if (val != null && val.length() > PROP_VALUE_MAX) {
- throw newValueTooLargeException(key, val);
+ throw new IllegalArgumentException("value of system property '" + key
+ + "' is longer than " + PROP_VALUE_MAX + " characters: " + val);
}
if (TRACK_KEY_ACCESS) onKeyAccess(key);
native_set(key, val);
}
- public static void addChangeCallback(Runnable callback) {
+ /**
+ * Add a callback that will be run whenever any system property changes.
+ *
+ * @param callback The {@link Runnable} that should be executed when a system property
+ * changes.
+ */
+ public static void addChangeCallback(@NonNull Runnable callback) {
synchronized (sChangeCallbacks) {
if (sChangeCallbacks.size() == 0) {
native_add_change_callback();
@@ -164,7 +186,8 @@
}
}
- static void callChangeCallbacks() {
+ @SuppressWarnings("unused") // Called from native code.
+ private static void callChangeCallbacks() {
synchronized (sChangeCallbacks) {
//Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
if (sChangeCallbacks.size() == 0) {
@@ -177,11 +200,6 @@
}
}
- private static IllegalArgumentException newValueTooLargeException(String key, String value) {
- return new IllegalArgumentException("value of system property '" + key + "' is longer than "
- + PROP_VALUE_MAX + " characters: " + value);
- }
-
/*
* Notifies listeners that a system property has changed
*/
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index abd6278..c5279e1 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -231,6 +231,7 @@
"libutils",
"libbinder",
"libui",
+ "libgraphicsenv",
"libgui",
"libsensor",
"libinput",
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 399dec8..f749488 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "GraphicsEnvironment"
-#include <ui/GraphicsEnv.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 8844fb0..a94cac0 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -17,188 +17,109 @@
#define LOG_TAG "SysPropJNI"
+#include "android-base/logging.h"
+#include "android-base/properties.h"
#include "cutils/properties.h"
#include "utils/misc.h"
#include <utils/Log.h>
#include "jni.h"
#include "core_jni_helpers.h"
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
namespace android
{
-static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz,
- jstring keyJ, jstring defJ)
-{
- int len;
- const char* key;
- char buf[PROPERTY_VALUE_MAX];
- jstring rvJ = NULL;
+namespace {
- if (keyJ == NULL) {
- jniThrowNullPointerException(env, "key must not be null.");
- goto error;
- }
-
- key = env->GetStringUTFChars(keyJ, NULL);
-
- len = property_get(key, buf, "");
- if ((len <= 0) && (defJ != NULL)) {
- rvJ = defJ;
- } else if (len >= 0) {
- rvJ = env->NewStringUTF(buf);
- } else {
- rvJ = env->NewStringUTF("");
- }
-
- env->ReleaseStringUTFChars(keyJ, key);
-
-error:
- return rvJ;
-}
-
-static jstring SystemProperties_getS(JNIEnv *env, jobject clazz,
- jstring keyJ)
-{
- return SystemProperties_getSS(env, clazz, keyJ, NULL);
-}
-
-static jint SystemProperties_get_int(JNIEnv *env, jobject clazz,
- jstring keyJ, jint defJ)
-{
- int len;
- const char* key;
- char buf[PROPERTY_VALUE_MAX];
- char* end;
- jint result = defJ;
-
- if (keyJ == NULL) {
- jniThrowNullPointerException(env, "key must not be null.");
- goto error;
- }
-
- key = env->GetStringUTFChars(keyJ, NULL);
-
- len = property_get(key, buf, "");
- if (len > 0) {
- result = strtol(buf, &end, 0);
- if (end == buf) {
- result = defJ;
+template <typename T, typename Handler>
+T ConvertKeyAndForward(JNIEnv *env, jstring keyJ, T defJ, Handler handler) {
+ std::string key;
+ {
+ // Scope the String access. If the handler can throw an exception,
+ // releasing the string characters late would trigger an abort.
+ ScopedUtfChars key_utf(env, keyJ);
+ if (key_utf.c_str() == nullptr) {
+ return defJ;
}
+ key = key_utf.c_str(); // This will make a copy, but we can't avoid
+ // with the existing interface in
+ // android::base.
}
-
- env->ReleaseStringUTFChars(keyJ, key);
-
-error:
- return result;
+ return handler(key, defJ);
}
-static jlong SystemProperties_get_long(JNIEnv *env, jobject clazz,
- jstring keyJ, jlong defJ)
+jstring SystemProperties_getSS(JNIEnv *env, jclass clazz, jstring keyJ,
+ jstring defJ)
{
- int len;
- const char* key;
- char buf[PROPERTY_VALUE_MAX];
- char* end;
- jlong result = defJ;
-
- if (keyJ == NULL) {
- jniThrowNullPointerException(env, "key must not be null.");
- goto error;
- }
-
- key = env->GetStringUTFChars(keyJ, NULL);
-
- len = property_get(key, buf, "");
- if (len > 0) {
- result = strtoll(buf, &end, 0);
- if (end == buf) {
- result = defJ;
+ // Using ConvertKeyAndForward is sub-optimal for copying the key string,
+ // but improves reuse and reasoning over code.
+ auto handler = [&](const std::string& key, jstring defJ) {
+ std::string prop_val = android::base::GetProperty(key, "");
+ if (!prop_val.empty()) {
+ return env->NewStringUTF(prop_val.c_str());
+ };
+ if (defJ != nullptr) {
+ return defJ;
}
- }
-
- env->ReleaseStringUTFChars(keyJ, key);
-
-error:
- return result;
+ // This function is specified to never return null (or have an
+ // exception pending).
+ return env->NewStringUTF("");
+ };
+ return ConvertKeyAndForward(env, keyJ, defJ, handler);
}
-static jboolean SystemProperties_get_boolean(JNIEnv *env, jobject clazz,
- jstring keyJ, jboolean defJ)
+jstring SystemProperties_getS(JNIEnv *env, jclass clazz, jstring keyJ)
{
- int len;
- const char* key;
- char buf[PROPERTY_VALUE_MAX];
- jboolean result = defJ;
+ return SystemProperties_getSS(env, clazz, keyJ, nullptr);
+}
- if (keyJ == NULL) {
- jniThrowNullPointerException(env, "key must not be null.");
- goto error;
- }
+template <typename T>
+T SystemProperties_get_integral(JNIEnv *env, jclass, jstring keyJ,
+ T defJ)
+{
+ auto handler = [](const std::string& key, T defV) {
+ return android::base::GetIntProperty<T>(key, defV);
+ };
+ return ConvertKeyAndForward(env, keyJ, defJ, handler);
+}
- key = env->GetStringUTFChars(keyJ, NULL);
+jboolean SystemProperties_get_boolean(JNIEnv *env, jclass, jstring keyJ,
+ jboolean defJ)
+{
+ auto handler = [](const std::string& key, jboolean defV) -> jboolean {
+ bool result = android::base::GetBoolProperty(key, defV);
+ return result ? JNI_TRUE : JNI_FALSE;
+ };
+ return ConvertKeyAndForward(env, keyJ, defJ, handler);
+}
- len = property_get(key, buf, "");
- if (len == 1) {
- char ch = buf[0];
- if (ch == '0' || ch == 'n')
- result = false;
- else if (ch == '1' || ch == 'y')
- result = true;
- } else if (len > 1) {
- if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
- result = false;
- } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
- result = true;
+void SystemProperties_set(JNIEnv *env, jobject clazz, jstring keyJ,
+ jstring valJ)
+{
+ auto handler = [&](const std::string& key, bool) {
+ std::string val;
+ if (valJ != nullptr) {
+ ScopedUtfChars key_utf(env, valJ);
+ val = key_utf.c_str();
}
- }
-
- env->ReleaseStringUTFChars(keyJ, key);
-
-error:
- return result;
-}
-
-static void SystemProperties_set(JNIEnv *env, jobject clazz,
- jstring keyJ, jstring valJ)
-{
- int err;
- const char* key;
- const char* val;
-
- if (keyJ == NULL) {
- jniThrowNullPointerException(env, "key must not be null.");
- return ;
- }
- key = env->GetStringUTFChars(keyJ, NULL);
-
- if (valJ == NULL) {
- val = ""; /* NULL pointer not allowed here */
- } else {
- val = env->GetStringUTFChars(valJ, NULL);
- }
-
- err = property_set(key, val);
-
- env->ReleaseStringUTFChars(keyJ, key);
-
- if (valJ != NULL) {
- env->ReleaseStringUTFChars(valJ, val);
- }
-
- if (err < 0) {
+ return android::base::SetProperty(key, val);
+ };
+ if (!ConvertKeyAndForward(env, keyJ, true, handler)) {
+ // Must have been a failure in SetProperty.
jniThrowException(env, "java/lang/RuntimeException",
"failed to set system property");
}
}
-static JavaVM* sVM = NULL;
-static jclass sClazz = NULL;
-static jmethodID sCallChangeCallbacks;
+JavaVM* sVM = nullptr;
+jclass sClazz = nullptr;
+jmethodID sCallChangeCallbacks;
-static void do_report_sysprop_change() {
+void do_report_sysprop_change() {
//ALOGI("Java SystemProperties: VM=%p, Clazz=%p", sVM, sClazz);
- if (sVM != NULL && sClazz != NULL) {
+ if (sVM != nullptr && sClazz != nullptr) {
JNIEnv* env;
if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
//ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
@@ -207,47 +128,49 @@
}
}
-static void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
+void SystemProperties_add_change_callback(JNIEnv *env, jobject clazz)
{
// This is called with the Java lock held.
- if (sVM == NULL) {
+ if (sVM == nullptr) {
env->GetJavaVM(&sVM);
}
- if (sClazz == NULL) {
+ if (sClazz == nullptr) {
sClazz = (jclass) env->NewGlobalRef(clazz);
sCallChangeCallbacks = env->GetStaticMethodID(sClazz, "callChangeCallbacks", "()V");
add_sysprop_change_callback(do_report_sysprop_change, -10000);
}
}
-static void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
+void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
{
report_sysprop_change();
}
-static const JNINativeMethod method_table[] = {
- { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
- (void*) SystemProperties_getS },
- { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
- (void*) SystemProperties_getSS },
- { "native_get_int", "(Ljava/lang/String;I)I",
- (void*) SystemProperties_get_int },
- { "native_get_long", "(Ljava/lang/String;J)J",
- (void*) SystemProperties_get_long },
- { "native_get_boolean", "(Ljava/lang/String;Z)Z",
- (void*) SystemProperties_get_boolean },
- { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
- (void*) SystemProperties_set },
- { "native_add_change_callback", "()V",
- (void*) SystemProperties_add_change_callback },
- { "native_report_sysprop_change", "()V",
- (void*) SystemProperties_report_sysprop_change },
-};
+} // namespace
int register_android_os_SystemProperties(JNIEnv *env)
{
- return RegisterMethodsOrDie(env, "android/os/SystemProperties", method_table,
- NELEM(method_table));
+ const JNINativeMethod method_table[] = {
+ { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
+ (void*) SystemProperties_getS },
+ { "native_get",
+ "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void*) SystemProperties_getSS },
+ { "native_get_int", "(Ljava/lang/String;I)I",
+ (void*) SystemProperties_get_integral<jint> },
+ { "native_get_long", "(Ljava/lang/String;J)J",
+ (void*) SystemProperties_get_integral<jlong> },
+ { "native_get_boolean", "(Ljava/lang/String;Z)Z",
+ (void*) SystemProperties_get_boolean },
+ { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
+ (void*) SystemProperties_set },
+ { "native_add_change_callback", "()V",
+ (void*) SystemProperties_add_change_callback },
+ { "native_report_sysprop_change", "()V",
+ (void*) SystemProperties_report_sysprop_change },
+ };
+ return RegisterMethodsOrDie(env, "android/os/SystemProperties",
+ method_table, NELEM(method_table));
}
};
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 7ec4b8e..5ef2a9e 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -56,7 +56,7 @@
}
template<typename T>
-static void tryAddSchema(const T* object, const XmlConverter<T>& converter,
+static void tryAddSchema(const std::shared_ptr<const T>& object, const XmlConverter<T>& converter,
const std::string& description,
std::vector<std::string>* cStrings) {
if (object == nullptr) {
@@ -66,7 +66,7 @@
}
}
-static void tryAddHalNamesAndVersions(const HalManifest *manifest,
+static void tryAddHalNamesAndVersions(const std::shared_ptr<const HalManifest>& manifest,
const std::string& description,
std::set<std::string> *output) {
if (manifest == nullptr) {
@@ -119,7 +119,7 @@
}
static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) {
- const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
+ std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) {
LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest";
return nullptr;
@@ -129,7 +129,7 @@
}
static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) {
- const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
+ std::shared_ptr<const HalManifest> manifest = VintfObject::GetFrameworkHalManifest();
if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) {
LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest";
return nullptr;
diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp
index 19220cf0..315eac1 100644
--- a/core/jni/android_os_VintfRuntimeInfo.cpp
+++ b/core/jni/android_os_VintfRuntimeInfo.cpp
@@ -32,7 +32,7 @@
#define MAP_STRING_METHOD(javaMethod, cppString) \
static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) \
{ \
- const RuntimeInfo *info = VintfObject::GetRuntimeInfo(); \
+ std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(); \
if (info == nullptr) return nullptr; \
return env->NewStringUTF((cppString).c_str()); \
} \
@@ -50,7 +50,7 @@
static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz)
{
- const RuntimeInfo *info = VintfObject::GetRuntimeInfo();
+ std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo();
if (info == nullptr) return 0;
return static_cast<jlong>(info->kernelSepolicyVersion());
}
diff --git a/core/res/res/values-mcc505-mnc01/config.xml b/core/res/res/values-mcc505-mnc01/config.xml
index ff06585..5a5b8f7 100644
--- a/core/res/res/values-mcc505-mnc01/config.xml
+++ b/core/res/res/values-mcc505-mnc01/config.xml
@@ -31,15 +31,6 @@
<item>9</item>
</integer-array>
- <!-- String containing the apn value for tethering. May be overriden by secure settings
- TETHER_DUN_APN. Value is a comma separated series of strings:
- "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type",
- Or string format of ApnSettingV3.
- note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
- <string-array translatable="false" name="config_tether_apndata">
- <item>Telstra Tethering,telstra.internet,,,,,,,,,505,01,,DUN</item>
- </string-array>
-
<!--Thresholds for LTE dbm in status bar-->
<integer-array translatable="false" name="config_lteDbmThresholds">
<item>-140</item> <!-- SIGNAL_STRENGTH_NONE_OR_UNKNOWN -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8995513..70c39af 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -296,6 +296,17 @@
less than 0x600 -->
<bool translatable="false" name="config_apfDrop802_3Frames">true</bool>
+ <!-- An array of Black listed EtherType, packets with EtherTypes within this array
+ will be dropped
+ TODO: need to put proper values, these are for testing purposes only -->
+ <integer-array translatable="false" name="config_apfEthTypeBlackList">
+ <item>0x88A2</item>
+ <item>0x88A4</item>
+ <item>0x88B8</item>
+ <item>0x88CD</item>
+ <item>0x88E3</item>
+ </integer-array>
+
<!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE.
This is the default value of that setting. -->
@@ -1493,16 +1504,16 @@
<integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
<!-- Idle current for bluetooth controller. 0 by default-->
- <integer translatable="false" name="config_bluetooth_idle_cur_ma">1</integer>
+ <integer translatable="false" name="config_bluetooth_idle_cur_ma">0</integer>
<!-- Rx current for bluetooth controller. 0 by default-->
- <integer translatable="false" name="config_bluetooth_rx_cur_ma">2</integer>
+ <integer translatable="false" name="config_bluetooth_rx_cur_ma">0</integer>
<!-- Tx current for bluetooth controller. 0 by default-->
- <integer translatable="false" name="config_bluetooth_tx_cur_ma">3</integer>
+ <integer translatable="false" name="config_bluetooth_tx_cur_ma">0</integer>
<!-- Operating volatage for bluetooth controller. 0 by default-->
- <integer translatable="false" name="config_bluetooth_operating_voltage_mv">4</integer>
+ <integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
<!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
<bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c527501..600c82f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1837,6 +1837,7 @@
<java-symbol type="integer" name="config_networkWakeupPacketMark" />
<java-symbol type="integer" name="config_networkWakeupPacketMask" />
<java-symbol type="bool" name="config_apfDrop802_3Frames" />
+ <java-symbol type="array" name="config_apfEthTypeBlackList" />
<java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 7e9f561..f5b350b 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -181,7 +181,7 @@
<shortcode country="mk" pattern="\\d{1,6}" free="129005|122" />
<!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052|9963" />
+ <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052|9963|76551" />
<!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
<shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288" />
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index d5f6321..9686dd9 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -24,10 +24,15 @@
import android.system.OsConstants;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Suppress;
+import android.util.ArraySet;
+
import junit.framework.TestCase;
import java.net.InetAddress;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
public class LinkPropertiesTest extends TestCase {
@@ -678,4 +683,76 @@
stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
assertTrue(v6lp.isReachable(DNS1));
}
+
+ @SmallTest
+ public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
+ // IPv4 case: no route added initially
+ LinkProperties rmnet0 = new LinkProperties();
+ rmnet0.setInterfaceName("rmnet0");
+ rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8"));
+ RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
+ rmnet0.getInterfaceName());
+
+ // Since no routes is added explicitly, getAllRoutes() should return empty.
+ assertTrue(rmnet0.getAllRoutes().isEmpty());
+ rmnet0.ensureDirectlyConnectedRoutes();
+ // ensureDirectlyConnectedRoutes() should have added the missing local route.
+ assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes());
+
+ // IPv4 case: both direct and default routes added initially
+ LinkProperties rmnet1 = new LinkProperties();
+ rmnet1.setInterfaceName("rmnet1");
+ rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
+ RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null,
+ NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName());
+ RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
+ rmnet1.getInterfaceName());
+ rmnet1.addRoute(defaultRoute1);
+ rmnet1.addRoute(directRoute1);
+
+ // Check added routes
+ assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
+ // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected
+ // route is already part of the configuration.
+ rmnet1.ensureDirectlyConnectedRoutes();
+ assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
+
+ // IPv6 case: only default routes added initially
+ LinkProperties rmnet2 = new LinkProperties();
+ rmnet2.setInterfaceName("rmnet2");
+ rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
+ rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
+ RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null,
+ NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName());
+ RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
+ rmnet2.getInterfaceName());
+ RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
+ rmnet2.getInterfaceName());
+ rmnet2.addRoute(defaultRoute2);
+
+ assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes());
+ rmnet2.ensureDirectlyConnectedRoutes();
+ assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2),
+ rmnet2.getAllRoutes());
+
+ // Corner case: no interface name
+ LinkProperties rmnet3 = new LinkProperties();
+ rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24"));
+ RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null,
+ rmnet3.getInterfaceName());
+
+ assertTrue(rmnet3.getAllRoutes().isEmpty());
+ rmnet3.ensureDirectlyConnectedRoutes();
+ assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
+
+ }
+
+ private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
+ Set<RouteInfo> expectedSet = new ArraySet<>(expected);
+ Set<RouteInfo> actualSet = new ArraySet<>(actual);
+ // Duplicated entries in actual routes are considered failures
+ assertEquals(actual.size(), actualSet.size());
+
+ assertEquals(expectedSet, actualSet);
+ }
}
diff --git a/core/tests/systemproperties/run_core_systemproperties_test.sh b/core/tests/systemproperties/run_core_systemproperties_test.sh
index d39adbb..9b1fe4b 100755
--- a/core/tests/systemproperties/run_core_systemproperties_test.sh
+++ b/core/tests/systemproperties/run_core_systemproperties_test.sh
@@ -15,7 +15,7 @@
if [[ $rebuild == true ]]; then
make -j4 FrameworksCoreSystemPropertiesTests
- TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreSystemPropertiesTests.apk
+ TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreSystemPropertiesTests/FrameworksCoreSystemPropertiesTests.apk
COMMAND="adb install -r $TESTAPP"
echo $COMMAND
$COMMAND
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 544a967..282b001 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -51,6 +51,11 @@
value = SystemProperties.get(KEY, "default");
assertEquals("default", value);
+ // null default value is the same as "".
+ SystemProperties.set(KEY, null);
+ value = SystemProperties.get(KEY, "default");
+ assertEquals("default", value);
+
SystemProperties.set(KEY, "SA");
value = SystemProperties.get(KEY, "default");
assertEquals("SA", value);
@@ -62,7 +67,78 @@
value = SystemProperties.get(KEY, "default");
assertEquals("default", value);
+ // null value is the same as "".
+ SystemProperties.set(KEY, "SA");
+ SystemProperties.set(KEY, null);
+ value = SystemProperties.get(KEY, "default");
+ assertEquals("default", value);
+
value = SystemProperties.get(KEY);
assertEquals("", value);
}
+
+ private static void testInt(String setVal, int defValue, int expected) {
+ SystemProperties.set(KEY, setVal);
+ int value = SystemProperties.getInt(KEY, defValue);
+ assertEquals(expected, value);
+ }
+
+ private static void testLong(String setVal, long defValue, long expected) {
+ SystemProperties.set(KEY, setVal);
+ long value = SystemProperties.getLong(KEY, defValue);
+ assertEquals(expected, value);
+ }
+
+ @SmallTest
+ public void testIntegralProperties() throws Exception {
+ testInt("", 123, 123);
+ testInt("", 0, 0);
+ testInt("", -123, -123);
+
+ testInt("123", 124, 123);
+ testInt("0", 124, 0);
+ testInt("-123", 124, -123);
+
+ testLong("", 3147483647L, 3147483647L);
+ testLong("", 0, 0);
+ testLong("", -3147483647L, -3147483647L);
+
+ testLong("3147483647", 124, 3147483647L);
+ testLong("0", 124, 0);
+ testLong("-3147483647", 124, -3147483647L);
+ }
+
+ @SmallTest
+ @SuppressWarnings("null")
+ public void testNullKey() throws Exception {
+ try {
+ SystemProperties.get(null);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException npe) {
+ }
+
+ try {
+ SystemProperties.get(null, "default");
+ fail("Expected NullPointerException");
+ } catch (NullPointerException npe) {
+ }
+
+ try {
+ SystemProperties.set(null, "value");
+ fail("Expected NullPointerException");
+ } catch (NullPointerException npe) {
+ }
+
+ try {
+ SystemProperties.getInt(null, 0);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException npe) {
+ }
+
+ try {
+ SystemProperties.getLong(null, 0);
+ fail("Expected NullPointerException");
+ } catch (NullPointerException npe) {
+ }
+ }
}
diff --git a/core/tests/utiltests/jni/Android.bp b/core/tests/utiltests/jni/Android.bp
index e9a4144..b0b09c2 100644
--- a/core/tests/utiltests/jni/Android.bp
+++ b/core/tests/utiltests/jni/Android.bp
@@ -17,7 +17,6 @@
shared_libs: [
"libcutils",
],
- clang: true,
stl: "libc++",
srcs: [
"registration.cpp",
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 0782269..7a0ef2b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -59,7 +59,6 @@
#endif
#define IDMAP_MAGIC 0x504D4449
-#define IDMAP_CURRENT_VERSION 0x00000001
#define APP_PACKAGE_ID 0x7f
#define SYS_PACKAGE_ID 0x01
@@ -246,11 +245,11 @@
}
const uint32_t version = htodl(*(reinterpret_cast<const uint32_t*>(idmap) + 1));
- if (version != IDMAP_CURRENT_VERSION) {
+ if (version != ResTable::IDMAP_CURRENT_VERSION) {
// We are strict about versions because files with this format are
// auto-generated and don't need backwards compatibility.
ALOGW("idmap: version mismatch in header (is 0x%08x, expected 0x%08x)",
- version, IDMAP_CURRENT_VERSION);
+ version, ResTable::IDMAP_CURRENT_VERSION);
return false;
}
return true;
@@ -6855,7 +6854,7 @@
uint32_t* data = (uint32_t*)*outData;
*data++ = htodl(IDMAP_MAGIC);
- *data++ = htodl(IDMAP_CURRENT_VERSION);
+ *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION);
*data++ = htodl(targetCrc);
*data++ = htodl(overlayCrc);
const char* paths[] = { targetPath, overlayPath };
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 7a6e37d..66c66c2 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1933,6 +1933,7 @@
void** outData, size_t* outSize) const;
static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256;
+ static const uint32_t IDMAP_CURRENT_VERSION = 0x00000001;
// Retrieve idmap meta-data.
//
diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp
new file mode 100644
index 0000000..b8f2904
--- /dev/null
+++ b/libs/usb/Android.bp
@@ -0,0 +1 @@
+subdirs = ["tests/*"]
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
new file mode 100644
index 0000000..4af6274
--- /dev/null
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -0,0 +1 @@
+subdirs = ["accessorychat"]
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.bp b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
new file mode 100644
index 0000000..5613745
--- /dev/null
+++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.bp
@@ -0,0 +1,30 @@
+cc_binary {
+ name: "accessorychat",
+ host_supported: true,
+
+ srcs: ["accessorychat.c"],
+ cflags: [
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+
+ target: {
+ android: {
+ shared_libs: [
+ "libusbhost",
+ "libcutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libusbhost",
+ "libcutils",
+ ],
+
+ cflags: ["-O0"],
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
deleted file mode 100644
index 51f2111..0000000
--- a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build for Linux (desktop) host
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessorychat.c
-
-LOCAL_MODULE := accessorychat
-
-LOCAL_STATIC_LIBRARIES := libusbhost libcutils
-LOCAL_LDLIBS += -lpthread
-LOCAL_CFLAGS := -g -O0
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif
-
-# Build for device
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessorychat.c
-
-LOCAL_MODULE := accessorychat
-
-LOCAL_SHARED_LIBRARIES := libusbhost libcutils
-
-include $(BUILD_EXECUTABLE)
diff --git a/libs/usb/tests/accessorytest/Android.bp b/libs/usb/tests/accessorytest/Android.bp
new file mode 100644
index 0000000..c6340e3
--- /dev/null
+++ b/libs/usb/tests/accessorytest/Android.bp
@@ -0,0 +1,28 @@
+cc_binary_host {
+ name: "accessorytest",
+
+ srcs: [
+ "accessory.c",
+ "audio.c",
+ "hid.c",
+ "usb.c",
+ ],
+
+ static_libs: [
+ "libusbhost",
+ "libcutils",
+ "libtinyalsa",
+ ],
+ cflags: [
+ "-O0",
+ "-Wno-unused-parameter",
+ "-Werror",
+ ],
+
+ target: {
+ darwin: {
+ // Build for Linux host only
+ enabled: false,
+ },
+ },
+}
diff --git a/libs/usb/tests/accessorytest/Android.mk b/libs/usb/tests/accessorytest/Android.mk
deleted file mode 100644
index 6d9a946..0000000
--- a/libs/usb/tests/accessorytest/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# Build for Linux host only
-ifeq ($(HOST_OS),linux)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := accessory.c \
- audio.c \
- hid.c \
- usb.c
-
-LOCAL_C_INCLUDES += external/tinyalsa/include
-
-LOCAL_MODULE := accessorytest
-
-LOCAL_STATIC_LIBRARIES := libusbhost libcutils libtinyalsa
-LOCAL_LDLIBS += -lpthread
-LOCAL_CFLAGS := -g -O0
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif
diff --git a/libs/usb/tests/accessorytest/accessory.h b/libs/usb/tests/accessorytest/accessory.h
index 55c4550..e86986e 100644
--- a/libs/usb/tests/accessorytest/accessory.h
+++ b/libs/usb/tests/accessorytest/accessory.h
@@ -19,7 +19,7 @@
int init_audio(unsigned int ic, unsigned int id, unsigned int oc, unsigned int od);
void init_hid();
-void usb_run(int enable_accessory);
+void usb_run(uintptr_t enable_accessory);
struct usb_device* usb_wait_for_device();
diff --git a/libs/usb/tests/accessorytest/hid.c b/libs/usb/tests/accessorytest/hid.c
index b70d678..283755d 100644
--- a/libs/usb/tests/accessorytest/hid.c
+++ b/libs/usb/tests/accessorytest/hid.c
@@ -139,7 +139,7 @@
fprintf(stderr, "opened /dev/%s\n", name);
pthread_t th;
- pthread_create(&th, NULL, hid_thread, (void *)fd);
+ pthread_create(&th, NULL, hid_thread, (void *)(uintptr_t)fd);
}
static void* inotify_thread(void* arg)
diff --git a/libs/usb/tests/accessorytest/usb.c b/libs/usb/tests/accessorytest/usb.c
index ac72b35..1a161ad 100644
--- a/libs/usb/tests/accessorytest/usb.c
+++ b/libs/usb/tests/accessorytest/usb.c
@@ -219,7 +219,7 @@
return device;
}
-void usb_run(int enable_accessory) {
+void usb_run(uintptr_t enable_accessory) {
struct usb_host_context* context = usb_host_init();
usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)enable_accessory);
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index c1f03fd..c79c018 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -170,7 +170,8 @@
}
private void done(boolean success) {
- if (DBG) logd(String.format("Result success %b for %s", success, mUrl.toString()));
+ if (DBG) logd(String.format("Result success %b for %s", success,
+ mUrl != null ? mUrl.toString() : "null"));
if (success) {
// Trigger re-evaluation upon success http response code
CarrierActionUtils.applyCarrierAction(
@@ -226,7 +227,8 @@
int httpResponseCode = 500;
int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
try {
- urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
+ urlConnection = (HttpURLConnection) mNetwork.openConnection(
+ new URL(mCm.getCaptivePortalServerUrl()));
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -234,6 +236,7 @@
urlConnection.getInputStream();
httpResponseCode = urlConnection.getResponseCode();
} catch (IOException e) {
+ loge(e.getMessage());
} finally {
if (urlConnection != null) urlConnection.disconnect();
TrafficStats.setThreadStatsTag(oldTag);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e279a09..5f302c6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -332,8 +332,7 @@
}
public int getProfileConnectionState(LocalBluetoothProfile profile) {
- if (mProfileConnectionState == null ||
- mProfileConnectionState.get(profile) == null) {
+ if (mProfileConnectionState.get(profile) == null) {
// If cache is empty make the binder call to get the state
int state = profile.getConnectionStatus(mDevice);
mProfileConnectionState.put(profile, state);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 0cf8900..fe03fba 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -58,9 +58,19 @@
KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onSimStateChanged(int subId, int slotId, State simState) {
- if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
- resetState();
- };
+ if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+ switch(simState) {
+ // If the SIM is removed, then we must remove the keyguard. It will be put up
+ // again when the PUK locked SIM is re-entered.
+ case ABSENT: {
+ KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId);
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ break;
+ }
+ default:
+ resetState();
+ }
+ }
};
public KeyguardSimPinView(Context context) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index fb3cee7..826a03d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -60,9 +60,23 @@
KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onSimStateChanged(int subId, int slotId, State simState) {
- if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
- resetState();
- };
+ if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+ switch(simState) {
+ // If the SIM is removed, then we must remove the keyguard. It will be put up
+ // again when the PUK locked SIM is re-entered.
+ case ABSENT:
+ // intentional fall-through
+ // If the SIM is unlocked via a key sequence through the emergency dialer, it will
+ // move into the READY state and the PUK lock keyguard should be removed.
+ case READY: {
+ KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId);
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ break;
+ }
+ default:
+ resetState();
+ }
+ }
};
public KeyguardSimPukView(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 2473335..cef7c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -170,7 +170,8 @@
int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
mAnimator = new Builder()
- .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0)
+ .addFloat(mSettingsContainer, "translationX",
+ isLayoutRtl() ? (remaining - defSpace) : -(remaining - defSpace), 0)
.addFloat(mSettingsButton, "rotation", -120, 0)
.build();
if (mAlarmShowing) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 0a0d2ce..bdc5e7d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -556,7 +556,7 @@
@Override
public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
- if (viewHolder.getItemViewType() == TYPE_EDIT) {
+ if (viewHolder.getItemViewType() == TYPE_EDIT || viewHolder.getItemViewType() == TYPE_DIVIDER) {
return makeMovementFlags(0, 0);
}
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 672f2c2..3495f570 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -439,15 +439,22 @@
public static class DrawableIcon extends Icon {
protected final Drawable mDrawable;
+ protected final Drawable mInvisibleDrawable;
public DrawableIcon(Drawable drawable) {
mDrawable = drawable;
+ mInvisibleDrawable = drawable.getConstantState().newDrawable();
}
@Override
public Drawable getDrawable(Context context) {
return mDrawable;
}
+
+ @Override
+ public Drawable getInvisibleDrawable(Context context) {
+ return mInvisibleDrawable;
+ }
}
public static class DrawableIconWithRes extends DrawableIcon {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index f58fe82..55498af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4486,7 +4486,7 @@
animateCollapsePanels();
return true;
}
- if (mKeyguardUserSwitcher.hideIfNotSimple(true)) {
+ if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
return true;
}
return false;
diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto
index 76c5418..01fb860 100644
--- a/proto/src/ipconnectivity.proto
+++ b/proto/src/ipconnectivity.proto
@@ -23,7 +23,7 @@
// It is not intended to map one to one to the TRANSPORT_* constants defined in
// android.net.NetworkCapabilities. Instead it is intended to be used as
// a dimension field for metrics events and aggregated metrics.
-// Next tag: 7
+// Next tag: 10
enum LinkLayer {
// An unknown link layer technology.
UNKNOWN = 0;
@@ -32,6 +32,9 @@
CELLULAR = 2;
ETHERNET = 3;
WIFI = 4;
+ WIFI_P2P = 7;
+ WIFI_NAN = 8; // Also known as WiFi Aware
+ LOWPAN = 9;
// Indicates that the link layer dimension is not relevant for the metrics or
// event considered.
@@ -47,16 +50,18 @@
optional int32 value = 2;
};
-// Logs changes in the system default network. Changes can be 1) acquiring a
-// default network with no previous default, 2) a switch of the system default
-// network to a new default network, 3) a loss of the system default network.
-// This message is associated to android.net.metrics.DefaultNetworkEvent.
+// An event record when the system default network disconnects or the system
+// switches to a new default network.
+// Next tag: 10.
message DefaultNetworkEvent {
- // A value of 0 means this is a loss of the system default network.
- optional NetworkId network_id = 1;
- // A value of 0 means there was no previous default network.
- optional NetworkId previous_network_id = 2;
+ // Reason why this network stopped being the default.
+ enum LostReason {
+ UNKNOWN = 0;
+ OUTSCORED = 1;
+ INVALIDATION = 2;
+ DISCONNECT = 3;
+ };
// Whether the network supports IPv4, IPv6, or both.
enum IPSupport {
@@ -66,17 +71,52 @@
DUAL = 3;
};
+ // Duration in milliseconds when this network was the default.
+ // Since version 4
+ optional int64 default_network_duration_ms = 5;
+
+ // Duration in milliseconds without a default network before this network
+ // became the default.
+ // Since version 4
+ optional int64 no_default_network_duration_ms = 6;
+
+ // Network score of this network when it became the default network.
+ // Since version 4
+ optional int64 initial_score = 7;
+
+ // Network score of this network when it stopped being the default network.
+ // Since version 4
+ optional int64 final_score = 8;
+
+ // Best available information about IP support of this default network.
+ // Since version 4
+ optional IPSupport ip_support = 9;
+
+
+ // Deprecated fields
+
+ // A value of 0 means this is a loss of the system default network.
+ // Deprecated since version 3. Replaced by top level network_id.
+ optional NetworkId network_id = 1 [deprecated = true];
+
+ // A value of 0 means there was no previous default network.
+ // Deprecated since version 3. Replaced by previous_default_network_id.
+ optional NetworkId previous_network_id = 2 [deprecated = true];
+
// Best available information about IP support of the previous network when
// disconnecting or switching to a new default network.
- optional IPSupport previous_network_ip_support = 3;
+ // Deprecated since version 3. Replaced by ip_support field.
+ optional IPSupport previous_network_ip_support = 3 [deprecated = true];
// The transport types of the new default network, represented by
// TRANSPORT_* constants as defined in NetworkCapabilities.
- repeated int32 transport_types = 4;
+ // Deprecated since version 3. Replaced by top-level transports field.
+ repeated int32 transport_types = 4 [deprecated = true];
};
// Logs IpReachabilityMonitor probe events and NUD_FAILED events.
// This message is associated to android.net.metrics.IpReachabilityEvent.
+// Next tag: 3.
message IpReachabilityEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
// Deprecated since version 2, to be replaced by link_layer field.
@@ -91,6 +131,7 @@
// Logs NetworkMonitor and ConnectivityService events related to the state of
// a network: connection, evaluation, validation, lingering, and disconnection.
// This message is associated to android.net.metrics.NetworkEvent.
+// Next tag: 4.
message NetworkEvent {
// The id of the network on which this event happened.
// Deprecated since version 3.
@@ -108,6 +149,7 @@
// Logs individual captive portal probing events that are performed when
// evaluating or reevaluating networks for Internet connectivity.
// This message is associated to android.net.metrics.ValidationProbeEvent.
+// Next tag: 5.
message ValidationProbeEvent {
// The id of the network for which the probe was sent.
// Deprecated since version 3.
@@ -124,26 +166,64 @@
optional int32 probe_result = 4;
}
-// Logs DNS lookup latencies. Repeated fields must have the same length.
+// Logs DNS lookup latencies.
// This message is associated to android.net.metrics.DnsEvent.
-// Deprecated since version 2.
+// Next tag: 11
message DNSLookupBatch {
+
+ // The time it took for successful DNS lookups to complete.
+ // The number of repeated values can be less than getaddrinfo_query_count
+ // + gethostbyname_query_count in case of event rate-limiting.
+ repeated int32 latencies_ms = 4;
+
+ // The total number of getaddrinfo queries.
+ // Since version 4.
+ optional int64 getaddrinfo_query_count = 5;
+
+ // The total number of gethostbyname queries.
+ // Since version 4.
+ optional int64 gethostbyname_query_count = 6;
+
+ // The total number of getaddrinfo errors.
+ // Since version 4.
+ optional int64 getaddrinfo_error_count = 7;
+
+ // The total number of gethostbyname errors.
+ // Since version 4.
+ optional int64 gethostbyname_error_count = 8;
+
+ // Counts of all errors returned by getaddrinfo.
+ // The Pair key field is the getaddrinfo error value.
+ // The value field is the count for that return value.
+ // Since version 4
+ repeated Pair getaddrinfo_errors = 9;
+
+ // Counts of all errors returned by gethostbyname.
+ // The Pair key field is the gethostbyname errno value.
+ // the Pair value field is the count for that errno code.
+ // Since version 4
+ repeated Pair gethostbyname_errors = 10;
+
+
+ // Deprecated fields
+
// The id of the network on which the DNS lookups took place.
- optional NetworkId network_id = 1;
+ // Deprecated since version 3.
+ optional NetworkId network_id = 1 [deprecated = true];
// The types of the DNS lookups, as defined in android.net.metrics.DnsEvent.
- repeated int32 event_types = 2;
+ // Deprecated since version 3.
+ repeated int32 event_types = 2 [deprecated = true];
// The return values of the DNS resolver for each DNS lookups.
- repeated int32 return_codes = 3;
-
- // The time it took for each DNS lookups to complete.
- repeated int32 latencies_ms = 4;
+ // Deprecated since version 3.
+ repeated int32 return_codes = 3 [deprecated = true];
};
// Represents a collections of DNS lookup latencies and counters for a
// particular combination of DNS query type and return code.
// Since version 2.
+// Next tag: 7.
message DNSLatencies {
// The type of the DNS lookups, as defined in android.net.metrics.DnsEvent.
// Acts as a key for a set of DNS query results.
@@ -203,6 +283,7 @@
// state transition or a response packet parsing error.
// This message is associated to android.net.metrics.DhcpClientEvent and
// android.net.metrics.DhcpErrorEvent.
+// Next tag: 5
message DHCPEvent {
// The interface name (wlan, rmnet, lo, ...) on which the event happened.
// Deprecated since version 2, to be replaced by link_layer field.
@@ -255,7 +336,7 @@
// Represents Router Advertisement listening statistics for an interface with
// Android Packet Filter enabled.
// Since version 1.
-// Next tag: 12
+// Next tag: 15
message ApfStatistics {
// The time interval in milliseconds these stastistics cover.
optional int64 duration_ms = 1;
@@ -288,12 +369,28 @@
// The total number of APF program updates triggered when disabling the
// multicast filter. Since version 3.
+ // Since version 4.
optional int32 program_updates_allowing_multicast = 11;
+
+ // The total number of packets processed by the APF interpreter.
+ // Since version 4.
+ optional int32 total_packet_processed = 12;
+
+ // The total number of packets dropped by the APF interpreter.
+ // Since version 4.
+ optional int32 total_packet_dropped = 13;
+
+ // List of hardware counters collected by the APF interpreter.
+ // The Pair key is the counter id, defined in android.net.metrics.ApfStats.
+ // The Pair value is the counter value.
+ // Since version 4.
+ repeated Pair hardware_counters = 14;
}
// Represents the reception of a Router Advertisement packet for an interface
// with Android Packet Filter enabled.
// Since version 1.
+// Next tag: 7.
message RaEvent {
// All lifetime values are expressed in seconds. The default value for an
// option lifetime that was not present in the RA option list is -1.
@@ -322,6 +419,7 @@
// Represents an IP provisioning event in IpManager and how long the
// provisioning action took.
// This message is associated to android.net.metrics.IpManagerEvent.
+// Next tag: 4.
message IpProvisioningEvent {
// The interface name (wlan, rmnet, lo, ...) on which the probe was sent.
// Deprecated since version 2, to be replaced by link_layer field.
@@ -335,8 +433,48 @@
optional int32 latency_ms = 3;
}
+// Represents statistics from a single android Network.
+// Since version 4. Replace NetworkEvent.
+// Next tag: 9.
+message NetworkStats {
+
+ // Duration of this Network lifecycle in milliseconds.
+ optional int64 duration_ms = 1;
+
+ // Information about IP support of this network.
+ optional DefaultNetworkEvent.IPSupport ip_support = 2;
+
+ // True if the network was validated at least once.
+ optional bool ever_validated = 3;
+
+ // True if a captive portal was found at least once on this network.
+ optional bool portal_found = 4;
+
+ // Total number of times no connectivity was reported for this network.
+ optional int32 no_connectivity_reports = 5;
+
+ // Total number of validation attempts.
+ optional int32 validation_attempts = 6;
+
+ // Results from all validation attempts.
+ // The Pair key is the result:
+ // 0 -> unvalidated
+ // 1 -> validated
+ // 2 -> captive portal
+ // The Pair value is the duration of the validation attempts in milliseconds.
+ repeated Pair validation_events = 7;
+
+ // Time series of validation states in time order.
+ // The Pair key is the state:
+ // 0 -> unvalidated
+ // 1 -> validated
+ // 2 -> captive portal,
+ // The Pair value is the duration of that state in milliseconds.
+ repeated Pair validation_states = 8;
+}
+
// Represents one of the IP connectivity event defined in this file.
-// Next tag: 19
+// Next tag: 20
message IpConnectivityEvent {
// Time in ms when the event was recorded.
optional int64 time_ms = 1;
@@ -370,14 +508,13 @@
oneof event {
// An event about the system default network.
- // The link_layer field is not relevant for this event and set to NONE.
DefaultNetworkEvent default_network_event = 2;
// An IP reachability probe event.
IpReachabilityEvent ip_reachability_event = 3;
// A network lifecycle event.
- NetworkEvent network_event = 4;
+ NetworkEvent network_event = 4 [deprecated = true];
// A batch of DNS lookups.
// Deprecated in the nyc-mr2 release since version 2,and replaced by
@@ -407,10 +544,14 @@
// An RA packet reception event.
RaEvent ra_event = 11;
+
+ // Network statistics.
+ NetworkStats network_stats = 19;
};
};
// The information about IP connectivity events.
+// Next tag: 4.
message IpConnectivityLog {
// An array of IP connectivity events.
repeated IpConnectivityEvent events = 1;
@@ -424,5 +565,6 @@
// nyc-mr1: not populated, implicitly 1.
// nyc-mr2: 2.
// oc: 3.
+ // oc-dr1: 4.
optional int32 version = 3;
};
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 7fca21f..f61fd550 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -4,7 +4,10 @@
LOCAL_MODULE := services.core
-LOCAL_AIDL_INCLUDES := system/netd/server/binder
+LOCAL_AIDL_INCLUDES := \
+ frameworks/native/aidl/binder \
+ system/netd/server/binder
+
LOCAL_SRC_FILES += \
$(call all-java-files-under,java) \
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index fb20533..1703bd5 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -458,6 +458,11 @@
private static final int MAX_WAKELOCK_LOGS = 20;
private final LocalLog mWakelockLogs = new LocalLog(MAX_WAKELOCK_LOGS);
+ private int mTotalWakelockAcquisitions = 0;
+ private int mTotalWakelockReleases = 0;
+ private long mTotalWakelockDurationMs = 0;
+ private long mMaxWakelockDurationMs = 0;
+ private long mLastWakeLockAcquireTimestamp = 0;
// Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
private static final int MAX_VALIDATION_LOGS = 10;
@@ -1959,6 +1964,14 @@
pw.println();
pw.println("NetTransition WakeLock activity (most recent first):");
pw.increaseIndent();
+ pw.println("total acquisitions: " + mTotalWakelockAcquisitions);
+ pw.println("total releases: " + mTotalWakelockReleases);
+ pw.println("cumulative duration: " + (mTotalWakelockDurationMs / 1000) + "s");
+ pw.println("longest duration: " + (mMaxWakelockDurationMs / 1000) + "s");
+ if (mTotalWakelockAcquisitions > mTotalWakelockReleases) {
+ long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
+ pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
+ }
mWakelockLogs.reverseDump(fd, pw, args);
pw.decreaseIndent();
}
@@ -3012,6 +3025,8 @@
return;
}
mNetTransitionWakeLock.acquire();
+ mLastWakeLockAcquireTimestamp = SystemClock.elapsedRealtime();
+ mTotalWakelockAcquisitions++;
}
mWakelockLogs.log("ACQUIRE for " + forWhom);
Message msg = mHandler.obtainMessage(EVENT_EXPIRE_NET_TRANSITION_WAKELOCK);
@@ -3044,6 +3059,10 @@
return;
}
mNetTransitionWakeLock.release();
+ long lockDuration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
+ mTotalWakelockDurationMs += lockDuration;
+ mMaxWakelockDurationMs = Math.max(mMaxWakelockDurationMs, lockDuration);
+ mTotalWakelockReleases++;
}
mWakelockLogs.log(String.format("RELEASE (%s)", event));
}
@@ -4316,11 +4335,13 @@
int currentScore, NetworkMisc networkMisc) {
enforceConnectivityInternalPermission();
+ LinkProperties lp = new LinkProperties(linkProperties);
+ lp.ensureDirectlyConnectedRoutes();
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
- new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
- linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
+ new Network(reserveNetId()), new NetworkInfo(networkInfo), lp,
+ new NetworkCapabilities(networkCapabilities), currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
synchronized (this) {
nai.networkMonitor.systemReady = mSystemReady;
@@ -4616,6 +4637,11 @@
}
public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
+ if (mNetworkForNetId.get(nai.network.netId) != nai) {
+ // Ignore updates for disconnected networks
+ return;
+ }
+
if (VDBG) {
log("Update of LinkProperties for " + nai.name() +
"; created=" + nai.created +
@@ -4625,6 +4651,8 @@
synchronized (nai) {
nai.linkProperties = newLp;
}
+ // msg.obj is already a defensive copy.
+ nai.linkProperties.ensureDirectlyConnectedRoutes();
if (nai.everConnected) {
updateLinkProperties(nai, oldLp);
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3e44532..caa2d51 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -76,6 +76,7 @@
import android.os.IBinder;
import android.os.INetworkActivityListener;
import android.os.INetworkManagementService;
+import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -1897,38 +1898,34 @@
return new NetworkStats(SystemClock.elapsedRealtime(), 0);
}
- final NativeDaemonEvent[] events;
+ final PersistableBundle bundle;
try {
- events = mConnector.executeForList("bandwidth", "gettetherstats");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ bundle = mNetdService.tetherGetStats();
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException("problem parsing tethering stats: ", e);
}
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- for (NativeDaemonEvent event : events) {
- if (event.getCode() != TetheringStatsListResult) continue;
- // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
- final StringTokenizer tok = new StringTokenizer(event.getMessage());
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
+ bundle.size());
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ for (String iface : bundle.keySet()) {
+ long[] statsArray = bundle.getLongArray(iface);
try {
- final String ifaceIn = tok.nextToken();
- final String ifaceOut = tok.nextToken();
-
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.iface = ifaceOut;
+ entry.iface = iface;
entry.uid = UID_TETHERING;
entry.set = SET_DEFAULT;
entry.tag = TAG_NONE;
- entry.rxBytes = Long.parseLong(tok.nextToken());
- entry.rxPackets = Long.parseLong(tok.nextToken());
- entry.txBytes = Long.parseLong(tok.nextToken());
- entry.txPackets = Long.parseLong(tok.nextToken());
+ entry.rxBytes = statsArray[INetd.TETHER_STATS_RX_BYTES];
+ entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
+ entry.txBytes = statsArray[INetd.TETHER_STATS_TX_BYTES];
+ entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
stats.combineValues(entry);
- } catch (NoSuchElementException e) {
- throw new IllegalStateException("problem parsing tethering stats: " + event);
- } catch (NumberFormatException e) {
- throw new IllegalStateException("problem parsing tethering stats: " + event);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalStateException("invalid tethering stats for " + iface, e);
}
}
+
return stats;
}
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 3c8c699..1517887 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -285,8 +285,9 @@
// Send the BCB commands if it's to setup BCB.
if (isSetup) {
- dos.writeInt(command.length());
- dos.writeBytes(command);
+ byte[] cmdUtf8 = command.getBytes("UTF-8");
+ dos.writeInt(cmdUtf8.length);
+ dos.write(cmdUtf8, 0, cmdUtf8.length);
dos.flush();
}
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index 5dee91d..ee38219 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -20,6 +20,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
@@ -362,29 +363,46 @@
TRANSPORT_LINKLAYER_MAP[TRANSPORT_BLUETOOTH] = IpConnectivityLogClass.BLUETOOTH;
TRANSPORT_LINKLAYER_MAP[TRANSPORT_ETHERNET] = IpConnectivityLogClass.ETHERNET;
TRANSPORT_LINKLAYER_MAP[TRANSPORT_VPN] = IpConnectivityLogClass.UNKNOWN;
- // TODO: change mapping TRANSPORT_WIFI_AWARE -> WIFI_AWARE
- TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.UNKNOWN;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.WIFI_NAN;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_LOWPAN] = IpConnectivityLogClass.LOWPAN;
};
private static int ifnameToLinkLayer(String ifname) {
// Do not try to catch all interface names with regexes, instead only catch patterns that
// are cheap to check, and otherwise fallback on postprocessing in aggregation layer.
- for (int i = 0; i < IFNAME_LINKLAYER_MAP.size(); i++) {
- String pattern = IFNAME_LINKLAYER_MAP.valueAt(i);
+ for (int i = 0; i < KNOWN_PREFIX; i++) {
+ String pattern = IFNAME_PREFIXES[i];
if (ifname.startsWith(pattern)) {
- return IFNAME_LINKLAYER_MAP.keyAt(i);
+ return IFNAME_LINKLAYERS[i];
}
}
return IpConnectivityLogClass.UNKNOWN;
}
- private static final SparseArray<String> IFNAME_LINKLAYER_MAP = new SparseArray<String>();
+ private static final int KNOWN_PREFIX = 7;
+ private static final String[] IFNAME_PREFIXES = new String[KNOWN_PREFIX];
+ private static final int[] IFNAME_LINKLAYERS = new int[KNOWN_PREFIX];
static {
- IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.CELLULAR, "rmnet");
- IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.WIFI, "wlan");
- IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.BLUETOOTH, "bt-pan");
- // TODO: rekey to USB
- IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.ETHERNET, "usb");
- // TODO: add mappings for nan -> WIFI_AWARE and p2p -> WIFI_P2P
+ // Ordered from most likely link layer to least likely.
+ IFNAME_PREFIXES[0] = "rmnet";
+ IFNAME_LINKLAYERS[0] = IpConnectivityLogClass.CELLULAR;
+
+ IFNAME_PREFIXES[1] = "wlan";
+ IFNAME_LINKLAYERS[1] = IpConnectivityLogClass.WIFI;
+
+ IFNAME_PREFIXES[2] = "bt-pan";
+ IFNAME_LINKLAYERS[2] = IpConnectivityLogClass.BLUETOOTH;
+
+ IFNAME_PREFIXES[3] = "p2p";
+ IFNAME_LINKLAYERS[3] = IpConnectivityLogClass.WIFI_P2P;
+
+ IFNAME_PREFIXES[4] = "aware";
+ IFNAME_LINKLAYERS[4] = IpConnectivityLogClass.WIFI_NAN;
+
+ IFNAME_PREFIXES[5] = "eth";
+ IFNAME_LINKLAYERS[5] = IpConnectivityLogClass.ETHERNET;
+
+ IFNAME_PREFIXES[6] = "wpan";
+ IFNAME_LINKLAYERS[6] = IpConnectivityLogClass.LOWPAN;
}
}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 10c8b8b..e6585ad 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -33,7 +33,7 @@
/**
* Class to manage a 464xlat CLAT daemon. Nat464Xlat is not thread safe and should be manipulated
- * from a consistent and unique thread context. It is the responsability of ConnectivityService to
+ * from a consistent and unique thread context. It is the responsibility of ConnectivityService to
* call into this class from its own Handler thread.
*
* @hide
@@ -60,7 +60,9 @@
private enum State {
IDLE, // start() not called. Base iface and stacked iface names are null.
STARTING, // start() called. Base iface and stacked iface names are known.
- RUNNING; // start() called, and the stacked iface is known to be up.
+ RUNNING, // start() called, and the stacked iface is known to be up.
+ STOPPING; // stop() called, this Nat464Xlat is still registered as a network observer for
+ // the stacked interface.
}
private String mBaseIface;
@@ -81,6 +83,8 @@
// TODO: migrate to NetworkCapabilities.TRANSPORT_*.
final int netType = nai.networkInfo.getType();
final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType());
+ // TODO: this should also consider if the network is in SUSPENDED state to avoid stopping
+ // clatd in SUSPENDED state.
final boolean connected = nai.networkInfo.isConnected();
// We only run clat on networks that don't have a native IPv4 address.
final boolean hasIPv4Address =
@@ -111,18 +115,70 @@
}
/**
- * Sets internal state.
+ * @return true if clatd has been stopped.
+ */
+ public boolean isStopping() {
+ return mState == State.STOPPING;
+ }
+
+ /**
+ * Start clatd, register this Nat464Xlat as a network observer for the stacked interface,
+ * and set internal state.
*/
private void enterStartingState(String baseIface) {
+ try {
+ mNMService.registerObserver(this);
+ } catch(RemoteException e) {
+ Slog.e(TAG,
+ "startClat: Can't register interface observer for clat on " + mNetwork.name());
+ return;
+ }
+ try {
+ mNMService.startClatd(baseIface);
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.e(TAG, "Error starting clatd on " + baseIface, e);
+ }
mIface = CLAT_PREFIX + baseIface;
mBaseIface = baseIface;
mState = State.STARTING;
}
/**
- * Clears internal state.
+ * Enter running state just after getting confirmation that the stacked interface is up, and
+ * turn ND offload off if on WiFi.
+ */
+ private void enterRunningState() {
+ maybeSetIpv6NdOffload(mBaseIface, false);
+ mState = State.RUNNING;
+ }
+
+ /**
+ * Stop clatd, and turn ND offload on if it had been turned off.
+ */
+ private void enterStoppingState() {
+ if (isRunning()) {
+ maybeSetIpv6NdOffload(mBaseIface, true);
+ }
+
+ try {
+ mNMService.stopClatd(mBaseIface);
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e);
+ }
+
+ mState = State.STOPPING;
+ }
+
+ /**
+ * Unregister as a base observer for the stacked interface, and clear internal state.
*/
private void enterIdleState() {
+ try {
+ mNMService.unregisterObserver(this);
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface, e);
+ }
+
mIface = null;
mBaseIface = null;
mState = State.IDLE;
@@ -142,27 +198,14 @@
return;
}
- try {
- mNMService.registerObserver(this);
- } catch(RemoteException e) {
- Slog.e(TAG, "startClat: Can't register interface observer for clat on " + mNetwork);
- return;
- }
-
String baseIface = mNetwork.linkProperties.getInterfaceName();
if (baseIface == null) {
Slog.e(TAG, "startClat: Can't start clat on null interface");
return;
}
// TODO: should we only do this if mNMService.startClatd() succeeds?
+ Slog.i(TAG, "Starting clatd on " + baseIface);
enterStartingState(baseIface);
-
- Slog.i(TAG, "Starting clatd on " + mBaseIface);
- try {
- mNMService.startClatd(mBaseIface);
- } catch(RemoteException|IllegalStateException e) {
- Slog.e(TAG, "Error starting clatd on " + mBaseIface, e);
- }
}
/**
@@ -170,18 +213,15 @@
*/
public void stop() {
if (!isStarted()) {
- Slog.e(TAG, "stopClat: already stopped or not started");
return;
}
-
Slog.i(TAG, "Stopping clatd on " + mBaseIface);
- try {
- mNMService.stopClatd(mBaseIface);
- } catch(RemoteException|IllegalStateException e) {
- Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e);
+
+ boolean wasStarting = isStarting();
+ enterStoppingState();
+ if (wasStarting) {
+ enterIdleState();
}
- // When clatd stops and its interface is deleted, handleInterfaceRemoved() will trigger
- // ConnectivityService#handleUpdateLinkProperties and call enterIdleState().
}
/**
@@ -255,55 +295,52 @@
if (!isStarting() || !up || !Objects.equals(mIface, iface)) {
return;
}
+
LinkAddress clatAddress = getLinkAddress(iface);
if (clatAddress == null) {
- Slog.e(TAG, "cladAddress was null for stacked iface " + iface);
+ Slog.e(TAG, "clatAddress was null for stacked iface " + iface);
return;
}
- mState = State.RUNNING;
+
Slog.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s",
mIface, mIface, mBaseIface));
-
- maybeSetIpv6NdOffload(mBaseIface, false);
+ enterRunningState();
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.addStackedLink(makeLinkProperties(clatAddress));
- mNetwork.connService.handleUpdateLinkProperties(mNetwork, lp);
+ mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp);
}
/**
* Removes stacked link on base link and transitions to IDLE state.
*/
private void handleInterfaceRemoved(String iface) {
- if (!isRunning() || !Objects.equals(mIface, iface)) {
+ if (!Objects.equals(mIface, iface)) {
+ return;
+ }
+ if (!isRunning() && !isStopping()) {
return;
}
Slog.i(TAG, "interface " + iface + " removed");
- // The interface going away likely means clatd has crashed. Ask netd to stop it,
- // because otherwise when we try to start it again on the same base interface netd
- // will complain that it's already started.
- try {
- mNMService.unregisterObserver(this);
- // TODO: add STOPPING state to avoid calling stopClatd twice.
- mNMService.stopClatd(mBaseIface);
- } catch(RemoteException|IllegalStateException e) {
- Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e);
+ if (!isStopping()) {
+ // Ensure clatd is stopped if stop() has not been called: this likely means that clatd
+ // has crashed.
+ enterStoppingState();
}
- maybeSetIpv6NdOffload(mBaseIface, true);
- LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
- lp.removeStackedLink(mIface);
enterIdleState();
- mNetwork.connService.handleUpdateLinkProperties(mNetwork, lp);
+ LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
+ lp.removeStackedLink(iface);
+ mNetwork.connService().handleUpdateLinkProperties(mNetwork, lp);
}
@Override
public void interfaceLinkStateChanged(String iface, boolean up) {
- mNetwork.handler.post(() -> { handleInterfaceLinkStateChanged(iface, up); });
+ mNetwork.handler().post(() -> { handleInterfaceLinkStateChanged(iface, up); });
}
@Override
public void interfaceRemoved(String iface) {
- mNetwork.handler.post(() -> { handleInterfaceRemoved(iface); });
+ mNetwork.handler().post(() -> { handleInterfaceRemoved(iface); });
}
@Override
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 7c4ef0f..e96f4b0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -249,9 +249,9 @@
private static final String TAG = ConnectivityService.class.getSimpleName();
private static final boolean VDBG = false;
- public final ConnectivityService connService;
+ private final ConnectivityService mConnService;
private final Context mContext;
- final Handler handler;
+ private final Handler mHandler;
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
@@ -263,13 +263,21 @@
linkProperties = lp;
networkCapabilities = nc;
currentScore = score;
- this.connService = connService;
+ mConnService = connService;
mContext = context;
- this.handler = handler;
- networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest);
+ mHandler = handler;
+ networkMonitor = mConnService.createNetworkMonitor(context, handler, this, defaultRequest);
networkMisc = misc;
}
+ public ConnectivityService connService() {
+ return mConnService;
+ }
+
+ public Handler handler() {
+ return mHandler;
+ }
+
// Functions for manipulating the requests satisfied by this network.
//
// These functions must only called on ConnectivityService's main thread.
@@ -432,7 +440,7 @@
private boolean ignoreWifiUnvalidationPenalty() {
boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- boolean avoidBadWifi = connService.avoidBadWifi() || avoidUnvalidated;
+ boolean avoidBadWifi = mConnService.avoidBadWifi() || avoidUnvalidated;
return isWifi && !avoidBadWifi && everValidated;
}
@@ -516,8 +524,8 @@
}
if (newExpiry > 0) {
- mLingerMessage = connService.makeWakeupMessage(
- mContext, handler,
+ mLingerMessage = mConnService.makeWakeupMessage(
+ mContext, mHandler,
"NETWORK_LINGER_COMPLETE." + network.netId,
EVENT_NETWORK_LINGER_COMPLETE, this);
mLingerMessage.schedule(newExpiry);
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 6d5c428..5eafe5f 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -30,6 +30,10 @@
import android.net.LinkProperties;
import android.net.NetworkStats;
import android.net.RouteInfo;
+import android.net.netlink.ConntrackMessage;
+import android.net.netlink.NetlinkConstants;
+import android.net.netlink.NetlinkSocket;
+import android.net.util.IpUtils;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -37,10 +41,12 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.OsConstants;
import android.text.TextUtils;
-import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import java.net.Inet4Address;
import java.net.Inet6Address;
@@ -63,6 +69,9 @@
*/
public class OffloadController {
private static final String TAG = OffloadController.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final String ANYIP = "0.0.0.0";
+ private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
@@ -94,6 +103,9 @@
// includes upstream interfaces that have a quota set.
private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
+ private int mNatUpdateCallbacksReceived;
+ private int mNatUpdateNetlinkErrors;
+
public OffloadController(Handler h, OffloadHardwareInterface hwi,
ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) {
mHandler = h;
@@ -113,12 +125,12 @@
}
}
- public void start() {
- if (started()) return;
+ public boolean start() {
+ if (started()) return true;
if (isOffloadDisabled()) {
mLog.i("tethering offload disabled");
- return;
+ return false;
}
if (!mConfigInitialized) {
@@ -126,11 +138,14 @@
if (!mConfigInitialized) {
mLog.i("tethering offload config not supported");
stop();
- return;
+ return false;
}
}
mControlInitialized = mHwInterface.initOffloadControl(
+ // OffloadHardwareInterface guarantees that these callback
+ // methods are called on the handler passed to it, which is the
+ // same as mHandler, as coordinated by the setup in Tethering.
new OffloadHardwareInterface.ControlCallback() {
@Override
public void onStarted() {
@@ -148,6 +163,14 @@
public void onStoppedUnsupported() {
if (!started()) return;
mLog.log("onStoppedUnsupported");
+ // Poll for statistics and trigger a sweep of tethering
+ // stats by observers. This might not succeed, but it's
+ // worth trying anyway. We need to do this because from
+ // this point on we continue with software forwarding,
+ // and we need to synchronize stats and limits between
+ // software and hardware forwarding.
+ updateStatsForAllUpstreams();
+ forceTetherStatsPoll();
}
@Override
@@ -155,11 +178,15 @@
if (!started()) return;
mLog.log("onSupportAvailable");
- // [1] Poll for statistics and notify NetworkStats
- // [2] (Re)Push all state:
- // [a] push local prefixes
- // [b] push downstreams
- // [c] push upstream parameters
+ // [1] Poll for statistics and trigger a sweep of stats
+ // by observers. We need to do this to ensure that any
+ // limits set take into account any software tethering
+ // traffic that has been happening in the meantime.
+ updateStatsForAllUpstreams();
+ forceTetherStatsPoll();
+ // [2] (Re)Push all state.
+ // TODO: computeAndPushLocalPrefixes()
+ // TODO: push all downstream state.
pushUpstreamParameters(null);
}
@@ -181,12 +208,7 @@
// The stats for the previous upstream were already updated on this thread
// just after the upstream was changed, so they are also up-to-date.
updateStatsForCurrentUpstream();
-
- try {
- mNms.tetherLimitReached(mStatsProvider);
- } catch (RemoteException e) {
- mLog.e("Cannot report data limit reached: " + e);
- }
+ forceTetherStatsPoll();
}
@Override
@@ -194,15 +216,20 @@
String srcAddr, int srcPort,
String dstAddr, int dstPort) {
if (!started()) return;
- mLog.log(String.format("NAT timeout update: %s (%s,%s) -> (%s,%s)",
- proto, srcAddr, srcPort, dstAddr, dstPort));
+ updateNatTimeout(proto, srcAddr, srcPort, dstAddr, dstPort);
}
});
- if (!mControlInitialized) {
+
+ final boolean isStarted = started();
+ if (!isStarted) {
mLog.i("tethering offload control not supported");
stop();
+ } else {
+ mLog.log("tethering offload started");
+ mNatUpdateCallbacksReceived = 0;
+ mNatUpdateNetlinkErrors = 0;
}
- mLog.log("tethering offload started");
+ return isStarted;
}
public void stop() {
@@ -218,6 +245,10 @@
if (wasStarted) mLog.log("tethering offload stopped");
}
+ private boolean started() {
+ return mConfigInitialized && mControlInitialized;
+ }
+
private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub {
@Override
public NetworkStats getTetherStats(int how) {
@@ -305,13 +336,33 @@
maybeUpdateStats(currentUpstreamInterface());
}
+ private void updateStatsForAllUpstreams() {
+ // In practice, there should only ever be a single digit number of
+ // upstream interfaces over the lifetime of an active tethering session.
+ // Roughly speaking, imagine a very ambitious one or two of each of the
+ // following interface types: [ "rmnet_data", "wlan", "eth", "rndis" ].
+ for (Map.Entry<String, ForwardedStats> kv : mForwardedStats.entrySet()) {
+ maybeUpdateStats(kv.getKey());
+ }
+ }
+
+ private void forceTetherStatsPoll() {
+ try {
+ mNms.tetherLimitReached(mStatsProvider);
+ } catch (RemoteException e) {
+ mLog.e("Cannot report data limit reached: " + e);
+ }
+ }
+
public void setUpstreamLinkProperties(LinkProperties lp) {
if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
- String prevUpstream = (mUpstreamLinkProperties != null) ?
- mUpstreamLinkProperties.getInterfaceName() : null;
+ final String prevUpstream = currentUpstreamInterface();
mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null;
+ // Make sure we record this interface in the ForwardedStats map.
+ final String iface = currentUpstreamInterface();
+ if (!TextUtils.isEmpty(iface)) mForwardedStats.putIfAbsent(iface, EMPTY_STATS);
// TODO: examine return code and decide what to do if programming
// upstream parameters fails (probably just wait for a subsequent
@@ -373,21 +424,21 @@
mContentResolver, TETHER_OFFLOAD_DISABLED, defaultDisposition) != 0);
}
- private boolean started() {
- return mConfigInitialized && mControlInitialized;
- }
-
private boolean pushUpstreamParameters(String prevUpstream) {
- if (mUpstreamLinkProperties == null) {
+ final String iface = currentUpstreamInterface();
+
+ if (TextUtils.isEmpty(iface)) {
+ final boolean rval = mHwInterface.setUpstreamParameters("", ANYIP, ANYIP, null);
+ // Update stats after we've told the hardware to stop forwarding so
+ // we don't miss packets.
maybeUpdateStats(prevUpstream);
- return mHwInterface.setUpstreamParameters(null, null, null, null);
+ return rval;
}
// A stacked interface cannot be an upstream for hardware offload.
// Consequently, we examine only the primary interface name, look at
// getAddresses() rather than getAllAddresses(), and check getRoutes()
// rather than getAllRoutes().
- final String iface = mUpstreamLinkProperties.getInterfaceName();
final ArrayList<String> v6gateways = new ArrayList<>();
String v4addr = null;
String v4gateway = null;
@@ -483,10 +534,113 @@
pw.println("Offload disabled");
return;
}
- pw.println("Offload HALs " + (started() ? "started" : "not started"));
+ final boolean isStarted = started();
+ pw.println("Offload HALs " + (isStarted ? "started" : "not started"));
LinkProperties lp = mUpstreamLinkProperties;
String upstream = (lp != null) ? lp.getInterfaceName() : null;
pw.println("Current upstream: " + upstream);
pw.println("Exempt prefixes: " + mLastLocalPrefixStrs);
+ pw.println("NAT timeout update callbacks received during the "
+ + (isStarted ? "current" : "last")
+ + " offload session: "
+ + mNatUpdateCallbacksReceived);
+ pw.println("NAT timeout update netlink errors during the "
+ + (isStarted ? "current" : "last")
+ + " offload session: "
+ + mNatUpdateNetlinkErrors);
+ }
+
+ private void updateNatTimeout(
+ int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) {
+ final String protoName = protoNameFor(proto);
+ if (protoName == null) {
+ mLog.e("Unknown NAT update callback protocol: " + proto);
+ return;
+ }
+
+ final Inet4Address src = parseIPv4Address(srcAddr);
+ if (src == null) {
+ mLog.e("Failed to parse IPv4 address: " + srcAddr);
+ return;
+ }
+
+ if (!IpUtils.isValidUdpOrTcpPort(srcPort)) {
+ mLog.e("Invalid src port: " + srcPort);
+ return;
+ }
+
+ final Inet4Address dst = parseIPv4Address(dstAddr);
+ if (dst == null) {
+ mLog.e("Failed to parse IPv4 address: " + dstAddr);
+ return;
+ }
+
+ if (!IpUtils.isValidUdpOrTcpPort(dstPort)) {
+ mLog.e("Invalid dst port: " + dstPort);
+ return;
+ }
+
+ mNatUpdateCallbacksReceived++;
+ if (DBG) {
+ mLog.log(String.format("NAT timeout update: %s (%s, %s) -> (%s, %s)",
+ protoName, srcAddr, srcPort, dstAddr, dstPort));
+ }
+
+ final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto);
+ final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ proto, src, srcPort, dst, dstPort, timeoutSec);
+
+ try {
+ NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg);
+ } catch (ErrnoException e) {
+ mNatUpdateNetlinkErrors++;
+ mLog.e("Error updating NAT conntrack entry: " + e
+ + ", msg: " + NetlinkConstants.hexify(msg));
+ mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived);
+ mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors);
+ }
+ }
+
+ private static Inet4Address parseIPv4Address(String addrString) {
+ try {
+ final InetAddress ip = InetAddress.parseNumericAddress(addrString);
+ // TODO: Consider other sanitization steps here, including perhaps:
+ // not eql to 0.0.0.0
+ // not within 169.254.0.0/16
+ // not within ::ffff:0.0.0.0/96
+ // not within ::/96
+ // et cetera.
+ if (ip instanceof Inet4Address) {
+ return (Inet4Address) ip;
+ }
+ } catch (IllegalArgumentException iae) {}
+ return null;
+ }
+
+ private static String protoNameFor(int proto) {
+ // OsConstants values are not constant expressions; no switch statement.
+ if (proto == OsConstants.IPPROTO_UDP) {
+ return "UDP";
+ } else if (proto == OsConstants.IPPROTO_TCP) {
+ return "TCP";
+ }
+ return null;
+ }
+
+ private static int connectionTimeoutUpdateSecondsFor(int proto) {
+ // TODO: Replace this with more thoughtful work, perhaps reading from
+ // and maybe writing to any required
+ //
+ // /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_*
+ // /proc/sys/net/netfilter/nf_conntrack_udp_timeout{,_stream}
+ //
+ // entries. TBD.
+ if (proto == OsConstants.IPPROTO_TCP) {
+ // Cf. /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
+ return 432000;
+ } else {
+ // Cf. /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream
+ return 180;
+ }
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 865a989..553fd8c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -21,10 +21,12 @@
import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.os.Handler;
import android.os.RemoteException;
import android.net.util.SharedLog;
+import android.system.OsConstants;
import java.util.ArrayList;
@@ -327,13 +329,24 @@
public void updateTimeout(NatTimeoutUpdate params) {
handler.post(() -> {
controlCb.onNatTimeoutUpdate(
- params.proto,
+ networkProtocolToOsConstant(params.proto),
params.src.addr, uint16(params.src.port),
params.dst.addr, uint16(params.dst.port));
});
}
}
+ private static int networkProtocolToOsConstant(int proto) {
+ switch (proto) {
+ case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
+ case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
+ default:
+ // The caller checks this value and will log an error. Just make
+ // sure it won't collide with valid OsContants.IPPROTO_* values.
+ return -Math.abs(proto);
+ }
+ }
+
private static class CbResults {
boolean success;
String errMsg;
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 57d2502..17adb1a 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -27,6 +27,7 @@
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.RouteInfo;
+import android.net.ip.InterfaceController;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.util.NetdService;
@@ -107,8 +108,10 @@
private final SharedLog mLog;
private final INetworkManagementService mNMService;
+ private final INetd mNetd;
private final INetworkStatsService mStatsService;
private final IControlsTethering mTetherController;
+ private final InterfaceController mInterfaceCtrl;
private final String mIfaceName;
private final int mInterfaceType;
@@ -136,8 +139,11 @@
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
mNMService = nMService;
+ // TODO: This should be passed in for testability.
+ mNetd = NetdService.getInstance();
mStatsService = statsService;
mTetherController = tetherController;
+ mInterfaceCtrl = new InterfaceController(ifaceName, nMService, mNetd, mLog);
mIfaceName = ifaceName;
mInterfaceType = interfaceType;
mLinkProperties = new LinkProperties();
@@ -179,6 +185,7 @@
private void stopIPv4() { configureIPv4(false); }
+ // TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
@@ -381,8 +388,8 @@
private void configureLocalIPv6Dns(
HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) {
- final INetd netd = NetdService.getInstance();
- if (netd == null) {
+ // TODO: Is this really necessary? Can we not fail earlier if INetd cannot be located?
+ if (mNetd == null) {
if (newDnses != null) newDnses.clear();
mLog.e("No netd service instance available; not setting local IPv6 addresses");
return;
@@ -391,11 +398,8 @@
// [1] Remove deprecated local DNS IP addresses.
if (!deprecatedDnses.isEmpty()) {
for (Inet6Address dns : deprecatedDnses) {
- final String dnsString = dns.getHostAddress();
- try {
- netd.interfaceDelAddress(mIfaceName, dnsString, RFC7421_PREFIX_LENGTH);
- } catch (ServiceSpecificException | RemoteException e) {
- mLog.e("Failed to remove local dns IP " + dnsString + ": " + e);
+ if (!mInterfaceCtrl.removeAddress(dns, RFC7421_PREFIX_LENGTH)) {
+ mLog.e("Failed to remove local dns IP " + dns);
}
mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
@@ -410,11 +414,8 @@
}
for (Inet6Address dns : addedDnses) {
- final String dnsString = dns.getHostAddress();
- try {
- netd.interfaceAddAddress(mIfaceName, dnsString, RFC7421_PREFIX_LENGTH);
- } catch (ServiceSpecificException | RemoteException e) {
- mLog.e("Failed to add local dns IP " + dnsString + ": " + e);
+ if (!mInterfaceCtrl.addAddress(dns, RFC7421_PREFIX_LENGTH)) {
+ mLog.e("Failed to add local dns IP " + dns);
newDnses.remove(dns);
}
@@ -423,7 +424,7 @@
}
try {
- netd.tetherApplyDnsInterfaces();
+ mNetd.tetherApplyDnsInterfaces();
} catch (ServiceSpecificException | RemoteException e) {
mLog.e("Failed to update local DNS caching server");
if (newDnses != null) newDnses.clear();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d9ca00c..ea260a0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -4184,7 +4184,7 @@
}
public static String getString(int uid, long procStateSeq) {
- return "UID=" + uid + " procStateSeq=" + procStateSeq;
+ return "UID=" + uid + " Seq=" + procStateSeq;
}
private int increaseNext(int next, int increment) {
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 04d91f8..807c343 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -92,26 +92,10 @@
return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
}
- boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) {
- // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
- return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath()));
- }
-
private String getIdmapPath(@NonNull final String baseCodePath) {
final StringBuilder sb = new StringBuilder("/data/resource-cache/");
sb.append(baseCodePath.substring(1).replace('/', '@'));
sb.append("@idmap");
return sb.toString();
}
-
- private boolean isDangerous(@NonNull final String idmapPath) {
- try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) {
- final int magic = dis.readInt();
- final int version = dis.readInt();
- final int dangerous = dis.readInt();
- return dangerous != 0;
- } catch (IOException e) {
- return true;
- }
- }
}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 8cb2df7..190b3a6 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -180,6 +180,7 @@
private static final int ETH_DEST_ADDR_OFFSET = 0;
private static final int ETH_ETHERTYPE_OFFSET = 12;
private static final int ETH_TYPE_MIN = 0x0600;
+ private static final int ETH_TYPE_MAX = 0xFFFF;
private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
{(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
// TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
@@ -232,6 +233,9 @@
private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
// Do not log ApfProgramEvents whose actual lifetimes was less than this.
private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2;
+ // Limit on the Black List size to cap on program usage for this
+ // TODO: Select a proper max length
+ private static final int APF_MAX_ETH_TYPE_BLACK_LIST_LEN = 20;
private final ApfCapabilities mApfCapabilities;
private final IpManager.Callback mIpManagerCallback;
@@ -247,6 +251,8 @@
@GuardedBy("this")
private boolean mMulticastFilter;
private final boolean mDrop802_3Frames;
+ private final int[] mEthTypeBlackList;
+
// Our IPv4 address, if we have just one, otherwise null.
@GuardedBy("this")
private byte[] mIPv4Address;
@@ -257,12 +263,16 @@
@VisibleForTesting
ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
IpManager.Callback ipManagerCallback, boolean multicastFilter,
- boolean ieee802_3Filter, IpConnectivityLog log) {
+ boolean ieee802_3Filter, int[] ethTypeBlackList, IpConnectivityLog log) {
mApfCapabilities = apfCapabilities;
mIpManagerCallback = ipManagerCallback;
mNetworkInterface = networkInterface;
mMulticastFilter = multicastFilter;
mDrop802_3Frames = ieee802_3Filter;
+
+ // Now fill the black list from the passed array
+ mEthTypeBlackList = filterEthTypeBlackList(ethTypeBlackList);
+
mMetricsLog = log;
// TODO: ApfFilter should not generate programs until IpManager sends provisioning success.
@@ -278,6 +288,35 @@
return mUniqueCounter++;
}
+ @GuardedBy("this")
+ private static int[] filterEthTypeBlackList(int[] ethTypeBlackList) {
+ ArrayList<Integer> bl = new ArrayList<Integer>();
+
+ for (int p : ethTypeBlackList) {
+ // Check if the protocol is a valid ether type
+ if ((p < ETH_TYPE_MIN) || (p > ETH_TYPE_MAX)) {
+ continue;
+ }
+
+ // Check if the protocol is not repeated in the passed array
+ if (bl.contains(p)) {
+ continue;
+ }
+
+ // Check if list reach its max size
+ if (bl.size() == APF_MAX_ETH_TYPE_BLACK_LIST_LEN) {
+ Log.w(TAG, "Passed EthType Black List size too large (" + bl.size() +
+ ") using top " + APF_MAX_ETH_TYPE_BLACK_LIST_LEN + " protocols");
+ break;
+ }
+
+ // Now add the protocol to the list
+ bl.add(p);
+ }
+
+ return bl.stream().mapToInt(Integer::intValue).toArray();
+ }
+
/**
* Attempt to start listening for RAs and, if RAs are received, generating and installing
* filters to ignore useless RAs.
@@ -891,6 +930,7 @@
* Begin generating an APF program to:
* <ul>
* <li>Drop/Pass 802.3 frames (based on policy)
+ * <li>Drop packets with EtherType within the Black List
* <li>Drop ARP requests not for us, if mIPv4Address is set,
* <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
* <li>Drop IPv4 multicast packets, if mMulticastFilter,
@@ -914,6 +954,8 @@
//
// if it's a 802.3 Frame (ethtype < 0x0600):
// drop or pass based on configurations
+ // if it has a ether-type that belongs to the black list
+ // drop
// if it's ARP:
// insert ARP filter to drop or pass these appropriately
// if it's IPv4:
@@ -931,6 +973,11 @@
gen.addJumpIfR0LessThan(ETH_TYPE_MIN, gen.DROP_LABEL);
}
+ // Handle ether-type black list
+ for (int p : mEthTypeBlackList) {
+ gen.addJumpIfR0Equals(p, gen.DROP_LABEL);
+ }
+
// Add ARP filters:
String skipArpFiltersLabel = "skipArpFilters";
gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
@@ -1115,7 +1162,7 @@
*/
public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities,
NetworkInterface networkInterface, IpManager.Callback ipManagerCallback,
- boolean multicastFilter, boolean ieee802_3Filter) {
+ boolean multicastFilter, boolean ieee802_3Filter, int[] ethTypeBlackList) {
if (apfCapabilities == null || networkInterface == null) return null;
if (apfCapabilities.apfVersionSupported == 0) return null;
if (apfCapabilities.maximumApfProgramSize < 512) {
@@ -1132,7 +1179,7 @@
return null;
}
return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback,
- multicastFilter, ieee802_3Filter, new IpConnectivityLog());
+ multicastFilter, ieee802_3Filter, ethTypeBlackList, new IpConnectivityLog());
}
public synchronized void shutdown() {
diff --git a/services/net/java/android/net/ip/InterfaceController.java b/services/net/java/android/net/ip/InterfaceController.java
new file mode 100644
index 0000000..02e4f87
--- /dev/null
+++ b/services/net/java/android/net/ip/InterfaceController.java
@@ -0,0 +1,162 @@
+/*
+ * 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.net.ip;
+
+import android.net.INetd;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.net.util.NetdService;
+import android.net.util.SharedLog;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.system.OsConstants;
+
+import java.net.InetAddress;
+
+
+/**
+ * Encapsulates the multiple IP configuration operations performed on an interface.
+ *
+ * TODO: refactor/eliminate the redundant ways to set and clear addresses.
+ *
+ * @hide
+ */
+public class InterfaceController {
+ private final static boolean DBG = false;
+
+ private final String mIfName;
+ private final INetworkManagementService mNMS;
+ private final INetd mNetd;
+ private final SharedLog mLog;
+
+ public InterfaceController(String ifname, INetworkManagementService nms, INetd netd,
+ SharedLog log) {
+ mIfName = ifname;
+ mNMS = nms;
+ mNetd = netd;
+ mLog = log;
+ }
+
+ public boolean setIPv4Address(LinkAddress address) {
+ final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(address);
+ try {
+ mNMS.setInterfaceConfig(mIfName, ifcg);
+ if (DBG) mLog.log("IPv4 configuration succeeded");
+ } catch (IllegalStateException | RemoteException e) {
+ logError("IPv4 configuration failed: %s", e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean clearIPv4Address() {
+ try {
+ final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(new LinkAddress("0.0.0.0/0"));
+ mNMS.setInterfaceConfig(mIfName, ifcg);
+ } catch (IllegalStateException | RemoteException e) {
+ logError("Failed to clear IPv4 address on interface %s: %s", mIfName, e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean enableIPv6() {
+ try {
+ mNMS.enableIpv6(mIfName);
+ } catch (IllegalStateException | RemoteException e) {
+ logError("enabling IPv6 failed: %s", e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean disableIPv6() {
+ try {
+ mNMS.disableIpv6(mIfName);
+ } catch (IllegalStateException | RemoteException e) {
+ logError("disabling IPv6 failed: %s", e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean setIPv6PrivacyExtensions(boolean enabled) {
+ try {
+ mNMS.setInterfaceIpv6PrivacyExtensions(mIfName, enabled);
+ } catch (IllegalStateException | RemoteException e) {
+ logError("error setting IPv6 privacy extensions: %s", e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean setIPv6AddrGenModeIfSupported(int mode) {
+ try {
+ mNMS.setIPv6AddrGenMode(mIfName, mode);
+ } catch (RemoteException e) {
+ logError("Unable to set IPv6 addrgen mode: %s", e);
+ return false;
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode != OsConstants.EOPNOTSUPP) {
+ logError("Unable to set IPv6 addrgen mode: %s", e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean addAddress(LinkAddress addr) {
+ return addAddress(addr.getAddress(), addr.getPrefixLength());
+ }
+
+ public boolean addAddress(InetAddress ip, int prefixLen) {
+ try {
+ mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen);
+ } catch (ServiceSpecificException | RemoteException e) {
+ logError("failed to add %s/%d: %s", ip, prefixLen, e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean removeAddress(InetAddress ip, int prefixLen) {
+ try {
+ mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen);
+ } catch (ServiceSpecificException | RemoteException e) {
+ logError("failed to remove %s/%d: %s", ip, prefixLen, e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean clearAllAddresses() {
+ try {
+ mNMS.clearInterfaceAddresses(mIfName);
+ } catch (Exception e) {
+ logError("Failed to clear addresses: %s", e);
+ return false;
+ }
+ return true;
+ }
+
+ private void logError(String fmt, Object... args) {
+ mLog.e(String.format(fmt, args));
+ }
+}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index c03ea38..b1eb085 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.net.DhcpResults;
import android.net.INetd;
-import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties.ProvisioningChange;
@@ -43,9 +42,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
import android.os.SystemClock;
-import android.system.OsConstants;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -568,7 +565,7 @@
private final LocalLog mConnectivityPacketLog;
private final MessageHandlingLogger mMsgStateLogger;
private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
- private final INetd mNetd;
+ private final InterfaceController mInterfaceCtrl;
private NetworkInterface mNetworkInterface;
@@ -612,12 +609,13 @@
mClatInterfaceName = CLAT_PREFIX + ifName;
mCallback = new LoggingCallbackWrapper(callback);
mNwService = nwService;
- mNetd = netd;
mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
mMsgStateLogger = new MessageHandlingLogger();
+ mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, netd, mLog);
+
mNetlinkTracker = new NetlinkTracker(
mInterfaceName,
new NetlinkTracker.Callback() {
@@ -1157,29 +1155,6 @@
return (delta != ProvisioningChange.LOST_PROVISIONING);
}
- private boolean setIPv4Address(LinkAddress address) {
- final InterfaceConfiguration ifcg = new InterfaceConfiguration();
- ifcg.setLinkAddress(address);
- try {
- mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- if (DBG) Log.d(mTag, "IPv4 configuration succeeded");
- } catch (IllegalStateException | RemoteException e) {
- logError("IPv4 configuration failed: %s", e);
- return false;
- }
- return true;
- }
-
- private void clearIPv4Address() {
- try {
- final InterfaceConfiguration ifcg = new InterfaceConfiguration();
- ifcg.setLinkAddress(new LinkAddress("0.0.0.0/0"));
- mNwService.setInterfaceConfig(mInterfaceName, ifcg);
- } catch (IllegalStateException | RemoteException e) {
- logError("Failed to clear IPv4 address on interface %s: %s", mInterfaceName, e);
- }
- }
-
private void handleIPv4Success(DhcpResults dhcpResults) {
mDhcpResults = new DhcpResults(dhcpResults);
final LinkProperties newLp = assembleLinkProperties();
@@ -1199,7 +1174,7 @@
// that could trigger a call to this function. If we missed handling
// that message in StartedState for some reason we would still clear
// any addresses upon entry to StoppedState.
- clearIPv4Address();
+ mInterfaceCtrl.clearIPv4Address();
mDhcpResults = null;
if (DBG) { Log.d(mTag, "onNewDhcpResults(null)"); }
mCallback.onNewDhcpResults(null);
@@ -1238,7 +1213,7 @@
// If we have a StaticIpConfiguration attempt to apply it and
// handle the result accordingly.
if (mConfiguration.mStaticIpConfig != null) {
- if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
+ if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
return false;
@@ -1253,46 +1228,16 @@
return true;
}
- private void setIPv6AddrGenModeIfSupported() throws RemoteException {
- try {
- mNwService.setIPv6AddrGenMode(mInterfaceName, mConfiguration.mIPv6AddrGenMode);
- } catch (ServiceSpecificException e) {
- if (e.errorCode != OsConstants.EOPNOTSUPP) {
- logError("Unable to set IPv6 addrgen mode: %s", e);
- }
- }
- }
-
private boolean startIPv6() {
- // Set privacy extensions.
- try {
- mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
-
- setIPv6AddrGenModeIfSupported();
- mNwService.enableIpv6(mInterfaceName);
- } catch (IllegalStateException | RemoteException | ServiceSpecificException e) {
- logError("Unable to change interface settings: %s", e);
- return false;
- }
-
- return true;
+ return mInterfaceCtrl.setIPv6PrivacyExtensions(true) &&
+ mInterfaceCtrl.setIPv6AddrGenModeIfSupported(mConfiguration.mIPv6AddrGenMode) &&
+ mInterfaceCtrl.enableIPv6();
}
private boolean applyInitialConfig(InitialConfiguration config) {
- if (mNetd == null) {
- logError("tried to add %s to %s but INetd was null", config, mInterfaceName);
- return false;
- }
-
// TODO: also support specifying a static IPv4 configuration in InitialConfiguration.
for (LinkAddress addr : findAll(config.ipAddresses, LinkAddress::isIPv6)) {
- try {
- mNetd.interfaceAddAddress(
- mInterfaceName, addr.getAddress().getHostAddress(), addr.getPrefixLength());
- } catch (ServiceSpecificException | RemoteException e) {
- logError("failed to add %s to %s: %s", addr, mInterfaceName, e);
- return false;
- }
+ if (!mInterfaceCtrl.addAddress(addr)) return false;
}
return true;
@@ -1329,17 +1274,8 @@
// - we don't get IPv4 routes from netlink
// so we neither react to nor need to wait for changes in either.
- try {
- mNwService.disableIpv6(mInterfaceName);
- } catch (Exception e) {
- logError("Failed to disable IPv6: %s", e);
- }
-
- try {
- mNwService.clearInterfaceAddresses(mInterfaceName);
- } catch (Exception e) {
- logError("Failed to clear addresses: %s", e);
- }
+ mInterfaceCtrl.disableIPv6();
+ mInterfaceCtrl.clearAllAddresses();
}
class StoppedState extends State {
@@ -1418,7 +1354,7 @@
break;
case DhcpClient.CMD_CLEAR_LINKADDRESS:
- clearIPv4Address();
+ mInterfaceCtrl.clearIPv4Address();
break;
case DhcpClient.CMD_ON_QUIT:
@@ -1508,8 +1444,11 @@
boolean filter802_3Frames =
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
+ int[] ethTypeBlackList = mContext.getResources().getIntArray(
+ R.array.config_apfEthTypeBlackList);
+
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
- mCallback, mMulticastFiltering, filter802_3Frames);
+ mCallback, mMulticastFiltering, filter802_3Frames, ethTypeBlackList);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1671,12 +1610,12 @@
break;
case DhcpClient.CMD_CLEAR_LINKADDRESS:
- clearIPv4Address();
+ mInterfaceCtrl.clearIPv4Address();
break;
case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {
final LinkAddress ipAddress = (LinkAddress) msg.obj;
- if (setIPv4Address(ipAddress)) {
+ if (mInterfaceCtrl.setIPv4Address(ipAddress)) {
mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);
} else {
logError("Failed to set IPv4 address.");
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index e833f6a..714b35a 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -205,44 +205,14 @@
final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage(
1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
- int errno = -OsConstants.EPROTO;
- try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) {
- final long IO_TIMEOUT = 300L;
- nlSocket.connectToKernel();
- nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT);
- final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT);
- // recvMessage() guaranteed to not return null if it did not throw.
- final NetlinkMessage response = NetlinkMessage.parse(bytes);
- if (response != null && response instanceof NetlinkErrorMessage &&
- (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
- errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
- if (errno != 0) {
- // TODO: consider ignoring EINVAL (-22), which appears to be
- // normal when probing a neighbor for which the kernel does
- // not already have / no longer has a link layer address.
- Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + response.toString());
- }
- } else {
- String errmsg;
- if (response == null) {
- bytes.position(0);
- errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
- } else {
- errmsg = response.toString();
- }
- Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + errmsg);
- }
+ try {
+ NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_ROUTE, msg);
} catch (ErrnoException e) {
- Log.e(TAG, "Error " + msgSnippet, e);
- errno = -e.errno;
- } catch (InterruptedIOException e) {
- Log.e(TAG, "Error " + msgSnippet, e);
- errno = -OsConstants.ETIMEDOUT;
- } catch (SocketException e) {
- Log.e(TAG, "Error " + msgSnippet, e);
- errno = -OsConstants.EIO;
+ Log.e(TAG, "Error " + msgSnippet + ": " + e);
+ return -e.errno;
}
- return errno;
+
+ return 0;
}
public IpReachabilityMonitor(Context context, String ifName, SharedLog log, Callback callback) {
diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java
new file mode 100644
index 0000000..605c46b
--- /dev/null
+++ b/services/net/java/android/net/netlink/ConntrackMessage.java
@@ -0,0 +1,117 @@
+/*
+ * 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.net.netlink;
+
+import static android.net.netlink.NetlinkConstants.alignedLengthOf;
+import static android.net.netlink.StructNlAttr.makeNestedType;
+import static android.net.netlink.StructNlAttr.NLA_HEADERLEN;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+import static android.net.util.NetworkConstants.IPV4_ADDR_LEN;
+import static java.nio.ByteOrder.BIG_ENDIAN;
+
+import android.system.OsConstants;
+import android.util.Log;
+import libcore.io.SizeOf;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+/**
+ * A NetlinkMessage subclass for netlink conntrack messages.
+ *
+ * see also: <linux_src>/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+ *
+ * @hide
+ */
+public class ConntrackMessage extends NetlinkMessage {
+ public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
+
+ public static final short NFNL_SUBSYS_CTNETLINK = 1;
+ public static final short IPCTNL_MSG_CT_NEW = 0;
+
+ // enum ctattr_type
+ public static final short CTA_TUPLE_ORIG = 1;
+ public static final short CTA_TUPLE_REPLY = 2;
+ public static final short CTA_TIMEOUT = 7;
+
+ // enum ctattr_tuple
+ public static final short CTA_TUPLE_IP = 1;
+ public static final short CTA_TUPLE_PROTO = 2;
+
+ // enum ctattr_ip
+ public static final short CTA_IP_V4_SRC = 1;
+ public static final short CTA_IP_V4_DST = 2;
+
+ // enum ctattr_l4proto
+ public static final short CTA_PROTO_NUM = 1;
+ public static final short CTA_PROTO_SRC_PORT = 2;
+ public static final short CTA_PROTO_DST_PORT = 3;
+
+ public static byte[] newIPv4TimeoutUpdateRequest(
+ int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
+ // *** STYLE WARNING ***
+ //
+ // Code below this point uses extra block indentation to highlight the
+ // packing of nested tuple netlink attribute types.
+ final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
+ new StructNlAttr(CTA_TUPLE_IP,
+ new StructNlAttr(CTA_IP_V4_SRC, src),
+ new StructNlAttr(CTA_IP_V4_DST, dst)),
+ new StructNlAttr(CTA_TUPLE_PROTO,
+ new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
+ new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
+ new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
+
+ final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
+
+ final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
+ final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+ byteBuffer.order(ByteOrder.nativeOrder());
+
+ final ConntrackMessage ctmsg = new ConntrackMessage();
+ ctmsg.mHeader.nlmsg_len = bytes.length;
+ ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
+ ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
+ ctmsg.mHeader.nlmsg_seq = 1;
+ ctmsg.pack(byteBuffer);
+
+ ctaTupleOrig.pack(byteBuffer);
+ ctaTimeout.pack(byteBuffer);
+
+ return bytes;
+ }
+
+ protected StructNfGenMsg mNfGenMsg;
+
+ private ConntrackMessage() {
+ super(new StructNlMsgHdr());
+ mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
+ }
+
+ public void pack(ByteBuffer byteBuffer) {
+ mHeader.pack(byteBuffer);
+ mNfGenMsg.pack(byteBuffer);
+ }
+}
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 657d48c..a9e0cd9 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -51,6 +51,47 @@
private long mLastRecvTimeoutMs;
private long mLastSendTimeoutMs;
+ public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
+ final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
+
+ try (NetlinkSocket nlSocket = new NetlinkSocket(nlProto)) {
+ final long IO_TIMEOUT = 300L;
+ nlSocket.connectToKernel();
+ nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT);
+ final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT);
+ // recvMessage() guaranteed to not return null if it did not throw.
+ final NetlinkMessage response = NetlinkMessage.parse(bytes);
+ if (response != null && response instanceof NetlinkErrorMessage &&
+ (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
+ final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
+ if (errno != 0) {
+ // TODO: consider ignoring EINVAL (-22), which appears to be
+ // normal when probing a neighbor for which the kernel does
+ // not already have / no longer has a link layer address.
+ Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
+ // Note: convert kernel errnos (negative) into userspace errnos (positive).
+ throw new ErrnoException(response.toString(), Math.abs(errno));
+ }
+ } else {
+ final String errmsg;
+ if (response == null) {
+ bytes.position(0);
+ errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
+ } else {
+ errmsg = response.toString();
+ }
+ Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
+ throw new ErrnoException(errmsg, OsConstants.EPROTO);
+ }
+ } catch (InterruptedIOException e) {
+ Log.e(TAG, errPrefix, e);
+ throw new ErrnoException(errPrefix, OsConstants.ETIMEDOUT, e);
+ } catch (SocketException e) {
+ Log.e(TAG, errPrefix, e);
+ throw new ErrnoException(errPrefix, OsConstants.EIO, e);
+ }
+ }
+
public NetlinkSocket(int nlProto) throws ErrnoException {
mDescriptor = Os.socket(
OsConstants.AF_NETLINK, OsConstants.SOCK_DGRAM, nlProto);
diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
index 02df131..e784fbb 100644
--- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
+++ b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
@@ -36,7 +36,7 @@
/**
- * A NetlinkMessage subclass for netlink error messages.
+ * A NetlinkMessage subclass for rtnetlink neighbor messages.
*
* see also: <linux_src>/include/uapi/linux/neighbour.h
*
diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java
new file mode 100644
index 0000000..99695e2
--- /dev/null
+++ b/services/net/java/android/net/netlink/StructNfGenMsg.java
@@ -0,0 +1,51 @@
+/*
+ * 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.net.netlink;
+
+import libcore.io.SizeOf;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * struct nfgenmsg
+ *
+ * see <linux_src>/include/uapi/linux/netfilter/nfnetlink.h
+ *
+ * @hide
+ */
+public class StructNfGenMsg {
+ public static final int STRUCT_SIZE = 2 + SizeOf.SHORT;
+
+ public static final int NFNETLINK_V0 = 0;
+
+ final public byte nfgen_family;
+ final public byte version;
+ final public short res_id; // N.B.: this is big endian in the kernel
+
+ public StructNfGenMsg(byte family) {
+ nfgen_family = family;
+ version = (byte) NFNETLINK_V0;
+ res_id = (short) 0;
+ }
+
+ public void pack(ByteBuffer byteBuffer) {
+ byteBuffer.put(nfgen_family);
+ byteBuffer.put(version);
+ byteBuffer.putShort(res_id);
+ }
+}
diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
index 597a6aa..811bdbb 100644
--- a/services/net/java/android/net/netlink/StructNlAttr.java
+++ b/services/net/java/android/net/netlink/StructNlAttr.java
@@ -34,7 +34,12 @@
*/
public class StructNlAttr {
// Already aligned.
- public static final int NLA_HEADERLEN = 4;
+ public static final int NLA_HEADERLEN = 4;
+ public static final int NLA_F_NESTED = (1 << 15);
+
+ public static short makeNestedType(short type) {
+ return (short) (type | NLA_F_NESTED);
+ }
// Return a (length, type) object only, without consuming any bytes in
// |byteBuffer| and without copying or interpreting any value bytes.
@@ -46,10 +51,17 @@
}
final int baseOffset = byteBuffer.position();
- final StructNlAttr struct = new StructNlAttr();
- struct.nla_len = byteBuffer.getShort();
- struct.nla_type = byteBuffer.getShort();
- struct.mByteOrder = byteBuffer.order();
+ // Assume the byte order of the buffer is the expected byte order of the value.
+ final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
+ // The byte order of nla_len and nla_type is always native.
+ final ByteOrder originalOrder = byteBuffer.order();
+ byteBuffer.order(ByteOrder.nativeOrder());
+ try {
+ struct.nla_len = byteBuffer.getShort();
+ struct.nla_type = byteBuffer.getShort();
+ } finally {
+ byteBuffer.order(originalOrder);
+ }
byteBuffer.position(baseOffset);
if (struct.nla_len < NLA_HEADERLEN) {
@@ -78,13 +90,65 @@
return struct;
}
- public short nla_len;
+ public short nla_len = (short) NLA_HEADERLEN;
public short nla_type;
public byte[] nla_value;
- public ByteOrder mByteOrder;
- public StructNlAttr() {
- mByteOrder = ByteOrder.nativeOrder();
+ // The byte order used to read/write the value member. Netlink length and
+ // type members are always read/written in native order.
+ private ByteOrder mByteOrder = ByteOrder.nativeOrder();
+
+ public StructNlAttr() {}
+
+ public StructNlAttr(ByteOrder byteOrder) {
+ mByteOrder = byteOrder;
+ }
+
+ public StructNlAttr(short type, byte value) {
+ nla_type = type;
+ setValue(new byte[1]);
+ nla_value[0] = value;
+ }
+
+ public StructNlAttr(short type, short value) {
+ this(type, value, ByteOrder.nativeOrder());
+ }
+
+ public StructNlAttr(short type, short value, ByteOrder order) {
+ this(order);
+ nla_type = type;
+ setValue(new byte[SizeOf.SHORT]);
+ getValueAsByteBuffer().putShort(value);
+ }
+
+ public StructNlAttr(short type, int value) {
+ this(type, value, ByteOrder.nativeOrder());
+ }
+
+ public StructNlAttr(short type, int value, ByteOrder order) {
+ this(order);
+ nla_type = type;
+ setValue(new byte[SizeOf.INT]);
+ getValueAsByteBuffer().putInt(value);
+ }
+
+ public StructNlAttr(short type, InetAddress ip) {
+ nla_type = type;
+ setValue(ip.getAddress());
+ }
+
+ public StructNlAttr(short type, StructNlAttr... nested) {
+ this();
+ nla_type = makeNestedType(type);
+
+ int payloadLength = 0;
+ for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
+ setValue(new byte[payloadLength]);
+
+ final ByteBuffer buf = getValueAsByteBuffer();
+ for (StructNlAttr nla : nested) {
+ nla.pack(buf);
+ }
}
public int getAlignedLength() {
@@ -117,13 +181,25 @@
}
public void pack(ByteBuffer byteBuffer) {
+ final ByteOrder originalOrder = byteBuffer.order();
final int originalPosition = byteBuffer.position();
- byteBuffer.putShort(nla_len);
- byteBuffer.putShort(nla_type);
- byteBuffer.put(nla_value);
+
+ byteBuffer.order(ByteOrder.nativeOrder());
+ try {
+ byteBuffer.putShort(nla_len);
+ byteBuffer.putShort(nla_type);
+ if (nla_value != null) byteBuffer.put(nla_value);
+ } finally {
+ byteBuffer.order(originalOrder);
+ }
byteBuffer.position(originalPosition + getAlignedLength());
}
+ private void setValue(byte[] value) {
+ nla_value = value;
+ nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
+ }
+
@Override
public String toString() {
return "StructNlAttr{ "
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index d0b36c9..fdb1f09 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1307,10 +1307,7 @@
/**
* Returns whether TTY is supported on this device.
- *
- * @hide
*/
- @SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PHONE_STATE
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index fe8774f..3c841a4 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -199,7 +199,7 @@
/** Display carrier settings menu if true */
public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
- /** Does not display additional call seting for IMS phone based on GSM Phone */
+ /** Does not display additional call setting for IMS phone based on GSM Phone */
public static final String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
/** Show APN Settings for some CDMA carriers */
@@ -1500,6 +1500,14 @@
public static final String IMSI_KEY_EXPIRATION_DAYS_TIME_INT =
"imsi_key_expiration_days_time_int";
+ /**
+ * Flag specifying whether IMS registration state menu is shown in Status Info setting,
+ * default to false.
+ * @hide
+ */
+ public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL =
+ "show_ims_registration_status_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -1697,7 +1705,6 @@
sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
new String[]{
"com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
- "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," +
"com.android.internal.telephony.CARRIER_SIGNAL_RESET"
});
sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
@@ -1753,6 +1760,7 @@
sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null);
sDefaults.putInt(IMSI_KEY_EXPIRATION_DAYS_TIME_INT, IMSI_ENCRYPTION_DAYS_TIME_DISABLED);
sDefaults.putString(IMSI_KEY_DOWNLOAD_URL_STRING, null);
+ sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ab679ff..4edb069 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5086,7 +5086,12 @@
}
}
- /** @hide */
+ /**
+ * @deprecated Use {@link android.telecom.TelecomManager#placeCall(Uri address,
+ * Bundle extras)} instead.
+ * @hide
+ */
+ @Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void call(String callingPackage, String number) {
@@ -5099,7 +5104,11 @@
}
}
- /** @hide */
+ /**
+ * @deprecated Use {@link android.telecom.TelecomManager#endCall()} instead.
+ * @hide
+ */
+ @Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public boolean endCall() {
@@ -5113,7 +5122,11 @@
return false;
}
- /** @hide */
+ /**
+ * @deprecated Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
+ * @hide
+ */
+ @Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void answerRingingCall() {
@@ -5126,7 +5139,11 @@
}
}
- /** @hide */
+ /**
+ * @deprecated Use {@link android.telecom.TelecomManager#silenceRinger} instead
+ * @hide
+ */
+ @Deprecated
@SystemApi
@SuppressLint("Doclava125")
public void silenceRinger() {
@@ -5681,10 +5698,13 @@
}
/**
+ * @deprecated Use {link@ android.telecom.TelecomManager#isTtySupported} instead
* Whether the phone supports TTY mode.
*
* @return {@code true} if the device supports TTY mode, and {@code false} otherwise.
+ *
*/
+ @Deprecated
public boolean isTtyModeSupported() {
try {
ITelephony telephony = getITelephony();
@@ -5776,6 +5796,25 @@
}
/**
+ * Returns the IMS Registration Status for a particular Subscription ID
+ *
+ * @param subId Subscription ID
+ * @return true if IMS status is registered, false if the IMS status is not registered or a
+ * RemoteException occurred.
+ *
+ * @hide
+ */
+ public boolean isImsRegistered(int subId) {
+ try {
+ return getITelephony().isImsRegisteredForSubscriber(subId);
+ } catch (RemoteException ex) {
+ return false;
+ } catch (NullPointerException ex) {
+ return false;
+ }
+ }
+
+ /**
* Returns the Status of Volte
* @hide
*/
@@ -6740,7 +6779,6 @@
* 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() {
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index e7b22bd..cf4c47b 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -524,6 +524,7 @@
* Defines IMS feature value.
*/
public static class FeatureValueConstants {
+ public static final int ERROR = -1;
public static final int OFF = 0;
public static final int ON = 1;
}
diff --git a/telephony/java/com/android/internal/telephony/ExponentialBackoff.java b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
new file mode 100644
index 0000000..80958c0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ExponentialBackoff.java
@@ -0,0 +1,84 @@
+/*
+ * 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.annotation.NonNull;
+import android.os.Handler;
+import android.os.Looper;
+
+/** The implementation of exponential backoff with jitter applied. */
+public class ExponentialBackoff {
+ private int mRetryCounter;
+ private long mStartDelayMs;
+ private long mMaximumDelayMs;
+ private long mCurrentDelayMs;
+ private int mMultiplier;
+ private Runnable mRunnable;
+ private Handler mHandler;
+
+ public ExponentialBackoff(
+ long initialDelayMs,
+ long maximumDelayMs,
+ int multiplier,
+ @NonNull Looper looper,
+ @NonNull Runnable runnable) {
+ this(initialDelayMs, maximumDelayMs, multiplier, new Handler(looper), runnable);
+ }
+
+ public ExponentialBackoff(
+ long initialDelayMs,
+ long maximumDelayMs,
+ int multiplier,
+ @NonNull Handler handler,
+ @NonNull Runnable runnable) {
+ mRetryCounter = 0;
+ mStartDelayMs = initialDelayMs;
+ mMaximumDelayMs = maximumDelayMs;
+ mMultiplier = multiplier;
+ mHandler = handler;
+ mRunnable = runnable;
+ }
+
+ /** Starts the backoff, the runnable will be executed after {@link #mStartDelayMs}. */
+ public void start() {
+ mRetryCounter = 0;
+ mCurrentDelayMs = mStartDelayMs;
+ mHandler.removeCallbacks(mRunnable);
+ mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+ }
+
+ /** Stops the backoff, all pending messages will be removed from the message queue. */
+ public void stop() {
+ mRetryCounter = 0;
+ mHandler.removeCallbacks(mRunnable);
+ }
+
+ /** Should call when the retry action has failed and we want to retry after a longer delay. */
+ public void notifyFailed() {
+ mRetryCounter++;
+ long temp = Math.min(
+ mMaximumDelayMs, (long) (mStartDelayMs * Math.pow(mMultiplier, mRetryCounter)));
+ mCurrentDelayMs = (long) (((1 + Math.random()) / 2) * temp);
+ mHandler.removeCallbacks(mRunnable);
+ mHandler.postDelayed(mRunnable, mCurrentDelayMs);
+ }
+
+ /** Returns the delay for the most recently posted message. */
+ public long getCurrentDelay() {
+ return mCurrentDelayMs;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index ab7c5e7..0dd846e 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1080,6 +1080,15 @@
boolean isImsRegistered();
/**
+ * Get IMS Registration Status on a particular subid.
+ *
+ * @param subId user preferred subId.
+ *
+ * @return {@code true} if the IMS status is registered.
+ */
+ boolean isImsRegisteredForSubscriber(int subId);
+
+ /**
* Returns the Status of Wi-Fi Calling
*/
boolean isWifiCallingAvailable();
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 0752661..a642fdf 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -70,11 +70,10 @@
LOCAL_SOURCE_FILES_ALL_GENERATED := true
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
# Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(android_test_mock_gen_stamp)
-$(full_classes_jack) : $(android_test_mock_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
# Archive a copy of the classes.jar in SDK build.
$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.jar)
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 3af0adc..677585c 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -42,6 +42,7 @@
libui \
libunwind \
libutils \
+ libvndksupport \
libcrypto \
libhidl-gen-utils \
libhidlbase \
@@ -52,6 +53,7 @@
libtinyxml2 \
libvintf \
libhwbinder \
+ libunwindstack \
android.hidl.token@1.0
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index bfbb8cc..5008a41 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -614,9 +614,10 @@
private final long mFixedTimeMs = SystemClock.elapsedRealtime();
public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
- boolean ieee802_3Filter, IpConnectivityLog log) throws Exception {
+ boolean ieee802_3Filter, int[] ethTypeBlackList,
+ IpConnectivityLog log) throws Exception {
super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
- ipManagerCallback, multicastFilter, ieee802_3Filter, log);
+ ipManagerCallback, multicastFilter, ieee802_3Filter, ethTypeBlackList, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
@@ -744,9 +745,10 @@
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
+ final int[] ethTypeBlackList = {};
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -796,9 +798,10 @@
@SmallTest
public void testApfFilterIPv6() throws Exception {
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
byte[] program = ipManagerCallback.getApfProgram();
// Verify empty IPv6 packet is passed
@@ -833,6 +836,7 @@
final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
@@ -840,7 +844,7 @@
lp.addLinkAddress(link);
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -903,7 +907,7 @@
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
program = ipManagerCallback.getApfProgram();
assertDrop(program, mcastv4packet.array());
@@ -924,9 +928,10 @@
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
+ final int[] ethTypeBlackList = {};
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -948,7 +953,7 @@
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
program = ipManagerCallback.getApfProgram();
@@ -968,6 +973,70 @@
apfFilter.shutdown();
}
+ @SmallTest
+ public void testApfFilterEthTypeBL() throws Exception {
+ MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
+ LinkProperties lp = new LinkProperties();
+ lp.addLinkAddress(link);
+ final int[] emptyBlackList = {};
+ final int[] ipv4BlackList = {ETH_P_IP};
+ final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
+
+ ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, emptyBlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+
+ byte[] program = ipManagerCallback.getApfProgram();
+
+ // Verify empty packet of 100 zero bytes is passed
+ // Note that eth-type = 0 makes it an IEEE802.3 frame
+ ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+ assertPass(program, packet.array());
+
+ // Verify empty packet with IPv4 is passed
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertPass(program, packet.array());
+
+ // Verify empty IPv6 packet is passed
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertPass(program, packet.array());
+
+ // Now add IPv4 to the black list
+ ipManagerCallback.resetApfProgramWait();
+ apfFilter.shutdown();
+ apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, ipv4BlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+ program = ipManagerCallback.getApfProgram();
+
+ // Verify that IPv4 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertDrop(program, packet.array());
+
+ // Verify that IPv6 frame will pass
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertPass(program, packet.array());
+
+ // Now let us have both IPv4 and IPv6 in the black list
+ ipManagerCallback.resetApfProgramWait();
+ apfFilter.shutdown();
+ apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, ipv4Ipv6BlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+ program = ipManagerCallback.getApfProgram();
+
+ // Verify that IPv4 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertDrop(program, packet.array());
+
+ // Verify that IPv6 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertDrop(program, packet.array());
+
+ apfFilter.shutdown();
+ }
+
private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
cb.resetApfProgramWait();
filter.setLinkProperties(lp);
@@ -991,9 +1060,10 @@
@SmallTest
public void testApfFilterArp() throws Exception {
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
// Verify initially ARP request filter is off, and GARP filter is on.
verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
@@ -1114,8 +1184,9 @@
@SmallTest
public void testApfFilterRa() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ final int[] ethTypeBlackList = {};
TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
byte[] program = ipManagerCallback.getApfProgram();
final int ROUTER_LIFETIME = 1000;
@@ -1256,9 +1327,10 @@
public void testRaParsing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback cb = new MockIpManagerCallback();
TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
for (int i = 0; i < 1000; i++) {
byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
r.nextBytes(packet);
@@ -1275,9 +1347,10 @@
public void testRaProcessing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback cb = new MockIpManagerCallback();
TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
for (int i = 0; i < 1000; i++) {
byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
r.nextBytes(packet);
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
new file mode 100644
index 0000000..3aab942
--- /dev/null
+++ b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.net.netlink;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+import android.system.OsConstants;
+import libcore.util.HexEncoding;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConntrackMessageTest {
+ private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
+
+ // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
+ public static final String CT_V4UPDATE_TCP_HEX =
+ // struct nlmsghdr
+ "50000000" + // length = 80
+ "0001" + // type = (1 << 8) | 0
+ "0501" + // flags
+ "01000000" + // seqno = 1
+ "00000000" + // pid = 0
+ // struct nfgenmsg
+ "02" + // nfgen_family = AF_INET
+ "00" + // version = NFNETLINK_V0
+ "0000" + // res_id
+ // struct nlattr
+ "3400" + // nla_len = 52
+ "0180" + // nla_type = nested CTA_TUPLE_ORIG
+ // struct nlattr
+ "1400" + // nla_len = 20
+ "0180" + // nla_type = nested CTA_TUPLE_IP
+ "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
+ "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
+ // struct nlattr
+ "1C00" + // nla_len = 28
+ "0280" + // nla_type = nested CTA_TUPLE_PROTO
+ "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6
+ "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
+ "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+ // struct nlattr
+ "0800" + // nla_len = 8
+ "0700" + // nla_type = CTA_TIMEOUT
+ "00069780"; // nla_value = 432000 (big endian)
+ public static final byte[] CT_V4UPDATE_TCP_BYTES =
+ HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+ // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
+ public static final String CT_V4UPDATE_UDP_HEX =
+ // struct nlmsghdr
+ "50000000" + // length = 80
+ "0001" + // type = (1 << 8) | 0
+ "0501" + // flags
+ "01000000" + // seqno = 1
+ "00000000" + // pid = 0
+ // struct nfgenmsg
+ "02" + // nfgen_family = AF_INET
+ "00" + // version = NFNETLINK_V0
+ "0000" + // res_id
+ // struct nlattr
+ "3400" + // nla_len = 52
+ "0180" + // nla_type = nested CTA_TUPLE_ORIG
+ // struct nlattr
+ "1400" + // nla_len = 20
+ "0180" + // nla_type = nested CTA_TUPLE_IP
+ "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
+ "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
+ // struct nlattr
+ "1C00" + // nla_len = 28
+ "0280" + // nla_type = nested CTA_TUPLE_PROTO
+ "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17
+ "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
+ "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+ // struct nlattr
+ "0800" + // nla_len = 8
+ "0700" + // nla_type = CTA_TIMEOUT
+ "000000B4"; // nla_value = 180 (big endian)
+ public static final byte[] CT_V4UPDATE_UDP_BYTES =
+ HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+ @Test
+ public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
+ assumeTrue(USING_LE);
+
+ final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ OsConstants.IPPROTO_TCP,
+ (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
+ (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
+ 432000);
+ assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
+ }
+
+ @Test
+ public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
+ assumeTrue(USING_LE);
+
+ final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ OsConstants.IPPROTO_UDP,
+ (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
+ (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
+ 180);
+ assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
+ }
+}
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index f77608f..9115378 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -28,6 +28,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
import android.os.HandlerThread;
import android.os.Handler;
@@ -38,6 +39,7 @@
import android.os.Message;
import android.os.Messenger;
import com.android.internal.util.AsyncChannel;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,6 +58,8 @@
@Mock INsdManager mService;
MockServiceHandler mServiceHandler;
+ NsdManager mManager;
+
long mTimeoutMs = 100; // non-final so that tests can adjust the value.
@Before
@@ -64,11 +68,23 @@
mServiceHandler = spy(MockServiceHandler.create(mContext));
when(mService.getMessenger()).thenReturn(new Messenger(mServiceHandler));
+
+ mManager = makeManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ waitForIdleHandler(mServiceHandler, mTimeoutMs);
+ mServiceHandler.chan.disconnect();
+ mServiceHandler.stop();
+ if (mManager != null) {
+ mManager.disconnect();
+ }
}
@Test
public void testResolveService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type");
@@ -88,7 +104,7 @@
@Test
public void testParallelResolveService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type");
@@ -111,7 +127,7 @@
@Test
public void testRegisterService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo request2 = new NsdServiceInfo("another_name", "another_type");
@@ -170,7 +186,7 @@
@Test
public void testDiscoverService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply2 = new NsdServiceInfo("another_name", "a_type");
@@ -248,7 +264,7 @@
@Test
public void testInvalidCalls() {
- NsdManager manager = new NsdManager(mContext, mService);
+ NsdManager manager = mManager;
NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class);
@@ -351,6 +367,10 @@
}
}
+ public void stop() {
+ getLooper().quitSafely();
+ }
+
public static MockServiceHandler create(Context context) {
HandlerThread t = new HandlerThread("mock-service-handler");
t.start();
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index f6481cf..8816d43 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -64,6 +64,7 @@
import android.net.NetworkMisc;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
+import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.StringNetworkSpecifier;
import android.net.metrics.IpConnectivityLog;
@@ -88,6 +89,7 @@
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.LogPrinter;
@@ -109,7 +111,10 @@
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -304,6 +309,10 @@
private String mRedirectUrl;
MockNetworkAgent(int transport) {
+ this(transport, new LinkProperties());
+ }
+
+ MockNetworkAgent(int transport, LinkProperties linkProperties) {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
@@ -329,7 +338,7 @@
mHandlerThread.start();
mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
"Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
- new LinkProperties(), mScore, new NetworkMisc()) {
+ linkProperties, mScore, new NetworkMisc()) {
@Override
public void unwanted() { mDisconnected.open(); }
@@ -3338,6 +3347,68 @@
assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
}
+ @SmallTest
+ public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(networkRequest, networkCallback);
+
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("wlan0");
+ LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
+ RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
+ NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+ lp.addLinkAddress(myIpv4Address);
+ lp.addRoute(myIpv4DefaultRoute);
+
+ // Verify direct routes are added when network agent is first registered in
+ // ConnectivityService.
+ MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
+ networkAgent.connect(true);
+ networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
+ networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
+ CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ networkAgent);
+ networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
+ networkCallback.assertNoCallback();
+ checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
+ Arrays.asList(myIpv4DefaultRoute));
+ checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
+ Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
+
+ // Verify direct routes are added during subsequent link properties updates.
+ LinkProperties newLp = new LinkProperties(lp);
+ LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
+ LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
+ newLp.addLinkAddress(myIpv6Address1);
+ newLp.addLinkAddress(myIpv6Address2);
+ networkAgent.sendLinkProperties(newLp);
+ cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
+ networkCallback.assertNoCallback();
+ checkDirectlyConnectedRoutes(cbi.arg,
+ Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
+ Arrays.asList(myIpv4DefaultRoute));
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+
+ private void checkDirectlyConnectedRoutes(Object callbackObj,
+ Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
+ assertTrue(callbackObj instanceof LinkProperties);
+ LinkProperties lp = (LinkProperties) callbackObj;
+
+ Set<RouteInfo> expectedRoutes = new ArraySet<>();
+ expectedRoutes.addAll(otherRoutes);
+ for (LinkAddress address : linkAddresses) {
+ RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
+ // Duplicates in linkAddresses are considered failures
+ assertTrue(expectedRoutes.add(localRoute));
+ }
+ List<RouteInfo> observedRoutes = lp.getRoutes();
+ assertEquals(expectedRoutes.size(), observedRoutes.size());
+ assertTrue(observedRoutes.containsAll(expectedRoutes));
+ }
+
private static <T> void assertEmpty(T[] ts) {
int length = ts.length;
assertEquals("expected empty array, but length was " + length, 0, length);
diff --git a/tests/net/java/com/android/server/NsdServiceTest.java b/tests/net/java/com/android/server/NsdServiceTest.java
index 68cb251..2e49c98 100644
--- a/tests/net/java/com/android/server/NsdServiceTest.java
+++ b/tests/net/java/com/android/server/NsdServiceTest.java
@@ -95,6 +95,9 @@
client2.disconnect();
verify(mDaemon, timeout(mTimeoutMs).times(1)).stop();
+
+ client1.disconnect();
+ client2.disconnect();
}
@Test
@@ -131,6 +134,8 @@
// checks that request are cleaned
verifyDaemonCommands("stop-register 2", "stop-discover 3", "stop-resolve 4");
+
+ client.disconnect();
}
NsdService makeService() {
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d11565a..eff04ab 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -201,9 +201,14 @@
" time_ms: 1",
" transports: 0",
" default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
" network_id <",
" network_id: 102",
" >",
+ " no_default_network_duration_ms: 0",
" previous_network_id <",
" network_id: 101",
" >",
@@ -442,6 +447,8 @@
" program_updates_all: 7",
" program_updates_allowing_multicast: 3",
" received_ras: 10",
+ " total_packet_dropped: 0",
+ " total_packet_processed: 0",
" zero_lifetime_ras: 1",
" >",
">",
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index e01469b..cc18b7f 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -256,9 +256,14 @@
" time_ms: 300",
" transports: 0",
" default_network_event <",
+ " default_network_duration_ms: 0",
+ " final_score: 0",
+ " initial_score: 0",
+ " ip_support: 0",
" network_id <",
" network_id: 102",
" >",
+ " no_default_network_duration_ms: 0",
" previous_network_id <",
" network_id: 101",
" >",
@@ -308,6 +313,8 @@
" program_updates_all: 7",
" program_updates_allowing_multicast: 3",
" received_ras: 10",
+ " total_packet_dropped: 0",
+ " total_packet_processed: 0",
" zero_lifetime_ras: 1",
" >",
">",
@@ -367,6 +374,10 @@
" event_types: 1",
" event_types: 1",
" event_types: 2",
+ " getaddrinfo_error_count: 0",
+ " getaddrinfo_query_count: 0",
+ " gethostbyname_error_count: 0",
+ " gethostbyname_query_count: 0",
" latencies_ms: 3456",
" latencies_ms: 45",
" latencies_ms: 638",
@@ -384,6 +395,10 @@
" dns_lookup_batch <",
" event_types: 1",
" event_types: 2",
+ " getaddrinfo_error_count: 0",
+ " getaddrinfo_query_count: 0",
+ " gethostbyname_error_count: 0",
+ " gethostbyname_query_count: 0",
" latencies_ms: 56",
" latencies_ms: 34",
" return_codes: 0",
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
new file mode 100644
index 0000000..e3f46a4
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -0,0 +1,226 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.INetworkManagementService;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.ConnectivityService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class Nat464XlatTest {
+
+ static final String BASE_IFACE = "test0";
+ static final String STACKED_IFACE = "v4-test0";
+ static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
+
+ @Mock ConnectivityService mConnectivity;
+ @Mock INetworkManagementService mNms;
+ @Mock InterfaceConfiguration mConfig;
+ @Mock NetworkAgentInfo mNai;
+
+ TestLooper mLooper;
+ Handler mHandler;
+
+ Nat464Xlat makeNat464Xlat() {
+ return new Nat464Xlat(mNms, mNai);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ MockitoAnnotations.initMocks(this);
+
+ mNai.linkProperties = new LinkProperties();
+ mNai.linkProperties.setInterfaceName(BASE_IFACE);
+ mNai.networkInfo = new NetworkInfo(null);
+ mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
+ when(mNai.connService()).thenReturn(mConnectivity);
+ when(mNai.handler()).thenReturn(mHandler);
+
+ when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
+ when(mConfig.getLinkAddress()).thenReturn(ADDR);
+ }
+
+ @Test
+ public void testNormalStartAndStop() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+ ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // Stacked interface up notification arrives.
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+ verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
+ verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertFalse(c.getValue().getStackedLinks().isEmpty());
+ assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertRunning(nat);
+
+ // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
+ nat.stop();
+
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
+
+ // Stacked interface removed notification arrives.
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertTrue(c.getValue().getStackedLinks().isEmpty());
+ assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testClatdCrashWhileRunning() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+ ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // Stacked interface up notification arrives.
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+ verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
+ verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertFalse(c.getValue().getStackedLinks().isEmpty());
+ assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertRunning(nat);
+
+ // Stacked interface removed notification arrives (clatd crashed, ...).
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
+ verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertTrue(c.getValue().getStackedLinks().isEmpty());
+ assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertIdle(nat);
+
+ // ConnectivityService stops clat: no-op.
+ nat.stop();
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testStopBeforeClatdStarts() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
+ nat.stop();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ assertIdle(nat);
+
+ // In-flight interface up notification arrives: no-op
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+
+ // Interface removed notification arrives after stopClatd() takes effect: no-op.
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testStopAndClatdNeverStarts() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
+ nat.stop();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ static void assertIdle(Nat464Xlat nat) {
+ assertTrue("Nat464Xlat was not IDLE", !nat.isStarted());
+ }
+
+ static void assertRunning(Nat464Xlat nat) {
+ assertTrue("Nat464Xlat was not RUNNING", nat.isRunning());
+ }
+}
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index f98ab3d..46f395e 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -111,6 +111,10 @@
" event_types: 1",
" event_types: 2",
" event_types: 2",
+ " getaddrinfo_error_count: 0",
+ " getaddrinfo_query_count: 0",
+ " gethostbyname_error_count: 0",
+ " gethostbyname_query_count: 0",
" latencies_ms: 3456",
" latencies_ms: 267",
" latencies_ms: 1230",
@@ -142,6 +146,10 @@
" event_types: 2",
" event_types: 1",
" event_types: 1",
+ " getaddrinfo_error_count: 0",
+ " getaddrinfo_query_count: 0",
+ " gethostbyname_error_count: 0",
+ " gethostbyname_query_count: 0",
" latencies_ms: 56",
" latencies_ms: 78",
" latencies_ms: 14",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 27e90bc..2199a13 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -32,12 +32,13 @@
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -441,6 +442,9 @@
ethernetStats.txBytes = 100000;
when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats);
offload.setUpstreamLinkProperties(null);
+ // Expect that we first clear the HAL's upstream parameters.
+ inOrder.verify(mHardware, times(1)).setUpstreamParameters(
+ eq(""), eq("0.0.0.0"), eq("0.0.0.0"), eq(null));
// Expect that we fetch stats from the previous upstream.
inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface));
@@ -450,8 +454,6 @@
waitForIdle();
// There is no current upstream, so no stats are fetched.
inOrder.verify(mHardware, never()).getForwardedStats(any());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(null), eq(null), eq(null), eq(null));
inOrder.verifyNoMoreInteractions();
assertEquals(2, stats.size());
@@ -626,6 +628,73 @@
inOrder.verifyNoMoreInteractions();
}
+ @Test
+ public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
+ setupFunctioningHardwareInterface();
+ enableOffload();
+
+ final OffloadController offload = makeOffloadController();
+ offload.start();
+
+ // Pretend to set a few different upstreams (only the interface name
+ // matters for this test; we're ignoring IP and route information).
+ final LinkProperties upstreamLp = new LinkProperties();
+ for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
+ upstreamLp.setInterfaceName(ifname);
+ offload.setUpstreamLinkProperties(upstreamLp);
+ }
+
+ // Clear invocation history, especially the getForwardedStats() calls
+ // that happen with setUpstreamParameters().
+ clearInvocations(mHardware);
+
+ OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ callback.onStoppedUnsupported();
+
+ // Verify forwarded stats behaviour.
+ verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
+ verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
+ verifyNoMoreInteractions(mHardware);
+ verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
+ verifyNoMoreInteractions(mNMService);
+ }
+
+ @Test
+ public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters()
+ throws Exception {
+ setupFunctioningHardwareInterface();
+ enableOffload();
+
+ final OffloadController offload = makeOffloadController();
+ offload.start();
+
+ // Pretend to set a few different upstreams (only the interface name
+ // matters for this test; we're ignoring IP and route information).
+ final LinkProperties upstreamLp = new LinkProperties();
+ for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
+ upstreamLp.setInterfaceName(ifname);
+ offload.setUpstreamLinkProperties(upstreamLp);
+ }
+
+ // Clear invocation history, especially the getForwardedStats() calls
+ // that happen with setUpstreamParameters().
+ clearInvocations(mHardware);
+
+ OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ callback.onSupportAvailable();
+
+ // Verify forwarded stats behaviour.
+ verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
+ verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
+ verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
+ verifyNoMoreInteractions(mNMService);
+
+ // TODO: verify local prefixes and downstreams are also pushed to the HAL.
+ verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
+ verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
+ verifyNoMoreInteractions(mHardware);
+ }
+
private static void assertArrayListContains(ArrayList<String> list, String... elems) {
for (String element : elems) {
assertTrue(list.contains(element));
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
new file mode 100644
index 0000000..e26c9c3
--- /dev/null
+++ b/tools/aapt/Android.bp
@@ -0,0 +1,115 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// ==========================================================
+// Setup some common variables for the different build
+// targets here.
+// ==========================================================
+
+cc_defaults {
+ name: "aapt_defaults",
+
+ static_libs: [
+ "libandroidfw",
+ "libpng",
+ "libutils",
+ "liblog",
+ "libcutils",
+ "libexpat",
+ "libziparchive",
+ "libbase",
+ "libz",
+ ],
+ group_static_libs: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+// ==========================================================
+// Build the host static library: libaapt
+// ==========================================================
+cc_library_host_static {
+ name: "libaapt",
+ defaults: ["aapt_defaults"],
+ target: {
+ darwin: {
+ cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
+ },
+ },
+ cflags: [
+ "-Wno-format-y2k",
+ "-DSTATIC_ANDROIDFW_FOR_TOOLS",
+ ],
+
+ srcs: [
+ "AaptAssets.cpp",
+ "AaptConfig.cpp",
+ "AaptUtil.cpp",
+ "AaptXml.cpp",
+ "ApkBuilder.cpp",
+ "Command.cpp",
+ "CrunchCache.cpp",
+ "FileFinder.cpp",
+ "Images.cpp",
+ "Package.cpp",
+ "pseudolocalize.cpp",
+ "Resource.cpp",
+ "ResourceFilter.cpp",
+ "ResourceIdCache.cpp",
+ "ResourceTable.cpp",
+ "SourcePos.cpp",
+ "StringPool.cpp",
+ "WorkQueue.cpp",
+ "XMLNode.cpp",
+ "ZipEntry.cpp",
+ "ZipFile.cpp",
+ ],
+}
+
+// ==========================================================
+// Build the host tests: libaapt_tests
+// ==========================================================
+cc_test_host {
+ name: "libaapt_tests",
+ defaults: ["aapt_defaults"],
+ srcs: [
+ "tests/AaptConfig_test.cpp",
+ "tests/AaptGroupEntry_test.cpp",
+ "tests/Pseudolocales_test.cpp",
+ "tests/ResourceFilter_test.cpp",
+ "tests/ResourceTable_test.cpp",
+ ],
+ static_libs: ["libaapt"],
+}
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 04f46d9..7bcf631d 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -14,7 +14,6 @@
# limitations under the License.
#
-# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
# ==========================================================
@@ -23,37 +22,6 @@
# ==========================================================
LOCAL_PATH:= $(call my-dir)
-aaptMain := Main.cpp
-aaptSources := \
- AaptAssets.cpp \
- AaptConfig.cpp \
- AaptUtil.cpp \
- AaptXml.cpp \
- ApkBuilder.cpp \
- Command.cpp \
- CrunchCache.cpp \
- FileFinder.cpp \
- Images.cpp \
- Package.cpp \
- pseudolocalize.cpp \
- Resource.cpp \
- ResourceFilter.cpp \
- ResourceIdCache.cpp \
- ResourceTable.cpp \
- SourcePos.cpp \
- StringPool.cpp \
- WorkQueue.cpp \
- XMLNode.cpp \
- ZipEntry.cpp \
- ZipFile.cpp
-
-aaptTests := \
- tests/AaptConfig_test.cpp \
- tests/AaptGroupEntry_test.cpp \
- tests/Pseudolocales_test.cpp \
- tests/ResourceFilter_test.cpp \
- tests/ResourceTable_test.cpp
-
aaptHostStaticLibs := \
libandroidfw \
libpng \
@@ -62,35 +30,10 @@
libcutils \
libexpat \
libziparchive \
- libbase
+ libbase \
+ libz
-aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER_FROM_FILE)\"
-aaptCFlags += -Wall -Werror
-
-aaptHostLdLibs_linux := -lrt -ldl -lpthread
-
-# Statically link libz for MinGW (Win SDK under Linux),
-# and dynamically link for all others.
-aaptHostStaticLibs_windows := libz
-aaptHostLdLibs_linux += -lz
-aaptHostLdLibs_darwin := -lz
-
-
-# ==========================================================
-# Build the host static library: libaapt
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaapt
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS := -Wno-format-y2k -DSTATIC_ANDROIDFW_FOR_TOOLS $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_CFLAGS_darwin := -D_DARWIN_UNLIMITED_STREAMS
-LOCAL_SRC_FILES := $(aaptSources)
-LOCAL_STATIC_LIBRARIES := $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
-
-include $(BUILD_HOST_STATIC_LIBRARY)
+aaptCFlags := -Wall -Werror
# ==========================================================
# Build the host executable: aapt
@@ -99,33 +42,10 @@
LOCAL_MODULE := aapt
LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_CFLAGS := $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_LDLIBS_darwin := $(aaptHostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(aaptHostLdLibs_linux)
-LOCAL_SRC_FILES := $(aaptMain)
+LOCAL_CFLAGS := -DAAPT_VERSION=\"$(BUILD_NUMBER_FROM_FILE)\" $(aaptCFlags)
+LOCAL_SRC_FILES := Main.cpp
LOCAL_STATIC_LIBRARIES := libaapt $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
include $(BUILD_HOST_EXECUTABLE)
-
-# ==========================================================
-# Build the host tests: libaapt_tests
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaapt_tests
-LOCAL_CFLAGS := $(aaptCFlags)
-LOCAL_CPPFLAGS := $(aaptCppFlags)
-LOCAL_LDLIBS_darwin := $(aaptHostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(aaptHostLdLibs_linux)
-LOCAL_SRC_FILES := $(aaptTests)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := libaapt $(aaptHostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(aaptHostStaticLibs_windows)
-
-include $(BUILD_HOST_NATIVE_TEST)
-
-
endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index ba73180..5e85802 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -29,24 +29,6 @@
using namespace android;
-#ifndef AAPT_VERSION
- #define AAPT_VERSION ""
-#endif
-
-/*
- * Show version info. All the cool kids do it.
- */
-int doVersion(Bundle* bundle)
-{
- if (bundle->getFileSpecCount() != 0) {
- printf("(ignoring extra arguments)\n");
- }
- printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
-
- return 0;
-}
-
-
/*
* Open the file read only. The call fails if the file doesn't exist.
*
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 417b7ae..d714687 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -20,6 +20,23 @@
static const char* gProgName = "aapt";
+#ifndef AAPT_VERSION
+ #define AAPT_VERSION ""
+#endif
+
+/*
+ * Show version info. All the cool kids do it.
+ */
+int doVersion(Bundle* bundle)
+{
+ if (bundle->getFileSpecCount() != 0) {
+ printf("(ignoring extra arguments)\n");
+ }
+ printf("Android Asset Packaging Tool, v0.2-" AAPT_VERSION "\n");
+
+ return 0;
+}
+
/*
* When running under Cygwin on Windows, this will convert slash-based
* paths into back-slash-based ones. Otherwise the ApptAssets file comparisons
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index eff8283..353c3e0 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -24,7 +24,7 @@
]
cc_defaults {
- name: "aapt_defaults",
+ name: "aapt2_defaults",
cflags: [
"-Wall",
"-Werror",
@@ -39,14 +39,9 @@
windows: {
enabled: true,
cflags: ["-Wno-maybe-uninitialized"],
- static_libs: ["libz"],
},
darwin: {
cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
- host_ldlibs: ["-lz"],
- },
- linux: {
- host_ldlibs: ["-lz"],
},
},
static_libs: [
@@ -59,6 +54,7 @@
"libpng",
"libbase",
"libprotobuf-cpp-lite",
+ "libz",
],
group_static_libs: true,
}
@@ -141,7 +137,7 @@
proto: {
export_proto_headers: true,
},
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -151,7 +147,7 @@
name: "libaapt2_jni",
srcs: toolSources + ["jni/aapt2_jni.cpp"],
static_libs: ["libaapt2"],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -161,7 +157,7 @@
name: "aapt2_tests",
srcs: ["test/Common.cpp", "**/*_test.cpp"],
static_libs: ["libaapt2", "libgmock"],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
// ==========================================================
@@ -171,5 +167,5 @@
name: "aapt2",
srcs: ["Main.cpp"] + toolSources,
static_libs: ["libaapt2"],
- defaults: ["aapt_defaults"],
+ defaults: ["aapt2_defaults"],
}
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 53c66a6..f0ac467 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -293,6 +293,7 @@
manifest_action["instrumentation"]["meta-data"] = meta_data_action;
manifest_action["original-package"];
+ manifest_action["overlay"];
manifest_action["protected-broadcast"];
manifest_action["uses-permission"];
manifest_action["uses-permission-sdk-23"];
diff --git a/tools/bit/Android.bp b/tools/bit/Android.bp
new file mode 100644
index 0000000..258e9b5
--- /dev/null
+++ b/tools/bit/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2015 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.
+//
+
+// ==========================================================
+// Build the host executable: bit
+// ==========================================================
+cc_binary_host {
+ name: "bit",
+
+ srcs: [
+ "aapt.cpp",
+ "adb.cpp",
+ "command.cpp",
+ "main.cpp",
+ "make.cpp",
+ "print.cpp",
+ "util.cpp",
+ ],
+
+ static_libs: [
+ "libexpat",
+ "libinstrumentation",
+ "libjsoncpp",
+ ],
+
+ shared_libs: ["libprotobuf-cpp-full"],
+}
diff --git a/tools/bit/Android.mk b/tools/bit/Android.mk
deleted file mode 100644
index 57f46d4..0000000
--- a/tools/bit/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bit
-
-LOCAL_MODULE_HOST_OS := linux darwin
-
-LOCAL_SRC_FILES := \
- aapt.cpp \
- adb.cpp \
- command.cpp \
- main.cpp \
- make.cpp \
- print.cpp \
- util.cpp
-
-LOCAL_STATIC_LIBRARIES := \
- libexpat \
- libinstrumentation \
- libjsoncpp
-
-LOCAL_SHARED_LIBRARIES := \
- libprotobuf-cpp-full
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/bit/adb.h b/tools/bit/adb.h
index dca80c8..f0774db9 100644
--- a/tools/bit/adb.h
+++ b/tools/bit/adb.h
@@ -17,7 +17,7 @@
#ifndef ADB_H
#define ADB_H
-#include "instrumentation_data.pb.h"
+#include "proto/instrumentation_data.pb.h"
#include <string>
diff --git a/tools/incident_report/Android.bp b/tools/incident_report/Android.bp
new file mode 100644
index 0000000..6f21605
--- /dev/null
+++ b/tools/incident_report/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2015 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.
+//
+
+// ==========================================================
+// Build the host executable: incident_report
+// ==========================================================
+cc_binary_host {
+ name: "incident_report",
+
+ srcs: [
+ "generic_message.cpp",
+ "main.cpp",
+ "printer.cpp",
+ ],
+
+ shared_libs: [
+ "libplatformprotos",
+ "libprotobuf-cpp-full",
+ ],
+
+ cflags: ["-Wno-unused-parameter"],
+
+ // b/34740546, work around clang-tidy segmentation fault.
+ tidy_checks: ["-modernize*"],
+}
diff --git a/tools/incident_report/Android.mk b/tools/incident_report/Android.mk
deleted file mode 100644
index e57a959..0000000
--- a/tools/incident_report/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incident_report
-
-LOCAL_C_INCLUDES := \
- external/protobuf/src
-
-LOCAL_SRC_FILES := \
- generic_message.cpp \
- main.cpp \
- printer.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libplatformprotos \
- libprotobuf-cpp-full
-
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-
-LOCAL_C_FLAGS := \
- -Wno-unused-parameter
-include $(BUILD_HOST_EXECUTABLE)
-
-
diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp
new file mode 100644
index 0000000..7f8151f
--- /dev/null
+++ b/tools/incident_section_gen/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2015 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.
+//
+
+// ==========================================================
+// Build the host executable: incident-section-gen
+// ==========================================================
+cc_binary_host {
+ name: "incident-section-gen",
+ // b/34740546, work around clang-tidy segmentation fault.
+ tidy_checks: ["-modernize*"],
+ cflags: [
+ "-g",
+ "-O0",
+ ],
+ srcs: ["main.cpp"],
+ shared_libs: [
+ "libplatformprotos",
+ "libprotobuf-cpp-full",
+ ],
+}
diff --git a/tools/incident_section_gen/Android.mk b/tools/incident_section_gen/Android.mk
deleted file mode 100644
index 0549026..0000000
--- a/tools/incident_section_gen/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH:= $(call my-dir)
-
-# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incident-section-gen
-# b/34740546, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -modernize*
-LOCAL_CFLAGS += -g -O0
-LOCAL_C_INCLUDES := \
- external/protobuf/src
-LOCAL_SRC_FILES := \
- main.cpp
-LOCAL_LDFLAGS := -ldl
-LOCAL_SHARED_LIBRARIES := \
- libplatformprotos \
- libprotobuf-cpp-full
-
-include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/tools/obbtool/Android.bp b/tools/obbtool/Android.bp
new file mode 100644
index 0000000..f879658
--- /dev/null
+++ b/tools/obbtool/Android.bp
@@ -0,0 +1,51 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Opaque Binary Blob (OBB) Tool
+//
+
+cc_binary_host {
+ name: "obbtool",
+
+ srcs: ["Main.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-mismatched-tags",
+ ],
+
+ static_libs: [
+ "libandroidfw",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+//####################################################
+cc_binary_host {
+ name: "pbkdf2gen",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-mismatched-tags",
+ ],
+ srcs: ["pbkdf2gen.cpp"],
+ static_libs: ["libcrypto"],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk
deleted file mode 100644
index 6dc306e..0000000
--- a/tools/obbtool/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Copyright 2010 The Android Open Source Project
-#
-# Opaque Binary Blob (OBB) Tool
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- Main.cpp
-
-LOCAL_CFLAGS := -Wall -Werror -Wno-mismatched-tags
-
-#LOCAL_C_INCLUDES +=
-
-LOCAL_STATIC_LIBRARIES := \
- libandroidfw \
- libutils \
- libcutils \
- liblog
-
-ifeq ($(HOST_OS),linux)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-LOCAL_MODULE := obbtool
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#####################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := pbkdf2gen
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := -Wall -Werror -Wno-mismatched-tags
-LOCAL_SRC_FILES := pbkdf2gen.cpp
-LOCAL_LDLIBS += -ldl
-LOCAL_STATIC_LIBRARIES := libcrypto
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#######################################################
-endif # TARGET_BUILD_APPS
diff --git a/tools/split-select/Android.bp b/tools/split-select/Android.bp
new file mode 100644
index 0000000..ee822b7
--- /dev/null
+++ b/tools/split-select/Android.bp
@@ -0,0 +1,108 @@
+//
+// Copyright (C) 2014 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// ==========================================================
+// Setup some common variables for the different build
+// targets here.
+// ==========================================================
+
+cc_defaults {
+ name: "split-select_defaults",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ include_dirs: ["frameworks/base/tools"],
+ static_libs: [
+ "libaapt",
+ "libandroidfw",
+ "libpng",
+ "libutils",
+ "liblog",
+ "libcutils",
+ "libexpat",
+ "libziparchive",
+ "libbase",
+ "libz",
+ ],
+ group_static_libs: true,
+
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ pdk: {
+ enabled: false,
+ },
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
+
+// ==========================================================
+// Build the host static library: libsplit-select
+// ==========================================================
+cc_library_host_static {
+ name: "libsplit-select",
+ defaults: ["split-select_defaults"],
+
+ srcs: [
+ "Abi.cpp",
+ "Grouper.cpp",
+ "Rule.cpp",
+ "RuleGenerator.cpp",
+ "SplitDescription.cpp",
+ "SplitSelector.cpp",
+ ],
+ cflags: ["-D_DARWIN_UNLIMITED_STREAMS"],
+
+}
+
+// ==========================================================
+// Build the host tests: libsplit-select_tests
+// ==========================================================
+cc_test_host {
+ name: "libsplit-select_tests",
+ defaults: ["split-select_defaults"],
+
+ srcs: [
+ "Grouper_test.cpp",
+ "Rule_test.cpp",
+ "RuleGenerator_test.cpp",
+ "SplitSelector_test.cpp",
+ "TestRules.cpp",
+ ],
+
+ static_libs: ["libsplit-select"],
+
+}
+
+// ==========================================================
+// Build the host executable: split-select
+// ==========================================================
+cc_binary_host {
+ name: "split-select",
+ defaults: ["split-select_defaults"],
+ srcs: ["Main.cpp"],
+
+ static_libs: ["libsplit-select"],
+}
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
deleted file mode 100644
index 4a1511e..0000000
--- a/tools/split-select/Android.mk
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
-
-# ==========================================================
-# Setup some common variables for the different build
-# targets here.
-# ==========================================================
-LOCAL_PATH:= $(call my-dir)
-
-main := Main.cpp
-sources := \
- Abi.cpp \
- Grouper.cpp \
- Rule.cpp \
- RuleGenerator.cpp \
- SplitDescription.cpp \
- SplitSelector.cpp
-
-testSources := \
- Grouper_test.cpp \
- Rule_test.cpp \
- RuleGenerator_test.cpp \
- SplitSelector_test.cpp \
- TestRules.cpp
-
-cIncludes := \
- external/zlib \
- frameworks/base/tools
-
-hostStaticLibs := \
- libaapt \
- libandroidfw \
- libpng \
- libutils \
- liblog \
- libcutils \
- libexpat \
- libziparchive \
- libbase
-
-cFlags := -Wall -Werror
-
-hostLdLibs_linux := -lrt -ldl -lpthread
-
-# Statically link libz for MinGW (Win SDK under Linux),
-# and dynamically link for all others.
-hostStaticLibs_windows := libz
-hostLdLibs_darwin := -lz
-hostLdLibs_linux += -lz
-
-
-# ==========================================================
-# Build the host static library: libsplit-select
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libsplit-select
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_SRC_FILES := $(sources)
-LOCAL_STATIC_LIBRARIES := $(hostStaticLibs)
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_CFLAGS := $(cFlags) -D_DARWIN_UNLIMITED_STREAMS
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-
-# ==========================================================
-# Build the host tests: libsplit-select_tests
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libsplit-select_tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(testSources)
-
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_STATIC_LIBRARIES := libsplit-select $(hostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
-LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
-LOCAL_CFLAGS := $(cFlags)
-
-include $(BUILD_HOST_NATIVE_TEST)
-
-# ==========================================================
-# Build the host executable: split-select
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := split-select
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_SRC_FILES := $(main)
-
-LOCAL_C_INCLUDES := $(cIncludes)
-LOCAL_STATIC_LIBRARIES := libsplit-select $(hostStaticLibs)
-LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
-LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
-LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
-LOCAL_CFLAGS := $(cFlags)
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
new file mode 100644
index 0000000..24068e9
--- /dev/null
+++ b/tools/streaming_proto/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2015 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.
+//
+
+// ==========================================================
+// Build the host executable: protoc-gen-javastream
+// ==========================================================
+cc_binary_host {
+ name: "protoc-gen-javastream",
+ srcs: [
+ "Errors.cpp",
+ "string_utils.cpp",
+ "main.cpp",
+ ],
+
+ shared_libs: ["libprotoc"],
+}
diff --git a/tools/streaming_proto/Android.mk b/tools/streaming_proto/Android.mk
index 5a54fd1..ebb77a1 100644
--- a/tools/streaming_proto/Android.mk
+++ b/tools/streaming_proto/Android.mk
@@ -16,19 +16,6 @@
LOCAL_PATH:= $(call my-dir)
# ==========================================================
-# Build the host executable: protoc-gen-javastream
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := protoc-gen-javastream
-LOCAL_SRC_FILES := \
- Errors.cpp \
- string_utils.cpp \
- main.cpp
-LOCAL_SHARED_LIBRARIES := \
- libprotoc
-include $(BUILD_HOST_EXECUTABLE)
-
-# ==========================================================
# Build the java test
# ==========================================================
include $(CLEAR_VARS)
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
new file mode 100644
index 0000000..6fb278c
--- /dev/null
+++ b/tools/validatekeymaps/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Keymap validation tool.
+//
+
+cc_binary_host {
+ name: "validatekeymaps",
+
+ srcs: ["Main.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ static_libs: [
+ "libinput",
+ "libutils",
+ "libcutils",
+ "liblog",
+ ],
+
+ // This tool is prebuilt if we're doing an app-only build.
+ product_variables: {
+ unbundled_build: {
+ enabled: false,
+ },
+ },
+}
diff --git a/tools/validatekeymaps/Android.mk b/tools/validatekeymaps/Android.mk
deleted file mode 100644
index 9af721d..0000000
--- a/tools/validatekeymaps/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright 2010 The Android Open Source Project
-#
-# Keymap validation tool.
-#
-
-# This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- Main.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_STATIC_LIBRARIES := \
- libinput \
- libutils \
- libcutils \
- liblog
-
-ifeq ($(HOST_OS),linux)
-LOCAL_LDLIBS += -ldl -lpthread
-endif
-
-LOCAL_MODULE := validatekeymaps
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif # TARGET_BUILD_APPS