Merge "Clean up the keepalive slots when network disconnect"
diff --git a/Android.bp b/Android.bp
index 57f6513..53da6e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -763,6 +763,7 @@
srcs: [
"core/java/android/annotation/IntDef.java",
"core/java/android/annotation/UnsupportedAppUsage.java",
+ ":unsupportedappusage_annotation_files",
],
}
diff --git a/api/current.txt b/api/current.txt
index 2417d8e..ea82aa1 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -11323,6 +11323,7 @@
field public static final String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
field public static final String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ field public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
field public static final String FEATURE_LEANBACK = "android.software.leanback";
field public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final String FEATURE_LIVE_TV = "android.software.live_tv";
@@ -20930,7 +20931,6 @@
ctor public JapaneseCalendar(int, int, int, int);
ctor public JapaneseCalendar(int, int, int);
ctor public JapaneseCalendar(int, int, int, int, int, int);
- field @Deprecated public static final int CURRENT_ERA;
field public static final int HEISEI;
field public static final int MEIJI;
field public static final int SHOWA;
@@ -26786,6 +26786,7 @@
method public int getVideoHeight();
method public float getVideoPixelAspectRatio();
method public int getVideoWidth();
+ method public boolean isEncrypted();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.tv.TvTrackInfo> CREATOR;
field public static final int TYPE_AUDIO = 0; // 0x0
@@ -26799,6 +26800,7 @@
method public android.media.tv.TvTrackInfo.Builder setAudioChannelCount(int);
method public android.media.tv.TvTrackInfo.Builder setAudioSampleRate(int);
method public android.media.tv.TvTrackInfo.Builder setDescription(CharSequence);
+ method public android.media.tv.TvTrackInfo.Builder setEncrypted(boolean);
method public android.media.tv.TvTrackInfo.Builder setExtra(android.os.Bundle);
method public android.media.tv.TvTrackInfo.Builder setLanguage(String);
method public android.media.tv.TvTrackInfo.Builder setVideoActiveFormatDescription(byte);
diff --git a/api/removed.txt b/api/removed.txt
index 72202ad..f40b146 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -275,6 +275,14 @@
}
+package android.icu.util {
+
+ public class JapaneseCalendar extends android.icu.util.GregorianCalendar {
+ field public static final int CURRENT_ERA;
+ }
+
+}
+
package android.location {
public class Location implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3b4a868..ce379f5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4609,17 +4609,6 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, @Nullable String, boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
- field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
- field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
- field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
- field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
- field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
- field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
- field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
- field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
- field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
- field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
- field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
field public static final String CARRIER_APP_NAMES = "carrier_app_names";
field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
diff --git a/api/test-current.txt b/api/test-current.txt
index cb9ff493..21d761f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1201,17 +1201,6 @@
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
- field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
- field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
- field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
- field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
- field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
- field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
- field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
- field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
- field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
- field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
- field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
field public static final String LOW_POWER_MODE = "low_power";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 1ac6ea8..f04f017 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -33,6 +33,7 @@
import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
import "frameworks/base/core/proto/android/stats/connectivity/network_stack.proto";
+import "frameworks/base/core/proto/android/stats/dnsresolver/dns_resolver.proto";
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
@@ -133,7 +134,7 @@
PhoneStateChanged phone_state_changed = 95;
LowMemReported low_mem_reported = 81;
ThermalThrottlingStateChanged thermal_throttling = 86;
- NetworkDnsEventReported network_dns_event_reported = 116;
+ NetworkDnsEventReported network_dns_event_reported = 116 [(log_from_module) = "resolv"];
DataStallEvent data_stall_event = 121 [(log_from_module) = "network_stack"];
BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125;
BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126;
@@ -2794,51 +2795,37 @@
}
/**
- * Logs the latency period(in microseconds) and the return code of
- * the DNS(Domain Name System) lookups.
- * These 4 methods(GETADDRINFO,GETHOSTBYNAME,GETHOSTBYADDR,RES_NSEND)
- * to get info(address or hostname) from DNS server(or DNS cache).
- * Logged from:
- * /system/netd/server/DnsProxyListener.cpp
+ * Logs a DNS lookup operation initiated by the system resolver on behalf of an application
+ * invoking native APIs such as getaddrinfo() or Java APIs such as Network#getAllByName().
+ *
+ * The NetworkDnsEventReported message represents the entire lookup operation, which may
+ * result one or more queries to the recursive DNS resolvers. Those are individually logged
+ * in DnsQueryEvents to enable computing error rates and network latency and timeouts
+ * broken up by query type, transport, network interface, etc.
*/
message NetworkDnsEventReported {
- // The types of the DNS lookups, as defined in
- //system/netd/server/binder/android/net/metrics/INetdEventListener.aidl
- enum EventType {
- EVENT_UNKNOWN = 0;
- EVENT_GETADDRINFO = 1;
- EVENT_GETHOSTBYNAME = 2;
- EVENT_GETHOSTBYADDR = 3;
- EVENT_RES_NSEND = 4;
- }
- optional EventType event_type = 1;
+ optional android.stats.dnsresolver.EventType event_type = 1;
- // The return value of the DNS resolver for each DNS lookups.
- //bionic/libc/include/netdb.h
- //system/netd/resolv/include/netd_resolv/resolv.h
- enum ReturnCode {
- EAI_NO_ERROR = 0;
- EAI_ADDRFAMILY = 1;
- EAI_AGAIN = 2;
- EAI_BADFLAGS = 3;
- EAI_FAIL = 4;
- EAI_FAMILY = 5;
- EAI_MEMORY = 6;
- EAI_NODATA = 7;
- EAI_NONAME = 8;
- EAI_SERVICE = 9;
- EAI_SOCKTYPE = 10;
- EAI_SYSTEM = 11;
- EAI_BADHINTS = 12;
- EAI_PROTOCOL = 13;
- EAI_OVERFLOW = 14;
- RESOLV_TIMEOUT = 255;
- EAI_MAX = 256;
- }
- optional ReturnCode return_code = 2;
+ optional android.stats.dnsresolver.ReturnCode return_code = 2;
- // The latency period(in microseconds) it took for this DNS lookup to complete.
+ // The latency in microseconds of the entire DNS lookup operation.
optional int32 latency_micros = 3;
+
+ // Only valid for event_type = EVENT_GETADDRINFO.
+ optional int32 hints_ai_flags = 4;
+
+ // Flags passed to android_res_nsend() defined in multinetwork.h
+ // Only valid for event_type = EVENT_RESNSEND.
+ optional int32 res_nsend_flags = 5;
+
+ optional android.stats.dnsresolver.Transport network_type = 6;
+
+ // The DNS over TLS mode on a specific netId.
+ optional android.stats.dnsresolver.PrivateDnsModes private_dns_modes = 7;
+
+ // Additional pass-through fields opaque to statsd.
+ // The DNS resolver Mainline module can add new fields here without requiring an OS update.
+ optional android.stats.dnsresolver.DnsQueryEvents dns_query_events = 8 [(log_mode) = MODE_BYTES];
}
/**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 70fa5fa..f6b7eef 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -555,7 +555,7 @@
new CachedServiceFetcher<RcsManager>() {
@Override
public RcsManager createService(ContextImpl ctx) {
- return new RcsManager();
+ return new RcsManager(ctx.getOuterContext());
}
});
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 1c9a43a..9c21e8f 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,7 +1,9 @@
-artikz@google.com
+alsutton@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
+nathch@google.com
+rthakohov@google.com
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 9faa1d6..e7f2d18 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -22,23 +22,16 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -209,101 +202,32 @@
@UnsupportedAppUsage
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
- private Context mContext;
- private ServiceListener mServiceListener;
- private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
- @GuardedBy("mServiceLock")
- private IBluetoothA2dp mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
- } else {
- try {
- mServiceLock.readLock().lock();
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
+ private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
+ IBluetoothA2dp.class.getName()) {
+ @Override
+ public IBluetoothA2dp getServiceInterface(IBinder service) {
+ return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
- /*package*/ BluetoothA2dp(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothA2dp(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothA2dp.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
+ private IBluetoothA2dp getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -333,17 +257,15 @@
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.connect(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.connect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -376,17 +298,15 @@
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.disconnect(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.disconnect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -397,17 +317,15 @@
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getConnectedDevices();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getConnectedDevices();
}
- 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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -418,17 +336,15 @@
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getDevicesMatchingConnectionStates(states);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getDevicesMatchingConnectionStates(states);
}
- 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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -439,18 +355,16 @@
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
}
- 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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -480,18 +394,16 @@
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
- return mService.setActiveDevice(device);
+ return service.setActiveDevice(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -511,17 +423,15 @@
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getActiveDevice();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getActiveDevice();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return null;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -543,22 +453,20 @@
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -578,18 +486,16 @@
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getPriority(device);
+ return service.getPriority(device);
}
- 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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -602,17 +508,15 @@
public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.isAvrcpAbsoluteVolumeSupported();
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.isAvrcpAbsoluteVolumeSupported();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -625,15 +529,13 @@
public void setAvrcpAbsoluteVolume(int volume) {
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- mService.setAvrcpAbsoluteVolume(volume);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ service.setAvrcpAbsoluteVolume(volume);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -646,18 +548,16 @@
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.isA2dpPlaying(device);
+ return service.isA2dpPlaying(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -694,19 +594,17 @@
public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getCodecStatus(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ return service.getCodecStatus(device);
}
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return null;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
return null;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -723,17 +621,15 @@
BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- mService.setCodecConfigPreference(device, codecConfig);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
+ service.setCodecConfigPreference(device, codecConfig);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -772,21 +668,19 @@
*/
private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()) {
if (enable) {
- mService.enableOptionalCodecs(device);
+ service.enableOptionalCodecs(device);
} else {
- mService.disableOptionalCodecs(device);
+ service.disableOptionalCodecs(device);
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -801,17 +695,15 @@
@UnsupportedAppUsage
public int supportsOptionalCodecs(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.supportsOptionalCodecs(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.supportsOptionalCodecs(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -826,17 +718,15 @@
@UnsupportedAppUsage
public int getOptionalCodecsEnabled(BluetoothDevice device) {
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.getOptionalCodecsEnabled(device);
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.getOptionalCodecsEnabled(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -858,18 +748,16 @@
Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
return;
}
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ final IBluetoothA2dp service = getService();
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- mService.setOptionalCodecsEnabled(device, value);
+ service.setOptionalCodecsEnabled(device, value);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -900,35 +788,6 @@
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- try {
- mServiceLock.writeLock().lock();
- mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
- } finally {
- mServiceLock.writeLock().unlock();
- }
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- } finally {
- mServiceLock.writeLock().unlock();
- }
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
- }
- }
- };
-
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index fda2f89..5a8055a 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -124,93 +121,31 @@
public static final String EXTRA_AUDIO_CONFIG =
"android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothA2dpSink mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
+ "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
+ @Override
+ public IBluetoothA2dpSink getServiceInterface(IBinder service) {
+ return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
- /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothA2dpSink(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private IBluetoothA2dpSink getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -241,7 +176,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -282,7 +217,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -301,7 +236,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -320,7 +255,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -339,7 +274,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -365,7 +300,7 @@
*/
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
if (VDBG) log("getAudioConfig(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getAudioConfig(device);
@@ -395,7 +330,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -427,7 +362,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -448,7 +383,7 @@
* @param device BluetoothDevice device
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
- final IBluetoothA2dpSink service = mService;
+ final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.isA2dpPlaying(device);
@@ -487,25 +422,6 @@
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- 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);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index e7c8944..4e7e441 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -16,10 +16,7 @@
package android.bluetooth;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -79,93 +76,32 @@
public static final String EXTRA_PLAYER_SETTING =
"android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothAvrcpController mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
+ "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
+ @Override
+ public IBluetoothAvrcpController getServiceInterface(IBinder service) {
+ return IBluetoothAvrcpController.Stub.asInterface(
+ Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothAvrcpController proxy object for interacting with the local
* Bluetooth AVRCP service.
*/
- /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothAvrcpController.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private IBluetoothAvrcpController getService() {
+ return mProfileConnector.getService();
}
@Override
@@ -179,7 +115,8 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -198,7 +135,8 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -217,7 +155,8 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -238,7 +177,8 @@
public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getPlayerSettings");
BluetoothAvrcpPlayerSettings settings = null;
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
settings = service.getPlayerSettings(device);
@@ -256,7 +196,8 @@
*/
public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.setPlayerApplicationSetting(plAppSetting);
@@ -276,7 +217,8 @@
public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
+ keyState);
- final IBluetoothAvrcpController service = mService;
+ final IBluetoothAvrcpController service =
+ getService();
if (service != null && isEnabled()) {
try {
service.sendGroupNavigationCmd(device, keyCode, keyState);
@@ -289,25 +231,6 @@
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);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 8d9d340..9862a63 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -337,19 +337,9 @@
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
doUnbind();
} else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doBind();
}
}
};
@@ -374,24 +364,32 @@
doBind();
}
- boolean doBind() {
- try {
- return mAdapter.getBluetoothManager().bindBluetoothProfileService(
- BluetoothProfile.HEADSET, mConnection);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to bind HeadsetService", e);
+ private boolean doBind() {
+ synchronized (mConnection) {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG, "Binding service...");
+ try {
+ return mAdapter.getBluetoothManager().bindBluetoothProfileService(
+ BluetoothProfile.HEADSET, mConnection);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to bind HeadsetService", e);
+ }
+ }
}
return false;
}
- void doUnbind() {
+ private void doUnbind() {
synchronized (mConnection) {
if (mService != null) {
+ if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mAdapter.getBluetoothManager().unbindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to unbind HeadsetService", e);
+ } finally {
+ mService = null;
}
}
}
@@ -411,8 +409,8 @@
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
mServiceListener = null;
@@ -1169,7 +1167,7 @@
@Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
+ doUnbind();
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_HEADSET_SERVICE_DISCONNECTED));
}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index ec18d42..05833b5 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -366,73 +363,22 @@
public static final int CALL_ACCEPT_HOLD = 1;
public static final int CALL_ACCEPT_TERMINATE = 2;
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothHeadsetClient mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
+ private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
+ "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
@Override
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- Intent intent = new Intent(
- IBluetoothHeadsetClient.class.getName());
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
+ return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHeadsetClient proxy object.
*/
- /*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHeadsetClient(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/**
@@ -443,27 +389,11 @@
*/
/*package*/ void close() {
if (VDBG) log("close()");
+ mProfileConnector.disconnect();
+ }
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
-
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothHeadsetClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -480,7 +410,8 @@
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -503,7 +434,8 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -524,7 +456,8 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -547,7 +480,8 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -569,7 +503,8 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -589,7 +524,8 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -611,7 +547,8 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -637,7 +574,8 @@
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.startVoiceRecognition(device);
@@ -662,7 +600,8 @@
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.stopVoiceRecognition(device);
@@ -682,7 +621,8 @@
*/
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentCalls(device);
@@ -702,7 +642,8 @@
*/
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentAgEvents(device);
@@ -726,7 +667,8 @@
@UnsupportedAppUsage
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.acceptCall(device, flag);
@@ -747,7 +689,8 @@
*/
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.holdCall(device);
@@ -773,7 +716,8 @@
@UnsupportedAppUsage
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.rejectCall(device);
@@ -803,7 +747,8 @@
*/
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.terminateCall(device, call);
@@ -831,7 +776,8 @@
*/
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.enterPrivateMode(device, index);
@@ -858,7 +804,8 @@
*/
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.explicitCallTransfer(device);
@@ -881,7 +828,8 @@
*/
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.dial(device, number);
@@ -905,7 +853,8 @@
*/
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendDTMF(device, code);
@@ -931,7 +880,8 @@
*/
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
if (DBG) log("getLastVoiceTagNumber()");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getLastVoiceTagNumber(device);
@@ -951,7 +901,8 @@
@UnsupportedAppUsage
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getAudioState(device);
@@ -974,7 +925,8 @@
*/
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
service.setAudioRouteAllowed(device, allowed);
@@ -996,7 +948,8 @@
*/
public boolean getAudioRouteAllowed(BluetoothDevice device) {
if (VDBG) log("getAudioRouteAllowed");
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getAudioRouteAllowed(device);
@@ -1020,7 +973,8 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean connectAudio(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.connectAudio(device);
@@ -1044,7 +998,8 @@
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean disconnectAudio(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.disconnectAudio(device);
@@ -1065,7 +1020,8 @@
* @return bundle of AG features; null if no service or AG not connected
*/
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
- final IBluetoothHeadsetClient service = mService;
+ final IBluetoothHeadsetClient service =
+ getService();
if (service != null && isEnabled()) {
try {
return service.getCurrentAgFeatures(device);
@@ -1079,29 +1035,6 @@
return null;
}
-
- private final ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
- BluetoothHeadsetClient.this);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 58ff2e1..60fb6fb 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,20 +22,14 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This class provides the public APIs to control the Hearing Aid profile.
@@ -128,97 +122,31 @@
*/
public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
- private Context mContext;
- private ServiceListener mServiceListener;
- private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
- @GuardedBy("mServiceLock")
- private IBluetoothHearingAid mService;
private BluetoothAdapter mAdapter;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
- } else {
- try {
- mServiceLock.readLock().lock();
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
+ private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
+ "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
+ @Override
+ public IBluetoothHearingAid getServiceInterface(IBinder service) {
+ return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHearingAid proxy object for interacting with the local
* Bluetooth Hearing Aid service.
*/
- /*package*/ BluetoothHearingAid(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHearingAid(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- void doBind() {
- Intent intent = new Intent(IBluetoothHearingAid.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- android.os.Process.myUserHandle())) {
- Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent);
- return;
- }
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
- mServiceListener = null;
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- try {
- mServiceLock.writeLock().lock();
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- } finally {
- mServiceLock.writeLock().unlock();
- }
+ private IBluetoothHearingAid getService() {
+ return mProfileConnector.getService();
}
/**
@@ -240,18 +168,16 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.connect(device);
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.connect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -282,18 +208,16 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled() && isValidDevice(device)) {
- return mService.disconnect(device);
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.disconnect(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -303,18 +227,16 @@
@Override
public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getConnectedDevices();
+ if (service != null && isEnabled()) {
+ return service.getConnectedDevices();
}
- 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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -325,18 +247,16 @@
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
@NonNull int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getDevicesMatchingConnectionStates(states);
+ if (service != null && isEnabled()) {
+ return service.getDevicesMatchingConnectionStates(states);
}
- 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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -347,19 +267,17 @@
public @BluetoothProfile.BtProfileState int getConnectionState(
@NonNull BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getConnectionState(device);
+ return service.getConnectionState(device);
}
- 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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -387,20 +305,18 @@
*/
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
- mService.setActiveDevice(device);
+ service.setActiveDevice(device);
return true;
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -418,18 +334,16 @@
@RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getActiveDevices();
+ if (service != null && isEnabled()) {
+ return service.getActiveDevices();
}
- 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<>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<>();
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -450,23 +364,21 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
- return mService.setPriority(device, priority);
+ return service.setPriority(device, priority);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -484,19 +396,17 @@
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getPriority(device);
+ return service.getPriority(device);
}
- 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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -535,18 +445,16 @@
if (VDBG) {
log("getVolume()");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()) {
- return mService.getVolume();
+ if (service != null && isEnabled()) {
+ return service.getVolume();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return 0;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return 0;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -566,21 +474,18 @@
public void adjustVolume(int direction) {
if (DBG) log("adjustVolume(" + direction + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
-
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
- mService.adjustVolume(direction);
+ service.adjustVolume(direction);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -593,20 +498,18 @@
public void setVolume(int volume) {
if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
- mService.setVolume(volume);
+ service.setVolume(volume);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -622,21 +525,19 @@
if (VDBG) {
log("getCustomerId(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService == null) {
+ if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return HI_SYNC_ID_INVALID;
}
if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID;
- return mService.getHiSyncId(device);
+ return service.getHiSyncId(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return HI_SYNC_ID_INVALID;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -652,19 +553,17 @@
if (VDBG) {
log("getDeviceSide(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getDeviceSide(device);
+ return service.getDeviceSide(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return SIDE_LEFT;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return SIDE_LEFT;
- } finally {
- mServiceLock.readLock().unlock();
}
}
@@ -680,52 +579,20 @@
if (VDBG) {
log("getDeviceMode(" + device + ")");
}
+ final IBluetoothHearingAid service = getService();
try {
- mServiceLock.readLock().lock();
- if (mService != null && isEnabled()
+ if (service != null && isEnabled()
&& isValidDevice(device)) {
- return mService.getDeviceMode(device);
+ return service.getDeviceMode(device);
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return MODE_MONAURAL;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return MODE_MONAURAL;
- } finally {
- mServiceLock.readLock().unlock();
}
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- try {
- mServiceLock.writeLock().lock();
- mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
- } finally {
- mServiceLock.writeLock().unlock();
- }
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID,
- BluetoothHearingAid.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- try {
- mServiceLock.writeLock().lock();
- mService = null;
- } finally {
- mServiceLock.writeLock().unlock();
- }
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID);
- }
- }
- };
-
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index 3bc8544..e9b0be2 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -18,10 +18,8 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -327,11 +325,6 @@
}
}
- private Context mContext;
- private ServiceListener mServiceListener;
- private volatile IBluetoothHidDevice mService;
- private BluetoothAdapter mAdapter;
-
private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
private final Executor mExecutor;
@@ -385,114 +378,33 @@
}
}
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
-
- public void onBluetoothStateChange(boolean up) {
- Log.d(TAG, "onBluetoothStateChange: up=" + up);
- synchronized (mConnection) {
- if (up) {
- try {
- if (mService == null) {
- Log.d(TAG, "Binding HID Device service...");
- doBind();
- }
- } catch (IllegalStateException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
- + "service: ", e);
- } catch (SecurityException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
- + "service: ", e);
- }
- } else {
- Log.d(TAG, "Unbinding service...");
- doUnbind();
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
+ "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
+ @Override
+ public IBluetoothHidDevice getServiceInterface(IBinder service) {
+ return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service));
}
- };
-
- private final ServiceConnection mConnection =
- new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "onServiceConnected()");
- mService = IBluetoothHidDevice.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(
- BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- Log.d(TAG, "onServiceDisconnected()");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
- }
- }
- };
+ };
BluetoothHidDevice(Context context, ServiceListener listener) {
- mContext = context;
- mServiceListener = listener;
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHidDevice.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
- return false;
- }
- Log.d(TAG, "Bound to HID Device Service");
- return true;
- }
-
- void doUnbind() {
- if (mService != null) {
- mService = null;
- try {
- mContext.unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Unable to unbind HidDevService", e);
- }
- }
+ mProfileConnector.connect(context, listener);
}
void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- doUnbind();
- }
- mServiceListener = null;
+ private IBluetoothHidDevice getService() {
+ return mProfileConnector.getService();
}
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getConnectedDevices() {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectedDevices();
@@ -509,7 +421,7 @@
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -526,7 +438,7 @@
/** {@inheritDoc} */
@Override
public int getConnectionState(BluetoothDevice device) {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectionState(device);
@@ -583,7 +495,7 @@
throw new IllegalArgumentException("callback parameter cannot be null");
}
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
CallbackWrapper cbw = new CallbackWrapper(executor, callback);
@@ -611,7 +523,7 @@
public boolean unregisterApp() {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.unregisterApp();
@@ -636,7 +548,7 @@
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.sendReport(device, id, data);
@@ -662,7 +574,7 @@
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.replyReport(device, type, id, data);
@@ -686,7 +598,7 @@
public boolean reportError(BluetoothDevice device, byte error) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.reportError(device, error);
@@ -707,7 +619,7 @@
* {@hide}
*/
public String getUserAppName() {
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
@@ -733,7 +645,7 @@
public boolean connect(BluetoothDevice device) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.connect(device);
@@ -757,7 +669,7 @@
public boolean disconnect(BluetoothDevice device) {
boolean result = false;
- final IBluetoothHidDevice service = mService;
+ final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.disconnect(device);
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 289e769..4afb382 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -18,10 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -219,97 +216,32 @@
public static final String EXTRA_IDLE_TIME =
"android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
- private Context mContext;
- private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private volatile IBluetoothHidHost mService;
-
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
+ "BluetoothHidHost", IBluetoothHidHost.class.getName()) {
+ @Override
+ public IBluetoothHidHost getServiceInterface(IBinder service) {
+ return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothHidHost proxy object for interacting with the local
* Bluetooth Service which handles the InputDevice profile
*/
- /*package*/ BluetoothHidHost(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothHidHost(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
-
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothHidHost.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
if (VDBG) log("close()");
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothHidHost getService() {
+ return mProfileConnector.getService();
}
/**
@@ -333,7 +265,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -373,7 +305,7 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -392,7 +324,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -411,7 +343,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -430,7 +362,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -460,7 +392,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -492,7 +424,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -505,26 +437,6 @@
return BluetoothProfile.PRIORITY_OFF;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
-
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.HID_HOST,
- BluetoothHidHost.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.HID_HOST);
- }
- }
- };
-
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
@@ -544,7 +456,7 @@
*/
public boolean virtualUnplug(BluetoothDevice device) {
if (DBG) log("virtualUnplug(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.virtualUnplug(device);
@@ -570,7 +482,7 @@
*/
public boolean getProtocolMode(BluetoothDevice device) {
if (VDBG) log("getProtocolMode(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getProtocolMode(device);
@@ -594,7 +506,7 @@
*/
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
if (DBG) log("setProtocolMode(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setProtocolMode(device, protocolMode);
@@ -625,7 +537,7 @@
log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+ "bufferSize=" + bufferSize);
}
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getReport(device, reportType, reportId, bufferSize);
@@ -651,7 +563,7 @@
*/
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setReport(device, reportType, report);
@@ -676,7 +588,7 @@
*/
public boolean sendData(BluetoothDevice device, String report) {
if (DBG) log("sendData(" + device + "), report=" + report);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendData(device, report);
@@ -700,7 +612,7 @@
*/
public boolean getIdleTime(BluetoothDevice device) {
if (DBG) log("getIdletime(" + device + ")");
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getIdleTime(device);
@@ -725,7 +637,7 @@
*/
public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
- final IBluetoothHidHost service = mService;
+ final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setIdleTime(device, idleTime);
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 98c23c6..dd2f150 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -44,11 +41,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothMap mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -57,64 +49,23 @@
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.MAP,
+ "BluetoothMap", IBluetoothMap.class.getName()) {
+ @Override
+ public IBluetoothMap getServiceInterface(IBinder service) {
+ return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothMap proxy object.
*/
- /*package*/ BluetoothMap(Context context, ServiceListener l) {
+ /*package*/ BluetoothMap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothMap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -132,26 +83,11 @@
* are ok.
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothMap getService() {
+ return mProfileConnector.getService();
}
/**
@@ -162,7 +98,7 @@
*/
public int getState() {
if (VDBG) log("getState()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getState();
@@ -184,7 +120,7 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -205,7 +141,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -237,7 +173,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -278,7 +214,7 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -298,7 +234,7 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -318,7 +254,7 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -344,7 +280,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -373,7 +309,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothMap service = mService;
+ final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -386,24 +322,6 @@
return PRIORITY_OFF;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) log("Proxy object connected");
- mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) log("Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.MAP);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 559a59b..ec0180c5 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -18,11 +18,9 @@
import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.net.Uri;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -60,11 +58,6 @@
public static final String EXTRA_SENDER_CONTACT_NAME =
"android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
- private volatile IBluetoothMapClient mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -75,64 +68,23 @@
private static final int UPLOADING_FEATURE_BITMASK = 0x08;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
+ "BluetoothMapClient", IBluetoothMapClient.class.getName()) {
+ @Override
+ public IBluetoothMapClient getServiceInterface(IBinder service) {
+ return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothMapClient proxy object.
*/
- /*package*/ BluetoothMapClient(Context context, ServiceListener l) {
+ /*package*/ BluetoothMapClient(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothMapClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -150,26 +102,11 @@
* are ok.
*/
public void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothMapClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -179,7 +116,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -199,7 +136,7 @@
*/
public boolean connect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.connect(device);
@@ -221,7 +158,7 @@
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -241,7 +178,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -262,7 +199,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -283,7 +220,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -307,7 +244,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -336,7 +273,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -365,7 +302,7 @@
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
PendingIntent sentIntent, PendingIntent deliveredIntent) {
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
@@ -385,7 +322,7 @@
*/
public boolean getUnreadMessages(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
- final IBluetoothMapClient service = mService;
+ final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getUnreadMessages(device);
@@ -405,34 +342,16 @@
* MapSupportedFeatures field is set. False is returned otherwise.
*/
public boolean isUploadingSupported(BluetoothDevice device) {
+ final IBluetoothMapClient service = getService();
try {
- return (mService != null && isEnabled() && isValidDevice(device))
- && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
+ return (service != null && isEnabled() && isValidDevice(device))
+ && ((service.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
return false;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothMapClient.Stub.asInterface(service);
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
- BluetoothMapClient.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
- }
- }
- };
-
private boolean isEnabled() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 58be732..fb78789 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -19,10 +19,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -121,108 +118,42 @@
*/
public static final int PAN_OPERATION_SUCCESS = 1004;
- private Context mContext;
- private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
- private volatile IBluetoothPan mPanService;
+ private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.PAN,
+ "BluetoothPan", IBluetoothPan.class.getName()) {
+ @Override
+ public IBluetoothPan getServiceInterface(IBinder service) {
+ return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
+ }
+ };
+
/**
* Create a BluetoothPan proxy object for interacting with the local
* Bluetooth Service which handles the Pan profile
*/
@UnsupportedAppUsage
- /*package*/ BluetoothPan(Context context, ServiceListener l) {
- mContext = context;
- mServiceListener = l;
+ /*package*/ BluetoothPan(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- try {
- mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
- } catch (RemoteException re) {
- Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- if (VDBG) Log.d(TAG, "BluetoothPan() call bindService");
- doBind();
- }
-
- @UnsupportedAppUsage
- boolean doBind() {
- Intent intent = new Intent(IBluetoothPan.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
if (VDBG) log("close()");
-
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mStateChangeCallback);
- } catch (RemoteException re) {
- Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
- }
- }
-
- synchronized (mConnection) {
- if (mPanService != null) {
- try {
- mPanService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ mProfileConnector.disconnect();
}
+ private IBluetoothPan getService() {
+ return mProfileConnector.getService();
+ }
+
+
protected void finalize() {
close();
}
- private final IBluetoothStateChangeCallback mStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
-
- @Override
- public void onBluetoothStateChange(boolean on) {
- // Handle enable request to bind again.
- Log.d(TAG, "onBluetoothStateChange on: " + on);
- if (on) {
- try {
- if (mPanService == null) {
- if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()");
- doBind();
- }
-
- } catch (IllegalStateException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
- e);
-
- } catch (SecurityException e) {
- Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
- e);
- }
- } else {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mPanService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- }
- };
-
/**
* Initiate connection to a profile of the remote bluetooth device.
*
@@ -243,7 +174,7 @@
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -284,7 +215,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -303,7 +234,7 @@
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -322,7 +253,7 @@
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -341,7 +272,7 @@
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -357,7 +288,7 @@
@UnsupportedAppUsage
public void setBluetoothTethering(boolean value) {
if (DBG) log("setBluetoothTethering(" + value + ")");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
service.setBluetoothTethering(value);
@@ -370,7 +301,7 @@
@UnsupportedAppUsage
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
- final IBluetoothPan service = mPanService;
+ final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.isTetheringOn();
@@ -381,25 +312,6 @@
return false;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- 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);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
- mPanService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
- }
- }
- };
-
@UnsupportedAppUsage
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index b303c34..d94c657 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -24,6 +24,7 @@
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -117,28 +118,9 @@
public void onBluetoothStateChange(boolean up) {
log("onBluetoothStateChange: up=" + up);
if (!up) {
- log("Unbinding service...");
- synchronized (mConnection) {
- try {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doUnbind();
} else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- log("Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
+ doBind();
}
}
};
@@ -154,25 +136,51 @@
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
doBind();
}
boolean doBind() {
- Intent intent = new Intent(IBluetoothPbap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
- return false;
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ log("Binding service...");
+ Intent intent = new Intent(IBluetoothPbap.class.getName());
+ ComponentName comp = intent.resolveSystemService(
+ mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ UserHandle.CURRENT_OR_SELF)) {
+ Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
+ return false;
+ }
+ }
+ } catch (SecurityException se) {
+ Log.e(TAG, "", se);
+ return false;
+ }
}
return true;
}
+ private void doUnbind() {
+ synchronized (mConnection) {
+ if (mService != null) {
+ log("Unbinding service...");
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException ie) {
+ Log.e(TAG, "", ie);
+ } finally {
+ mService = null;
+ }
+ }
+ }
+ }
+
protected void finalize() throws Throwable {
try {
close();
@@ -192,21 +200,11 @@
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
}
}
-
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ doUnbind();
mServiceListener = null;
}
@@ -312,7 +310,7 @@
public void onServiceDisconnected(ComponentName className) {
log("Proxy object disconnected");
- mService = null;
+ doUnbind();
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected();
}
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index 1446adc..d70e1e7 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,10 +16,7 @@
package android.bluetooth;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -42,11 +39,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothPbapClient mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -55,72 +47,25 @@
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) {
- Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
- }
- if (!up) {
- if (VDBG) {
- Log.d(TAG, "Unbinding service...");
- }
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) {
- Log.d(TAG, "Binding service...");
- }
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
+ "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
+ @Override
+ public IBluetoothPbapClient getServiceInterface(IBinder service) {
+ return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothPbapClient proxy object.
*/
- BluetoothPbapClient(Context context, ServiceListener l) {
+ BluetoothPbapClient(Context context, ServiceListener listener) {
if (DBG) {
Log.d(TAG, "Create BluetoothPbapClient proxy object");
}
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- private boolean doBind() {
- Intent intent = new Intent(IBluetoothPbapClient.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -138,26 +83,11 @@
* are ok.
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothPbapClient getService() {
+ return mProfileConnector.getService();
}
/**
@@ -173,7 +103,7 @@
if (DBG) {
log("connect(" + device + ") for PBAP Client.");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -198,7 +128,7 @@
if (DBG) {
log("disconnect(" + device + ")" + new Exception());
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
service.disconnect(device);
@@ -225,7 +155,7 @@
if (DBG) {
log("getConnectedDevices()");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -250,7 +180,7 @@
if (DBG) {
log("getDevicesMatchingStates()");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -275,7 +205,7 @@
if (DBG) {
log("getConnectionState(" + device + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -290,29 +220,6 @@
return BluetoothProfile.STATE_DISCONNECTED;
}
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) {
- log("Proxy object connected");
- }
- mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT,
- BluetoothPbapClient.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) {
- log("Proxy object disconnected");
- }
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
@@ -345,7 +252,7 @@
if (DBG) {
log("setPriority(" + device + ", " + priority + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -378,7 +285,7 @@
if (VDBG) {
log("getPriority(" + device + ")");
}
- final IBluetoothPbapClient service = mService;
+ final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
new file mode 100644
index 0000000..d9987249
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019 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.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * Connector for Bluetooth profile proxies to bind manager service and
+ * profile services
+ * @param <T> The Bluetooth profile interface for this connection.
+ * @hide
+ */
+public abstract class BluetoothProfileConnector<T> {
+ private int mProfileId;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private BluetoothProfile mProfileProxy;
+ private Context mContext;
+ private String mProfileName;
+ private String mServiceName;
+ private volatile T mService;
+
+ private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (up) {
+ doBind();
+ } else {
+ doUnbind();
+ }
+ }
+ };
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ logDebug("Proxy object connected");
+ mService = getServiceInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ logDebug("Proxy object disconnected");
+ doUnbind();
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
+ }
+ }
+ };
+
+ BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
+ String serviceName) {
+ mProfileId = profileId;
+ mProfileProxy = profile;
+ mProfileName = profileName;
+ mServiceName = serviceName;
+ }
+
+ private boolean doBind() {
+ synchronized (mConnection) {
+ if (mService == null) {
+ logDebug("Binding service...");
+ try {
+ Intent intent = new Intent(mServiceName);
+ ComponentName comp = intent.resolveSystemService(
+ mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ UserHandle.CURRENT_OR_SELF)) {
+ logError("Could not bind to Bluetooth Service with " + intent);
+ return false;
+ }
+ } catch (SecurityException se) {
+ logError("Failed to bind service. " + se);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void doUnbind() {
+ synchronized (mConnection) {
+ if (mService != null) {
+ logDebug("Unbinding service...");
+ try {
+ mContext.unbindService(mConnection);
+ } catch (IllegalArgumentException ie) {
+ logError("Unable to unbind service: " + ie);
+ } finally {
+ mService = null;
+ }
+ }
+ }
+ }
+
+ void connect(Context context, BluetoothProfile.ServiceListener listener) {
+ mContext = context;
+ mServiceListener = listener;
+ IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException re) {
+ logError("Failed to register state change callback. " + re);
+ }
+ }
+ doBind();
+ }
+
+ void disconnect() {
+ mServiceListener = null;
+ IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException re) {
+ logError("Failed to unregister state change callback" + re);
+ }
+ }
+ doUnbind();
+ }
+
+ T getService() {
+ return mService;
+ }
+
+ /**
+ * This abstract function is used to implement method to get the
+ * connected Bluetooth service interface.
+ * @param service the connected binder service.
+ * @return T the binder interface of {@code service}.
+ * @hide
+ */
+ public abstract T getServiceInterface(IBinder service);
+
+ private void logDebug(String log) {
+ Log.d(mProfileName, log);
+ }
+
+ private void logError(String log) {
+ Log.e(mProfileName, log);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 1b73206..e0610c8 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -69,11 +66,6 @@
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
- private volatile IBluetoothSap mService;
- private final Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
-
/**
* There was an error trying to obtain the state.
*
@@ -95,64 +87,23 @@
*/
public static final int RESULT_CANCELED = 2;
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (VDBG) Log.d(TAG, "Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG, "Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
+ private BluetoothAdapter mAdapter;
+ private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.SAP,
+ "BluetoothSap", IBluetoothSap.class.getName()) {
+ @Override
+ public IBluetoothSap getServiceInterface(IBinder service) {
+ return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
}
- };
+ };
/**
* Create a BluetoothSap proxy object.
*/
- /*package*/ BluetoothSap(Context context, ServiceListener l) {
+ /*package*/ BluetoothSap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
- mContext = context;
- mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- }
- doBind();
- }
-
- boolean doBind() {
- Intent intent = new Intent(IBluetoothSap.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- intent.setComponent(comp);
- if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
- mContext.getUser())) {
- Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -172,26 +123,11 @@
* @hide
*/
public synchronized void close() {
- IBluetoothManager mgr = mAdapter.getBluetoothManager();
- if (mgr != null) {
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (Exception e) {
- Log.e(TAG, "", e);
- }
- }
+ mProfileConnector.disconnect();
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG, "", re);
- }
- }
- }
- mServiceListener = null;
+ private IBluetoothSap getService() {
+ return mProfileConnector.getService();
}
/**
@@ -203,7 +139,7 @@
*/
public int getState() {
if (VDBG) log("getState()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getState();
@@ -226,7 +162,7 @@
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -249,7 +185,7 @@
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -284,7 +220,7 @@
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -305,7 +241,7 @@
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -326,7 +262,7 @@
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -347,7 +283,7 @@
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -372,7 +308,7 @@
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -398,7 +334,7 @@
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- final IBluetoothSap service = mService;
+ final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -411,24 +347,6 @@
return PRIORITY_OFF;
}
- 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));
- if (mServiceListener != null) {
- mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this);
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) log("Proxy object disconnected");
- mService = null;
- if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.SAP);
- }
- }
- };
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 72981a7..4f7f07b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2719,6 +2719,16 @@
= "android.content.pm.CLEAN_EXTERNAL_STORAGE";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
+ * the requisite kernel support for multinetworking-capable IPsec tunnels.
+ *
+ * <p>This feature implies that the device supports XFRM Interfaces (CONFIG_XFRM_INTERFACE), or
+ * VTIs with kernel patches allowing updates of output/set mark via UPDSA.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
+
+ /**
* Extra field name for the URI to a verification file. Passed to a package
* verifier.
*
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d710d57..ca43d40 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -80,7 +80,6 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Base64;
-import android.util.ByteStringUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.PackageUtils;
@@ -99,6 +98,7 @@
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -5999,7 +5999,8 @@
}
// first see if the hash represents a single-signer in our signing history
- byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
+ byte[] sha256Bytes = sha256String == null
+ ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */);
if (hasSha256Certificate(sha256Bytes, flags)) {
return true;
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0e10de8..a69ca99 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3449,6 +3449,10 @@
final NetworkCallback callback;
synchronized (sCallbacks) {
callback = sCallbacks.get(request);
+ if (message.what == CALLBACK_UNAVAIL) {
+ sCallbacks.remove(request);
+ callback.networkRequest = ALREADY_UNREGISTERED;
+ }
}
if (DBG) {
Log.d(TAG, getCallbackName(message.what) + " for network " + network);
@@ -3995,8 +3999,10 @@
synchronized (sCallbacks) {
Preconditions.checkArgument(networkCallback.networkRequest != null,
"NetworkCallback was not registered");
- Preconditions.checkArgument(networkCallback.networkRequest != ALREADY_UNREGISTERED,
- "NetworkCallback was already unregistered");
+ if (networkCallback.networkRequest == ALREADY_UNREGISTERED) {
+ Log.d(TAG, "NetworkCallback was already unregistered");
+ return;
+ }
for (Map.Entry<NetworkRequest, NetworkCallback> e : sCallbacks.entrySet()) {
if (e.getValue() == networkCallback) {
reqs.add(e.getKey());
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index a33f3fc..65bc75b 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -64,6 +64,8 @@
@UnsupportedAppUsage
public int mtu;
+ public String serverHostName;
+
public DhcpResults() {
super();
}
@@ -97,6 +99,7 @@
vendorInfo = source.vendorInfo;
leaseDuration = source.leaseDuration;
mtu = source.mtu;
+ serverHostName = source.serverHostName;
}
}
@@ -129,6 +132,7 @@
vendorInfo = null;
leaseDuration = 0;
mtu = 0;
+ serverHostName = null;
}
@Override
@@ -139,6 +143,7 @@
str.append(" Vendor info ").append(vendorInfo);
str.append(" lease ").append(leaseDuration).append(" seconds");
if (mtu != 0) str.append(" MTU ").append(mtu);
+ str.append(" Servername ").append(serverHostName);
return str.toString();
}
@@ -154,6 +159,7 @@
return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
&& Objects.equals(serverAddress, target.serverAddress)
&& Objects.equals(vendorInfo, target.vendorInfo)
+ && Objects.equals(serverHostName, target.serverHostName)
&& leaseDuration == target.leaseDuration
&& mtu == target.mtu;
}
@@ -179,6 +185,7 @@
dest.writeInt(mtu);
InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
dest.writeString(vendorInfo);
+ dest.writeString(serverHostName);
}
@Override
@@ -193,6 +200,7 @@
dhcpResults.mtu = in.readInt();
dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
dhcpResults.vendorInfo = in.readString();
+ dhcpResults.serverHostName = in.readString();
return dhcpResults;
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index d4c3edc..889e9bc 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -941,7 +941,8 @@
throw new IllegalArgumentException(sse);
} else if (sse.errorCode == OsConstants.EAGAIN) {
throw new IllegalStateException(sse);
- } else if (sse.errorCode == OsConstants.EOPNOTSUPP) {
+ } else if (sse.errorCode == OsConstants.EOPNOTSUPP
+ || sse.errorCode == OsConstants.EPROTONOSUPPORT) {
throw new UnsupportedOperationException(sse);
}
}
diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java
index 30d3b84..cd8ce8d 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -176,7 +176,7 @@
out.writeInt(filteredRas);
out.writeInt(currentRas);
out.writeInt(programLength);
- out.writeInt(flags);
+ out.writeInt(this.flags);
}
/** @hide */
@@ -192,6 +192,18 @@
programLength, actualLifetime, lifetimeString, namesOf(flags));
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false;
+ final ApfProgramEvent other = (ApfProgramEvent) obj;
+ return lifetime == other.lifetime
+ && actualLifetime == other.actualLifetime
+ && filteredRas == other.filteredRas
+ && currentRas == other.currentRas
+ && programLength == other.programLength
+ && flags == other.flags;
+ }
+
/** @hide */
public static final Parcelable.Creator<ApfProgramEvent> CREATOR
= new Parcelable.Creator<ApfProgramEvent>() {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index ddc788d..2e78469 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -275,6 +275,22 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfStats.class))) return false;
+ final ApfStats other = (ApfStats) obj;
+ return durationMs == other.durationMs
+ && receivedRas == other.receivedRas
+ && matchingRas == other.matchingRas
+ && droppedRas == other.droppedRas
+ && zeroLifetimeRas == other.zeroLifetimeRas
+ && parseErrors == other.parseErrors
+ && programUpdates == other.programUpdates
+ && programUpdatesAll == other.programUpdatesAll
+ && programUpdatesAllowingMulticast == other.programUpdatesAllowingMulticast
+ && maxProgramSize == other.maxProgramSize;
+ }
+
/** @hide */
public static final Parcelable.Creator<ApfStats> CREATOR = new Parcelable.Creator<ApfStats>() {
public ApfStats createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 93063cb..fa6bff3 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -22,6 +22,7 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
* An event recorded when a DhcpClient state machine transitions to a new state.
@@ -101,6 +102,14 @@
return String.format("DhcpClientEvent(%s, %dms)", msg, durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(DhcpClientEvent.class))) return false;
+ final DhcpClientEvent other = (DhcpClientEvent) obj;
+ return TextUtils.equals(msg, other.msg)
+ && durationMs == other.durationMs;
+ }
+
/** @hide */
public static final Parcelable.Creator<DhcpClientEvent> CREATOR
= new Parcelable.Creator<DhcpClientEvent>() {
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index 013e353..77908e6 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -101,6 +101,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpManagerEvent.class))) return false;
+ final IpManagerEvent other = (IpManagerEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{IpManagerEvent.class},
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index c736297..f9ee39b 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -93,6 +93,13 @@
return String.format("IpReachabilityEvent(%s:%02x)", eventName, lo);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpReachabilityEvent.class))) return false;
+ final IpReachabilityEvent other = (IpReachabilityEvent) obj;
+ return eventType == other.eventType;
+ }
+
final static class Decoder {
static final SparseArray<String> constants =
MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class},
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 5128115..ec0f82a 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -121,6 +121,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(NetworkEvent.class))) return false;
+ final NetworkEvent other = (NetworkEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"});
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index d16a104..6ccca7d 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -97,6 +97,18 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(RaEvent.class))) return false;
+ final RaEvent other = (RaEvent) obj;
+ return routerLifetime == other.routerLifetime
+ && prefixValidLifetime == other.prefixValidLifetime
+ && prefixPreferredLifetime == other.prefixPreferredLifetime
+ && routeInfoLifetime == other.routeInfoLifetime
+ && rdnssLifetime == other.rdnssLifetime
+ && dnsslLifetime == other.dnsslLifetime;
+ }
+
/** @hide */
public static final Parcelable.Creator<RaEvent> CREATOR = new Parcelable.Creator<RaEvent>() {
public RaEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index ebca7e6..6784420 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -170,6 +170,15 @@
getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ValidationProbeEvent.class))) return false;
+ final ValidationProbeEvent other = (ValidationProbeEvent) obj;
+ return durationMs == other.durationMs
+ && probeType == other.probeType
+ && returnCode == other.returnCode;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{ValidationProbeEvent.class},
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index e366fe0..32735aa 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -32,7 +32,7 @@
import libcore.io.IoUtils;
import java.io.File;
-import java.io.IOException;
+import java.io.FileNotFoundException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
@@ -146,7 +146,6 @@
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@NonNull BugreportCallback callback) {
- File tmpScreenshotFile = null;
try {
Preconditions.checkNotNull(bugreportFd);
Preconditions.checkNotNull(params);
@@ -155,13 +154,10 @@
if (screenshotFd == null) {
// Binder needs a valid File Descriptor to be passed
- tmpScreenshotFile = File.createTempFile("tmp", ".png");
- screenshotFd = ParcelFileDescriptor.open(tmpScreenshotFile,
+ screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
ParcelFileDescriptor.MODE_READ_ONLY);
}
- DumpstateListener dsListener = new DumpstateListener(executor,
- callback, tmpScreenshotFile);
-
+ DumpstateListener dsListener = new DumpstateListener(executor, callback);
// Note: mBinder can get callingUid from the binder transaction.
mBinder.startBugreport(-1 /* callingUid */,
mContext.getOpPackageName(),
@@ -169,13 +165,9 @@
screenshotFd.getFileDescriptor(),
params.getMode(), dsListener);
} catch (RemoteException e) {
- deleteFile(tmpScreenshotFile);
throw e.rethrowFromSystemServer();
- } catch (IOException e) {
- // Need to delete the file if it was created but failed while trying to get fd
- deleteFile(tmpScreenshotFile);
- Log.e(TAG, "Not able to create/open temporary screenshot file ", e);
- callback.onError(BugreportCallback.BUGREPORT_ERROR_RUNTIME);
+ } catch (FileNotFoundException e) {
+ Log.wtf(TAG, "Not able to find /dev/null file: ", e);
} finally {
// We can close the file descriptors here because binder would have duped them.
IoUtils.closeQuietly(bugreportFd);
@@ -197,26 +189,13 @@
}
}
- private void deleteFile(@Nullable File tmpScreenshotFile) {
- try {
- if (tmpScreenshotFile != null && tmpScreenshotFile.exists()) {
- tmpScreenshotFile.delete();
- }
- } catch (SecurityException e) {
- Log.e(TAG, "Not able to delete temporary screenshot file ", e);
- }
- }
-
private final class DumpstateListener extends IDumpstateListener.Stub {
private final Executor mExecutor;
private final BugreportCallback mCallback;
- private final File mTmpScreenshotFile;
- DumpstateListener(Executor executor, BugreportCallback callback,
- @Nullable File tmpScreenshotFile) {
+ DumpstateListener(Executor executor, BugreportCallback callback) {
mExecutor = executor;
mCallback = callback;
- mTmpScreenshotFile = tmpScreenshotFile;
}
@Override
@@ -240,7 +219,6 @@
});
} finally {
Binder.restoreCallingIdentity(identity);
- deleteFile(mTmpScreenshotFile);
}
}
@@ -253,7 +231,6 @@
});
} finally {
Binder.restoreCallingIdentity(identity);
- deleteFile(mTmpScreenshotFile);
}
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 03e8c15..7f60b9c 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -363,18 +363,6 @@
boolean isNetworkActive();
/**
- * Setup a new physical network.
- * @param permission PERMISSION_NONE if no permissions required to access this network.
- * PERMISSION_NETWORK or PERMISSION_SYSTEM to set respective permission.
- */
- void createPhysicalNetwork(int netId, int permission);
-
- /**
- * Setup a new VPN.
- */
- void createVirtualNetwork(int netId, boolean secure);
-
- /**
* Add an interface to a network.
*/
void addInterfaceToNetwork(String iface, int netId);
@@ -396,9 +384,6 @@
*/
void setNetworkPermission(int netId, int permission);
- void setPermission(String permission, in int[] uids);
- void clearPermission(in int[] uids);
-
/**
* Allow UID to call protect().
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f98641d..e94d3a7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10336,8 +10336,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
/**
@@ -10346,8 +10344,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
/**
@@ -10356,8 +10352,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
/**
@@ -10367,8 +10361,6 @@
* The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
/**
@@ -10397,8 +10389,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
/**
@@ -10407,8 +10397,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
/**
@@ -10417,8 +10405,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
/**
@@ -10427,8 +10413,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
"captive_portal_other_fallback_urls";
@@ -10438,8 +10422,6 @@
* by "@@,@@".
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
"captive_portal_fallback_probe_specs";
@@ -10450,8 +10432,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
/**
@@ -10460,8 +10440,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
/**
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index 3861695..fc23c54 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -19,7 +19,7 @@
import android.annotation.Nullable;
import android.text.TextUtils;
-import libcore.net.MimeUtils;
+import libcore.net.MimeMap;
import java.util.regex.Pattern;
@@ -79,7 +79,7 @@
* @return {@code true} if there is a mimeType entry in the map.
*/
public boolean hasMimeType(String mimeType) {
- return MimeUtils.hasMimeType(mimeType);
+ return MimeMap.getDefault().hasMimeType(mimeType);
}
/**
@@ -89,12 +89,12 @@
*/
@Nullable
public String getMimeTypeFromExtension(String extension) {
- return MimeUtils.guessMimeTypeFromExtension(extension);
+ return MimeMap.getDefault().guessMimeTypeFromExtension(extension);
}
// Static method called by jni.
private static String mimeTypeFromExtension(String extension) {
- return MimeUtils.guessMimeTypeFromExtension(extension);
+ return MimeMap.getDefault().guessMimeTypeFromExtension(extension);
}
/**
@@ -103,7 +103,7 @@
* @return {@code true} if there is an extension entry in the map.
*/
public boolean hasExtension(String extension) {
- return MimeUtils.hasExtension(extension);
+ return MimeMap.getDefault().hasExtension(extension);
}
/**
@@ -115,7 +115,7 @@
*/
@Nullable
public String getExtensionFromMimeType(String mimeType) {
- return MimeUtils.guessExtensionFromMimeType(mimeType);
+ return MimeMap.getDefault().guessExtensionFromMimeType(mimeType);
}
/**
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 28c59db..c5fc9b3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -49,8 +49,8 @@
namespace android {
constexpr int MAXPACKETSIZE = 8 * 1024;
-// FrameworkListener limits the size of commands to 1024 bytes. TODO: fix this.
-constexpr int MAXCMDSIZE = 1024;
+// FrameworkListener limits the size of commands to 4096 bytes.
+constexpr int MAXCMDSIZE = 4096;
static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 9c60e6b..129b8af 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -188,7 +188,7 @@
if (env->IsInstanceOf(excep, gErrorClass)) {
/* It's an error */
LOG(ERROR) << "Forcefully exiting";
- exit(1);
+ _exit(1);
} else {
LOG(ERROR) << "Uncaught exception!";
}
diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp
index 182a621..a26707e 100644
--- a/core/jni/android_util_jar_StrictJarFile.cpp
+++ b/core/jni/android_util_jar_StrictJarFile.cpp
@@ -146,7 +146,7 @@
ZipEntry data;
const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
- ZipString(entryNameChars.c_str()), &data);
+ entryNameChars.c_str(), &data);
if (error) {
return NULL;
}
diff --git a/core/proto/android/stats/dnsresolver/Android.bp b/core/proto/android/stats/dnsresolver/Android.bp
new file mode 100644
index 0000000..0b5aa86
--- /dev/null
+++ b/core/proto/android/stats/dnsresolver/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 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.
+
+java_library_static {
+ name: "dnsresolverprotosnano",
+ proto: {
+ type: "nano",
+ },
+ srcs: [
+ "dns_resolver.proto",
+ ],
+ sdk_version: "system_current",
+ no_framework_libs: true,
+}
diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto
new file mode 100644
index 0000000..af6fea0
--- /dev/null
+++ b/core/proto/android/stats/dnsresolver/dns_resolver.proto
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+syntax = "proto2";
+package android.stats.dnsresolver;
+
+enum EventType {
+ EVENT_UNKNOWN = 0;
+ EVENT_GETADDRINFO = 1;
+ EVENT_GETHOSTBYNAME = 2;
+ EVENT_GETHOSTBYADDR = 3;
+ EVENT_RES_NSEND = 4;
+}
+
+// The return value of the DNS resolver for each DNS lookups.
+// bionic/libc/include/netdb.h
+// system/netd/resolv/include/netd_resolv/resolv.h
+enum ReturnCode {
+ RC_EAI_NO_ERROR = 0;
+ RC_EAI_ADDRFAMILY = 1;
+ RC_EAI_AGAIN = 2;
+ RC_EAI_BADFLAGS = 3;
+ RC_EAI_FAIL = 4;
+ RC_EAI_FAMILY = 5;
+ RC_EAI_MEMORY = 6;
+ RC_EAI_NODATA = 7;
+ RC_EAI_NONAME = 8;
+ RC_EAI_SERVICE = 9;
+ RC_EAI_SOCKTYPE = 10;
+ RC_EAI_SYSTEM = 11;
+ RC_EAI_BADHINTS = 12;
+ RC_EAI_PROTOCOL = 13;
+ RC_EAI_OVERFLOW = 14;
+ RC_RESOLV_TIMEOUT = 255;
+ RC_EAI_MAX = 256;
+}
+
+enum NsRcode {
+ NS_R_NO_ERROR = 0; // No error occurred.
+ NS_R_FORMERR = 1; // Format error.
+ NS_R_SERVFAIL = 2; // Server failure.
+ NS_R_NXDOMAIN = 3; // Name error.
+ NS_R_NOTIMPL = 4; // Unimplemented.
+ NS_R_REFUSED = 5; // Operation refused.
+ // these are for BIND_UPDATE
+ NS_R_YXDOMAIN = 6; // Name exists
+ NS_R_YXRRSET = 7; // RRset exists
+ NS_R_NXRRSET = 8; // RRset does not exist
+ NS_R_NOTAUTH = 9; // Not authoritative for zone
+ NS_R_NOTZONE = 10; // Zone of record different from zone section
+ NS_R_MAX = 11;
+ // The following are EDNS extended rcodes
+ NS_R_BADVERS = 16;
+ // The following are TSIG errors
+ // NS_R_BADSIG = 16,
+ NS_R_BADKEY = 17;
+ NS_R_BADTIME = 18;
+}
+
+// Currently defined type values for resources and queries.
+enum NsType {
+ NS_T_INVALID = 0; // Cookie.
+ NS_T_A = 1; // Host address.
+ NS_T_NS = 2; // Authoritative server.
+ NS_T_MD = 3; // Mail destination.
+ NS_T_MF = 4; // Mail forwarder.
+ NS_T_CNAME = 5; // Canonical name.
+ NS_T_SOA = 6; // Start of authority zone.
+ NS_T_MB = 7; // Mailbox domain name.
+ NS_T_MG = 8; // Mail group member.
+ NS_T_MR = 9; // Mail rename name.
+ NS_T_NULL = 10; // Null resource record.
+ NS_T_WKS = 11; // Well known service.
+ NS_T_PTR = 12; // Domain name pointer.
+ NS_T_HINFO = 13; // Host information.
+ NS_T_MINFO = 14; // Mailbox information.
+ NS_T_MX = 15; // Mail routing information.
+ NS_T_TXT = 16; // Text strings.
+ NS_T_RP = 17; // Responsible person.
+ NS_T_AFSDB = 18; // AFS cell database.
+ NS_T_X25 = 19; // X_25 calling address.
+ NS_T_ISDN = 20; // ISDN calling address.
+ NS_T_RT = 21; // Router.
+ NS_T_NSAP = 22; // NSAP address.
+ NS_T_NSAP_PTR = 23; // Reverse NSAP lookup (deprecated).
+ NS_T_SIG = 24; // Security signature.
+ NS_T_KEY = 25; // Security key.
+ NS_T_PX = 26; // X.400 mail mapping.
+ NS_T_GPOS = 27; // Geographical position (withdrawn).
+ NS_T_AAAA = 28; // IPv6 Address.
+ NS_T_LOC = 29; // Location Information.
+ NS_T_NXT = 30; // Next domain (security).
+ NS_T_EID = 31; // Endpoint identifier.
+ NS_T_NIMLOC = 32; // Nimrod Locator.
+ NS_T_SRV = 33; // Server Selection.
+ NS_T_ATMA = 34; // ATM Address
+ NS_T_NAPTR = 35; // Naming Authority PoinTeR
+ NS_T_KX = 36; // Key Exchange
+ NS_T_CERT = 37; // Certification record
+ NS_T_A6 = 38; // IPv6 address (experimental)
+ NS_T_DNAME = 39; // Non-terminal DNAME
+ NS_T_SINK = 40; // Kitchen sink (experimentatl)
+ NS_T_OPT = 41; // EDNS0 option (meta-RR)
+ NS_T_APL = 42; // Address prefix list (RFC 3123)
+ NS_T_DS = 43; // Delegation Signer
+ NS_T_SSHFP = 44; // SSH Fingerprint
+ NS_T_IPSECKEY = 45; // IPSEC Key
+ NS_T_RRSIG = 46; // RRset Signature
+ NS_T_NSEC = 47; // Negative security
+ NS_T_DNSKEY = 48; // DNS Key
+ NS_T_DHCID = 49; // Dynamic host configuratin identifier
+ NS_T_NSEC3 = 50; // Negative security type 3
+ NS_T_NSEC3PARAM = 51; // Negative security type 3 parameters
+ NS_T_HIP = 55; // Host Identity Protocol
+ NS_T_SPF = 99; // Sender Policy Framework
+ NS_T_TKEY = 249; // Transaction key
+ NS_T_TSIG = 250; // Transaction signature.
+ NS_T_IXFR = 251; // Incremental zone transfer.
+ NS_T_AXFR = 252; // Transfer zone of authority.
+ NS_T_MAILB = 253; // Transfer mailbox records.
+ NS_T_MAILA = 254; // Transfer mail agent records.
+ NS_T_ANY = 255; // Wildcard match.
+ NS_T_ZXFR = 256; // BIND-specific, nonstandard.
+ NS_T_DLV = 32769; // DNSSEC look-aside validatation.
+ NS_T_MAX = 65536;
+}
+
+enum IpVersion {
+ IV_UNKNOWN = 0;
+ IV_IPV4 = 1;
+ IV_IPV6 = 2;
+}
+
+enum TransportType {
+ TT_UNKNOWN = 0;
+ TT_UDP = 1;
+ TT_TCP = 2;
+ TT_DOT = 3;
+}
+
+enum PrivateDnsModes {
+ PDM_UNKNOWN = 0;
+ PDM_OFF = 1;
+ PDM_OPPORTUNISTIC = 2;
+ PDM_STRICT = 3;
+}
+
+enum Transport {
+ // Indicates this network uses a Cellular transport.
+ TRANSPORT_DEFAULT = 0; // TRANSPORT_CELLULAR
+ // Indicates this network uses a Wi-Fi transport.
+ TRANSPORT_WIFI = 1;
+ // Indicates this network uses a Bluetooth transport.
+ TRANSPORT_BLUETOOTH = 2;
+ // Indicates this network uses an Ethernet transport.
+ TRANSPORT_ETHERNET = 3;
+ // Indicates this network uses a VPN transport.
+ TRANSPORT_VPN = 4;
+ // Indicates this network uses a Wi-Fi Aware transport.
+ TRANSPORT_WIFI_AWARE = 5;
+ // Indicates this network uses a LoWPAN transport.
+ TRANSPORT_LOWPAN = 6;
+}
+
+enum CacheStatus{
+ // the cache can't handle that kind of queries.
+ // or the answer buffer is too small.
+ CS_UNSUPPORTED = 0;
+ // the cache doesn't know about this query.
+ CS_NOTFOUND = 1;
+ // the cache found the answer.
+ CS_FOUND = 2;
+ // Don't do anything on cache.
+ CS_SKIP = 3;
+}
+
+message DnsQueryEvent {
+ optional android.stats.dnsresolver.NsRcode rcode = 1;
+
+ optional android.stats.dnsresolver.NsType type = 2;
+
+ optional android.stats.dnsresolver.CacheStatus cache_hit = 3;
+
+ optional android.stats.dnsresolver.IpVersion ip_version = 4;
+
+ optional android.stats.dnsresolver.TransportType transport = 5;
+
+ // Number of DNS query retry times
+ optional int32 retry_times = 6;
+
+ // Ordinal number of name server.
+ optional int32 dns_server_count = 7;
+
+ // Used only by TCP and DOT. True for new connections.
+ optional bool connected = 8;
+
+ optional int32 latency_micros = 9;
+}
+
+message DnsQueryEvents {
+ repeated DnsQueryEvent dns_query_event = 1;
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f1e9d65..be49250 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3395,7 +3395,7 @@
<item name="config_inCallNotificationVolume" format="float" type="dimen">.10</item>
<!-- URI for in call notification sound -->
- <string translatable="false" name="config_inCallNotificationSound">/system/media/audio/ui/InCallNotification.ogg</string>
+ <string translatable="false" name="config_inCallNotificationSound">/product/media/audio/ui/InCallNotification.ogg</string>
<!-- The OEM specified sensor type for the lift trigger to launch the camera app. -->
<integer name="config_cameraLiftTriggerSensorType">-1</integer>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 7163769..a92c500 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -70,7 +70,7 @@
<shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" />
<!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
- <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765" />
+ <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075" />
<!-- Chile: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="cl" pattern="\\d{4,5}" free="9963|9240" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 875f2c0..c17f076 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,6 +33,11 @@
<permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.captiveportallogin">
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.cellbroadcastreceiver">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
@@ -204,6 +209,7 @@
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
<permission name="android.permission.MANAGE_SUBSCRIPTION_PLANS"/>
<permission name="android.permission.MANAGE_USB"/>
+ <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
<permission name="android.permission.PACKET_KEEPALIVE_OFFLOAD"/>
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
<permission name="android.permission.READ_PRECISE_PHONE_STATE"/>
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 66a5477..47b7d64 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -120,9 +120,8 @@
std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(unmanaged_handle, path));
// Find the resource table.
- ::ZipString entry_name(kResourcesArsc.c_str());
::ZipEntry entry;
- result = ::FindEntry(loaded_apk->zip_handle_.get(), entry_name, &entry);
+ result = ::FindEntry(loaded_apk->zip_handle_.get(), kResourcesArsc, &entry);
if (result != 0) {
// There is no resources.arsc, so create an empty LoadedArsc and return.
loaded_apk->loaded_arsc_ = LoadedArsc::CreateEmpty();
@@ -160,9 +159,8 @@
std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode mode) const {
CHECK(zip_handle_ != nullptr);
- ::ZipString name(path.c_str());
::ZipEntry entry;
- int32_t result = ::FindEntry(zip_handle_.get(), name, &entry);
+ int32_t result = ::FindEntry(zip_handle_.get(), path, &entry);
if (result != 0) {
return {};
}
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index 6e2ca60c..44614c1 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -98,7 +98,7 @@
data->name = ZipString(entryName);
- const int32_t error = FindEntry(mHandle, data->name, &(data->entry));
+ const int32_t error = FindEntry(mHandle, entryName, &(data->entry));
if (error) {
delete data;
return NULL;
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
index 9e320a2..a81bb6f 100644
--- a/libs/androidfw/tests/TestHelpers.cpp
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -34,9 +34,8 @@
<< "': " << ::ErrorCodeString(result);
}
- ::ZipString name(file.c_str());
::ZipEntry entry;
- result = ::FindEntry(handle, name, &entry);
+ result = ::FindEntry(handle, file.c_str(), &entry);
if (result != 0) {
::CloseArchive(handle);
return AssertionFailure() << "Could not find file '" << file << "' in zip '" << zip_path
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..adfae5b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -81,7 +81,7 @@
// mean and stddev which doesn't make sense for our usage
std::vector<BenchmarkReporter::Run> reports;
BenchmarkReporter::Run report;
- report.run_name = info.name;
+ report.run_name.function_name = info.name;
report.iterations = static_cast<int64_t>(opts.count);
report.real_accumulated_time = durationInS;
report.cpu_accumulated_time = durationInS;
@@ -94,8 +94,8 @@
// in that test case than percentiles.
if (!opts.renderOffscreen) {
for (auto& ri : REPORTS) {
- reports[0].run_name = info.name;
- reports[0].run_name += ri.suffix;
+ reports[0].run_name.function_name = info.name;
+ reports[0].run_name.function_name += ri.suffix;
durationInS = proxy->frameTimePercentile(ri.percentile) / 1000.0;
reports[0].real_accumulated_time = durationInS;
reports[0].cpu_accumulated_time = durationInS;
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
index 4af6274..63a670c 100644
--- a/libs/usb/tests/AccessoryChat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -1 +1,25 @@
subdirs = ["accessorychat"]
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+ name: "AccessoryChat",
+
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+
+}
diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk
deleted file mode 100644
index cfe2da1..0000000
--- a/libs/usb/tests/AccessoryChat/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2011 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)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessoryChat
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index c9c881c..2bc9a2b 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -58,6 +58,7 @@
private final String mId;
private final String mLanguage;
private final CharSequence mDescription;
+ private final boolean mEncrypted;
private final int mAudioChannelCount;
private final int mAudioSampleRate;
private final int mVideoWidth;
@@ -69,13 +70,14 @@
private final Bundle mExtra;
private TvTrackInfo(int type, String id, String language, CharSequence description,
- int audioChannelCount, int audioSampleRate, int videoWidth, int videoHeight,
- float videoFrameRate, float videoPixelAspectRatio, byte videoActiveFormatDescription,
- Bundle extra) {
+ boolean encrypted, int audioChannelCount, int audioSampleRate, int videoWidth,
+ int videoHeight, float videoFrameRate, float videoPixelAspectRatio,
+ byte videoActiveFormatDescription, Bundle extra) {
mType = type;
mId = id;
mLanguage = language;
mDescription = description;
+ mEncrypted = encrypted;
mAudioChannelCount = audioChannelCount;
mAudioSampleRate = audioSampleRate;
mVideoWidth = videoWidth;
@@ -91,6 +93,7 @@
mId = in.readString();
mLanguage = in.readString();
mDescription = in.readString();
+ mEncrypted = in.readInt() != 0;
mAudioChannelCount = in.readInt();
mAudioSampleRate = in.readInt();
mVideoWidth = in.readInt();
@@ -133,6 +136,18 @@
}
/**
+ * Returns {@code true} if the track is encrypted, {@code false} otherwise. If the encryption
+ * status is unknown or could not be determined, the corresponding value will be {@code false}.
+ *
+ * <p>For example: ISO/IEC 13818-1 defines a CA descriptor that can be used to determine the
+ * encryption status of some broadcast streams.
+ */
+
+ public boolean isEncrypted() {
+ return mEncrypted;
+ }
+
+ /**
* Returns the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
*
* @throws IllegalStateException if not called on an audio track
@@ -248,6 +263,7 @@
dest.writeString(mId);
dest.writeString(mLanguage);
dest.writeString(mDescription != null ? mDescription.toString() : null);
+ dest.writeInt(mEncrypted ? 1 : 0);
dest.writeInt(mAudioChannelCount);
dest.writeInt(mAudioSampleRate);
dest.writeInt(mVideoWidth);
@@ -273,6 +289,7 @@
&& mType == obj.mType
&& TextUtils.equals(mLanguage, obj.mLanguage)
&& TextUtils.equals(mDescription, obj.mDescription)
+ && mEncrypted == obj.mEncrypted
&& Objects.equals(mExtra, obj.mExtra)
&& (mType == TYPE_AUDIO
? mAudioChannelCount == obj.mAudioChannelCount
@@ -310,6 +327,7 @@
private final int mType;
private String mLanguage;
private CharSequence mDescription;
+ private boolean mEncrypted;
private int mAudioChannelCount;
private int mAudioSampleRate;
private int mVideoWidth;
@@ -361,6 +379,19 @@
}
/**
+ * Sets the encryption status of the track.
+ *
+ * <p>For example: ISO/IEC 13818-1 defines a CA descriptor that can be used to determine the
+ * encryption status of some broadcast streams.
+ *
+ * @param encrypted The encryption status of the track.
+ */
+ public Builder setEncrypted(boolean encrypted) {
+ mEncrypted = encrypted;
+ return this;
+ }
+
+ /**
* Sets the audio channel count. Valid only for {@link #TYPE_AUDIO} tracks.
*
* @param audioChannelCount The audio channel count.
@@ -490,9 +521,9 @@
* @return The new {@link TvTrackInfo} instance
*/
public TvTrackInfo build() {
- return new TvTrackInfo(mType, mId, mLanguage, mDescription, mAudioChannelCount,
- mAudioSampleRate, mVideoWidth, mVideoHeight, mVideoFrameRate,
- mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
+ return new TvTrackInfo(mType, mId, mLanguage, mDescription, mEncrypted,
+ mAudioChannelCount, mAudioSampleRate, mVideoWidth, mVideoHeight,
+ mVideoFrameRate, mVideoPixelAspectRatio, mVideoActiveFormatDescription, mExtra);
}
}
}
diff --git a/nfc-extras/tests/Android.bp b/nfc-extras/tests/Android.bp
new file mode 100644
index 0000000..fc52006
--- /dev/null
+++ b/nfc-extras/tests/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2011, 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.
+
+android_test {
+ name: "NfcExtrasTests",
+
+ // We only want this apk build for tests.
+
+ libs: [
+ "android.test.runner.stubs",
+ "com.android.nfc_extras.stubs",
+ "android.test.base.stubs",
+ ],
+
+ static_libs: ["junit"],
+
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+
+ sdk_version: "current",
+
+}
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
deleted file mode 100644
index 8bba3ba..0000000
--- a/nfc-extras/tests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2011, 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)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner.stubs \
- com.android.nfc_extras.stubs \
- android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NfcExtrasTests
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 44e0a65..0a03425 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -26,10 +26,12 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<application android:label="@string/app_name"
+ android:icon="@drawable/app_icon"
android:usesCleartextTraffic="true"
android:supportsRtl="true" >
<activity
diff --git a/packages/CaptivePortalLogin/res/drawable/app_icon.xml b/packages/CaptivePortalLogin/res/drawable/app_icon.xml
new file mode 100644
index 0000000..456ca83
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/drawable/app_icon.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2019 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.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background>
+ <color android:color="@*android:color/accent_device_default_light" />
+ </background>
+ <foreground>
+ <inset
+ android:drawable="@drawable/maybe_wifi"
+ android:inset="25%">
+ </inset>
+ </foreground>
+</adaptive-icon>
diff --git a/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml b/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml
new file mode 100644
index 0000000..207aade
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/drawable/maybe_wifi.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="26.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="26.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/>
+</vector>
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index e0bb862..62de2ba 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -56,15 +56,24 @@
srcs: [
"jni/network_stack_utils_jni.cpp"
],
-
+ sdk_version: "current",
shared_libs: [
"liblog",
- "libcutils",
- "libnativehelper",
+ "libnativehelper_compat_libc++",
],
- static_libs: [
- "libpcap",
- ],
+
+ // We cannot use plain "libc++" here to link libc++ dynamically because it results in:
+ // java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found
+ // even if "libc++" is added into jni_libs below. Adding "libc++_shared" into jni_libs doesn't
+ // build because soong complains of:
+ // module NetworkStack missing dependencies: libc++_shared
+ //
+ // So, link libc++ statically. This means that we also need to ensure that all the C++ libraries
+ // we depend on do not dynamically link libc++. This is currently the case, because liblog is
+ // C-only and libnativehelper_compat_libc also uses stl: "c++_static".
+ //
+ // TODO: find a better solution for this in R.
+ stl: "c++_static",
cflags: [
"-Wall",
"-Werror",
@@ -79,7 +88,10 @@
static_libs: [
"NetworkStackBase",
],
- jni_libs: ["libnetworkstackutilsjni"],
+ jni_libs: [
+ "libnativehelper_compat_libc++",
+ "libnetworkstackutilsjni",
+ ],
// Resources already included in NetworkStackBase
resource_dirs: [],
jarjar_rules: "jarjar-rules-shared.txt",
diff --git a/packages/NetworkStack/jni/network_stack_utils_jni.cpp b/packages/NetworkStack/jni/network_stack_utils_jni.cpp
index 5544eaa..f2ba575 100644
--- a/packages/NetworkStack/jni/network_stack_utils_jni.cpp
+++ b/packages/NetworkStack/jni/network_stack_utils_jni.cpp
@@ -31,7 +31,7 @@
#include <string>
#include <nativehelper/JNIHelp.h>
-#include <utils/Log.h>
+#include <android/log.h>
namespace android {
constexpr const char NETWORKSTACKUTILS_PKG_NAME[] = "android/net/util/NetworkStackUtils";
@@ -249,7 +249,7 @@
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
return JNI_ERR;
}
@@ -261,4 +261,4 @@
return JNI_VERSION_1_6;
}
-}; // namespace android
\ No newline at end of file
+}; // namespace android
diff --git a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
index 475f826..41715b2 100644
--- a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
+++ b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java
@@ -19,6 +19,9 @@
import android.annotation.NonNull;
import android.content.Context;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+
/**
* service used to communicate with the ip memory store service in network stack,
* which is running in the same module.
@@ -35,8 +38,7 @@
}
@Override
- @NonNull
- protected IIpMemoryStore getService() {
- return mService;
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ cb.accept(mService);
}
}
diff --git a/packages/NetworkStack/src/android/net/apf/ApfFilter.java b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
index 663e2f1..359c859 100644
--- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java
+++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
@@ -39,6 +39,7 @@
import android.content.IntentFilter;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;
@@ -1691,13 +1692,13 @@
}
/**
- * Add keepalive ack packet filter.
+ * Add TCP keepalive ack packet filter.
* This will add a filter to drop acks to the keepalive packet passed as an argument.
*
* @param slot The index used to access the filter.
* @param sentKeepalivePacket The attributes of the sent keepalive packet.
*/
- public synchronized void addKeepalivePacketFilter(final int slot,
+ public synchronized void addTcpKeepalivePacketFilter(final int slot,
final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
log("Adding keepalive ack(" + slot + ")");
if (null != mKeepaliveAcks.get(slot)) {
@@ -1711,6 +1712,18 @@
}
/**
+ * Add NATT keepalive packet filter.
+ * This will add a filter to drop NATT keepalive packet which is passed as an argument.
+ *
+ * @param slot The index used to access the filter.
+ * @param sentKeepalivePacket The attributes of the sent keepalive packet.
+ */
+ public synchronized void addNattKeepalivePacketFilter(final int slot,
+ final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
+ Log.e(TAG, "APF add NATT keepalive filter is not implemented");
+ }
+
+ /**
* Remove keepalive packet filter.
*
* @param slot The index used to access the filter.
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
index d7ff98b1..a15d423 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
@@ -195,6 +195,18 @@
public static final String VENDOR_INFO_ANDROID_METERED = "ANDROID_METERED";
/**
+ * DHCP Optional Type: Option overload option
+ */
+ protected static final byte DHCP_OPTION_OVERLOAD = 52;
+
+ /**
+ * Possible values of the option overload option.
+ */
+ private static final byte OPTION_OVERLOAD_FILE = 1;
+ private static final byte OPTION_OVERLOAD_SNAME = 2;
+ private static final byte OPTION_OVERLOAD_BOTH = 3;
+
+ /**
* DHCP Optional Type: DHCP Requested IP Address
*/
protected static final byte DHCP_REQUESTED_IP = 50;
@@ -309,6 +321,11 @@
protected final byte[] mClientMac;
/**
+ * The server host name from server.
+ */
+ protected String mServerHostName;
+
+ /**
* Asks the packet object to create a ByteBuffer serialization of
* the packet for transmission.
*/
@@ -848,6 +865,8 @@
Inet4Address ipDst = null;
Inet4Address bcAddr = null;
Inet4Address requestedIp = null;
+ String serverHostName;
+ byte optionOverload = 0;
// The following are all unsigned integers. Internally we store them as signed integers of
// the same length because that way we're guaranteed that they can't be out of the range of
@@ -989,9 +1008,9 @@
packet.get(clientMac);
// skip over address padding (16 octets allocated)
- packet.position(packet.position() + (16 - addrLen)
- + 64 // skip server host name (64 chars)
- + 128); // skip boot file name (128 chars)
+ packet.position(packet.position() + (16 - addrLen));
+ serverHostName = readAsciiString(packet, 64, false);
+ packet.position(packet.position() + 128);
// Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
if (packet.remaining() < 4) {
@@ -1102,6 +1121,11 @@
// Embedded nulls are safe as this does not get passed to netd.
vendorInfo = readAsciiString(packet, optionLen, true);
break;
+ case DHCP_OPTION_OVERLOAD:
+ expectedLen = 1;
+ optionOverload = packet.get();
+ optionOverload &= OPTION_OVERLOAD_BOTH;
+ break;
default:
// ignore any other parameters
for (int i = 0; i < optionLen; i++) {
@@ -1192,6 +1216,11 @@
newPacket.mT2 = T2;
newPacket.mVendorId = vendorId;
newPacket.mVendorInfo = vendorInfo;
+ if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
+ newPacket.mServerHostName = serverHostName;
+ } else {
+ newPacket.mServerHostName = "";
+ }
return newPacket;
}
@@ -1251,6 +1280,7 @@
results.vendorInfo = mVendorInfo;
results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
+ results.serverHostName = mServerHostName;
return results;
}
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 96e09fa..dc74c04 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -29,6 +29,7 @@
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.NetworkStackIpMemoryStore;
import android.net.ProvisioningConfigurationParcelable;
import android.net.ProxyInfo;
@@ -371,6 +372,10 @@
private boolean mMulticastFiltering;
private long mStartTimeMillis;
+ /* This must match the definition in KeepaliveTracker.KeepaliveInfo */
+ private static final int TYPE_NATT = 1;
+ private static final int TYPE_TCP = 2;
+
/**
* Reading the snapshot is an asynchronous operation initiated by invoking
* Callback.startReadPacketFilter() and completed when the WiFi Service responds with an
@@ -553,6 +558,11 @@
IpClient.this.addKeepalivePacketFilter(slot, pkt);
}
@Override
+ public void addNattKeepalivePacketFilter(int slot, NattKeepalivePacketDataParcelable pkt) {
+ checkNetworkStackCallingPermission();
+ IpClient.this.addNattKeepalivePacketFilter(slot, pkt);
+ }
+ @Override
public void removeKeepalivePacketFilter(int slot) {
checkNetworkStackCallingPermission();
IpClient.this.removeKeepalivePacketFilter(slot);
@@ -691,11 +701,20 @@
}
/**
- * Called by WifiStateMachine to add keepalive packet filter before setting up
+ * Called by WifiStateMachine to add TCP keepalive packet filter before setting up
* keepalive offload.
*/
public void addKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketDataParcelable pkt) {
- sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */, pkt);
+ sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_TCP, pkt);
+ }
+
+ /**
+ * Called by WifiStateMachine to add NATT keepalive packet filter before setting up
+ * keepalive offload.
+ */
+ public void addNattKeepalivePacketFilter(int slot,
+ @NonNull NattKeepalivePacketDataParcelable pkt) {
+ sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_NATT, pkt);
}
/**
@@ -1607,9 +1626,16 @@
case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: {
final int slot = msg.arg1;
+ final int type = msg.arg2;
+
if (mApfFilter != null) {
- mApfFilter.addKeepalivePacketFilter(slot,
- (TcpKeepalivePacketDataParcelable) msg.obj);
+ if (type == TYPE_NATT) {
+ mApfFilter.addNattKeepalivePacketFilter(slot,
+ (NattKeepalivePacketDataParcelable) msg.obj);
+ } else {
+ mApfFilter.addTcpKeepalivePacketFilter(slot,
+ (TcpKeepalivePacketDataParcelable) msg.obj);
+ }
}
break;
}
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index fb03c54..abfed3e 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -62,6 +62,49 @@
*/
public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
+ /**
+ * The URL used for HTTPS captive portal detection upon a new connection.
+ * A 204 response code from the server is used for validation.
+ */
+ public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
+
+ /**
+ * The URL used for HTTP captive portal detection upon a new connection.
+ * A 204 response code from the server is used for validation.
+ */
+ public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
+
+ /**
+ * The URL used for fallback HTTP captive portal detection when previous HTTP
+ * and HTTPS captive portal detection attemps did not return a conclusive answer.
+ */
+ public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
+
+ /**
+ * What to do when connecting a network that presents a captive portal.
+ * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
+ *
+ * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
+ */
+ public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
+
+ /**
+ * Don't attempt to detect captive portals.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
+
+ /**
+ * When detecting a captive portal, display a notification that
+ * prompts the user to sign in.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
+
+ /**
+ * When detecting a captive portal, immediately disconnect from the
+ * network and do not reconnect to that network in the future.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
+
static {
System.loadLibrary("networkstackutilsjni");
}
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 50eb5d4..d6355bc 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -44,6 +44,12 @@
import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS;
import static android.net.util.DataStallUtils.DEFAULT_DNS_LOG_SIZE;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTPS_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTP_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_IGNORE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;
@@ -144,9 +150,6 @@
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
- // Enough for 3 DNS queries 5 seconds apart.
- // TODO: get this from resources and DeviceConfig instead.
- private static final int DNS_TIMEOUT_MS = 12500;
enum EvaluationResult {
VALIDATED(true),
@@ -276,8 +279,8 @@
private final Context mContext;
private final INetworkMonitorCallbacks mCallback;
+ private final Network mCleartextDnsNetwork;
private final Network mNetwork;
- private final Network mNonPrivateDnsBypassNetwork;
private final TelephonyManager mTelephonyManager;
private final WifiManager mWifiManager;
private final ConnectivityManager mCm;
@@ -367,8 +370,8 @@
mCallback = cb;
mDependencies = deps;
mDetectionStatsUtils = detectionStatsUtils;
- mNonPrivateDnsBypassNetwork = network;
- mNetwork = deps.getPrivateDnsBypassNetwork(network);
+ mNetwork = network;
+ mCleartextDnsNetwork = deps.getPrivateDnsBypassNetwork(network);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -493,7 +496,7 @@
@Override
protected void log(String s) {
- if (DBG) Log.d(TAG + "/" + mNetwork.toString(), s);
+ if (DBG) Log.d(TAG + "/" + mCleartextDnsNetwork.toString(), s);
}
private void validationLog(int probeType, Object url, String msg) {
@@ -766,7 +769,7 @@
case CMD_LAUNCH_CAPTIVE_PORTAL_APP:
final Bundle appExtras = new Bundle();
// OneAddressPerFamilyNetwork is not parcelable across processes.
- final Network network = new Network(mNetwork);
+ final Network network = new Network(mCleartextDnsNetwork);
appExtras.putParcelable(ConnectivityManager.EXTRA_NETWORK, network);
final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
appExtras.putString(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
@@ -878,7 +881,7 @@
CustomIntentReceiver(String action, int token, int what) {
mToken = token;
mWhat = what;
- mAction = action + "_" + mNetwork.getNetworkHandle() + "_" + token;
+ mAction = action + "_" + mCleartextDnsNetwork.getNetworkHandle() + "_" + token;
mContext.registerReceiver(this, new IntentFilter(mAction));
}
public PendingIntent getPendingIntent() {
@@ -991,7 +994,8 @@
private void resolveStrictModeHostname() {
try {
// Do a blocking DNS resolution using the network-assigned nameservers.
- final InetAddress[] ips = mNetwork.getAllByName(mPrivateDnsProviderHostname);
+ final InetAddress[] ips = mCleartextDnsNetwork.getAllByName(
+ mPrivateDnsProviderHostname);
mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
validationLog("Strict mode hostname resolved: " + mPrivateDnsConfig);
} catch (UnknownHostException uhe) {
@@ -1030,7 +1034,7 @@
+ oneTimeHostnameSuffix;
final Stopwatch watch = new Stopwatch().start();
try {
- final InetAddress[] ips = mNonPrivateDnsBypassNetwork.getAllByName(host);
+ final InetAddress[] ips = mNetwork.getAllByName(host);
final long time = watch.stop();
final String strIps = Arrays.toString(ips);
final boolean success = (ips != null && ips.length > 0);
@@ -1178,10 +1182,10 @@
}
private boolean getIsCaptivePortalCheckEnabled() {
- String symbol = Settings.Global.CAPTIVE_PORTAL_MODE;
- int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT;
+ String symbol = CAPTIVE_PORTAL_MODE;
+ int defaultValue = CAPTIVE_PORTAL_MODE_PROMPT;
int mode = mDependencies.getSetting(mContext, symbol, defaultValue);
- return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE;
+ return mode != CAPTIVE_PORTAL_MODE_IGNORE;
}
private boolean getUseHttpsValidation() {
@@ -1191,8 +1195,7 @@
private String getCaptivePortalServerHttpsUrl() {
return getSettingFromResource(mContext, R.string.config_captive_portal_https_url,
- R.string.default_captive_portal_https_url,
- Settings.Global.CAPTIVE_PORTAL_HTTPS_URL);
+ R.string.default_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL);
}
private int getDnsProbeTimeout() {
@@ -1231,8 +1234,7 @@
*/
public String getCaptivePortalServerHttpUrl() {
return getSettingFromResource(mContext, R.string.config_captive_portal_http_url,
- R.string.default_captive_portal_http_url,
- Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+ R.string.default_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL);
}
private int getConsecutiveDnsTimeoutThreshold() {
@@ -1261,8 +1263,8 @@
private URL[] makeCaptivePortalFallbackUrls() {
try {
- final String firstUrl = mDependencies.getSetting(mContext,
- Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, null);
+ final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL,
+ null);
final URL[] settingProviderUrls;
if (!TextUtils.isEmpty(firstUrl)) {
@@ -1505,7 +1507,7 @@
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
TrafficStatsConstants.TAG_SYSTEM_PROBE);
- mDependencies.getDnsResolver().query(mNetwork, host, DnsResolver.FLAG_EMPTY,
+ mDependencies.getDnsResolver().query(mCleartextDnsNetwork, host, DnsResolver.FLAG_EMPTY,
r -> r.run() /* executor */, null /* cancellationSignal */, callback);
TrafficStats.setThreadStatsTag(oldTag);
@@ -1564,7 +1566,7 @@
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
TrafficStatsConstants.TAG_SYSTEM_PROBE);
try {
- urlConnection = (HttpURLConnection) mNetwork.openConnection(url);
+ urlConnection = (HttpURLConnection) mCleartextDnsNetwork.openConnection(url);
urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
@@ -1813,7 +1815,7 @@
private void logNetworkEvent(int evtype) {
int[] transports = mNetworkCapabilities.getTransportTypes();
- mMetricsLog.log(mNetwork, transports, new NetworkEvent(evtype));
+ mMetricsLog.log(mCleartextDnsNetwork, transports, new NetworkEvent(evtype));
}
private int networkEventType(ValidationStage s, EvaluationResult r) {
@@ -1835,7 +1837,7 @@
private void maybeLogEvaluationResult(int evtype) {
if (mEvaluationTimer.isRunning()) {
int[] transports = mNetworkCapabilities.getTransportTypes();
- mMetricsLog.log(mNetwork, transports,
+ mMetricsLog.log(mCleartextDnsNetwork, transports,
new NetworkEvent(evtype, mEvaluationTimer.stop()));
mEvaluationTimer.reset();
}
@@ -1849,7 +1851,7 @@
.setReturnCode(probeResult)
.setDurationMs(durationMs)
.build();
- mMetricsLog.log(mNetwork, transports, ev);
+ mMetricsLog.log(mCleartextDnsNetwork, transports, ev);
}
@VisibleForTesting
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index fe3c1e8..039f6bf 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -56,6 +56,7 @@
"liblog",
"liblzma",
"libnativehelper",
+ "libnativehelper_compat_libc++",
"libnetworkstacktestsjni",
"libnetworkstackutilsjni",
"libpackagelistparser",
@@ -99,5 +100,4 @@
"libapf",
"libpcap",
],
-
}
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index a0e508f..93ab3be 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -1553,7 +1553,7 @@
parcel.seq = seqNum;
parcel.ack = ackNum;
- apfFilter.addKeepalivePacketFilter(slot1, parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
@@ -1592,7 +1592,7 @@
ipv6Parcel.seq = seqNum;
ipv6Parcel.ack = ackNum;
- apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv6 keepalive ack packet is dropped
@@ -1614,8 +1614,8 @@
apfFilter.removeKeepalivePacketFilter(slot1);
// Verify multiple filters
- apfFilter.addKeepalivePacketFilter(slot1, parcel);
- apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
index 4d98403..a30d3e4 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
@@ -302,8 +302,9 @@
}
private void assertDhcpResults(String ipAddress, String gateway, String dnsServersString,
- String domains, String serverAddress, String vendorInfo, int leaseDuration,
- boolean hasMeteredHint, int mtu, DhcpResults dhcpResults) throws Exception {
+ String domains, String serverAddress, String serverHostName, String vendorInfo,
+ int leaseDuration, boolean hasMeteredHint, int mtu, DhcpResults dhcpResults)
+ throws Exception {
assertEquals(new LinkAddress(ipAddress), dhcpResults.ipAddress);
assertEquals(v4Address(gateway), dhcpResults.gateway);
@@ -316,6 +317,7 @@
assertEquals(domains, dhcpResults.domains);
assertEquals(v4Address(serverAddress), dhcpResults.serverAddress);
+ assertEquals(serverHostName, dhcpResults.serverHostName);
assertEquals(vendorInfo, dhcpResults.vendorInfo);
assertEquals(leaseDuration, dhcpResults.leaseDuration);
assertEquals(hasMeteredHint, dhcpResults.hasMeteredHint());
@@ -327,6 +329,7 @@
// TODO: Turn all of these into golden files. This will probably require using
// androidx.test.InstrumentationRegistry for obtaining a Context object
// to read such golden files, along with an appropriate Android.mk.
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"451001480000000080118849c0a89003c0a89ff7" +
@@ -347,16 +350,18 @@
// Options
"638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
"3a0400000e103b040000189cff00000000000000000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
- null, "192.168.144.3", null, 7200, false, 0, dhcpResults);
+ null, "192.168.144.3", "", null, 7200, false, 0, dhcpResults);
}
@Test
public void testOffer2() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -366,9 +371,9 @@
"02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
// MAC address.
"30766ff2a90c00000000000000000000" +
- // Server name.
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000" +
+ // Server name ("dhcp.android.com" plus invalid "AAAA" after null terminator).
+ "646863702e616e64726f69642e636f6d00000000000000000000000000000000" +
+ "0000000000004141414100000000000000000000000000000000000000000000" +
// File.
"0000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000000000000000000000000000000000000" +
@@ -377,13 +382,15 @@
// Options
"638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
"1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+ // CHECKSTYLE:ON Generated code
assertEquals(337, packet.limit());
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.43.247/24", "192.168.43.1", "192.168.43.1",
- null, "192.168.43.1", "ANDROID_METERED", 3600, true, 0, dhcpResults);
+ null, "192.168.43.1", "dhcp.android.com", "ANDROID_METERED", 3600, true, 0,
+ dhcpResults);
assertTrue(dhcpResults.hasMeteredHint());
}
@@ -588,11 +595,12 @@
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
- null, "192.168.144.3", null, 7200, false, expectedMtu, dhcpResults);
+ null, "192.168.144.3", "", null, 7200, false, expectedMtu, dhcpResults);
}
@Test
public void testMtu() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"451001480000000080118849c0a89003c0a89ff7" +
@@ -613,6 +621,7 @@
// Options
"638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
"3a0400000e103b040000189cff00000000"));
+ // CHECKSTYLE:ON Generated code
checkMtu(packet, 0, null);
checkMtu(packet, 0, mtuBytes(1501));
@@ -629,6 +638,7 @@
@Test
public void testBadHwaddrLength() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -649,6 +659,7 @@
// Options
"638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
"1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+ // CHECKSTYLE:ON Generated code
String expectedClientMac = "30766FF2A90C";
final int hwAddrLenOffset = 20 + 8 + 2;
@@ -705,6 +716,7 @@
// store any information in the overloaded fields).
//
// For now, we just check that it parses correctly.
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"b4cef6000000e80462236e300800" +
@@ -727,16 +739,18 @@
// Options
"638253633501023604010101010104ffff000033040000a8c03401030304ac1101010604ac110101" +
"0000000000000000000000000000000000000000000000ff000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("172.17.152.118/16", "172.17.1.1", "172.17.1.1",
- null, "1.1.1.1", null, 43200, false, 0, dhcpResults);
+ null, "1.1.1.1", "", null, 43200, false, 0, dhcpResults);
}
@Test
public void testBug2111() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"4500014c00000000ff119beac3eaf3880a3f5d04" +
@@ -757,16 +771,18 @@
// Options.
"638253633501023604c00002fe33040000bfc60104fffff00003040a3f50010608c0000201c0000202" +
"0f0f646f6d61696e3132332e636f2e756b0000000000ff00000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket);
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.63.93.4/20", "10.63.80.1", "192.0.2.1,192.0.2.2",
- "domain123.co.uk", "192.0.2.254", null, 49094, false, 0, dhcpResults);
+ "domain123.co.uk", "192.0.2.254", "", null, 49094, false, 0, dhcpResults);
}
@Test
public void testBug2136() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"bcf5ac000000d0c7890000000800" +
@@ -789,17 +805,19 @@
// Options.
"6382536335010236040a20ff80330400001c200104fffff00003040a20900106089458413494584135" +
"0f0b6c616e63732e61632e756b000000000000000000ff00000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
assertEquals("BCF5AC000000", HexDump.toHexString(offerPacket.getClientMac()));
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.32.158.205/20", "10.32.144.1", "148.88.65.52,148.88.65.53",
- "lancs.ac.uk", "10.32.255.128", null, 7200, false, 0, dhcpResults);
+ "lancs.ac.uk", "10.32.255.128", "", null, 7200, false, 0, dhcpResults);
}
@Test
public void testUdpServerAnySourcePort() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"9cd917000000001c2e0000000800" +
@@ -823,6 +841,7 @@
// Options.
"6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
"d18180060f0777766d2e6564751c040a0fffffff000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -830,11 +849,12 @@
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.15.122.242/16", "10.15.200.23",
"209.129.128.3,209.129.148.3,209.129.128.6",
- "wvm.edu", "10.1.105.252", null, 86400, false, 0, dhcpResults);
+ "wvm.edu", "10.1.105.252", "", null, 86400, false, 0, dhcpResults);
}
@Test
public void testUdpInvalidDstPort() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"9cd917000000001c2e0000000800" +
@@ -858,6 +878,7 @@
// Options.
"6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
"d18180060f0777766d2e6564751c040a0fffffff000000"));
+ // CHECKSTYLE:ON Generated code
try {
DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
@@ -867,6 +888,7 @@
@Test
public void testMultipleRouters() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"fc3d93000000" + "081735000000" + "0800" +
@@ -889,13 +911,14 @@
// Options.
"638253633501023604c0abbd023304000070803a04000038403b04000062700104ffffff00" +
"0308c0a8bd01ffffff0006080808080808080404ff000000000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
assertEquals("FC3D93000000", HexDump.toHexString(offerPacket.getClientMac()));
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.189.49/24", "192.168.189.1", "8.8.8.8,8.8.4.4",
- null, "192.171.189.2", null, 28800, false, 0, dhcpResults);
+ null, "192.171.189.2", "", null, 28800, false, 0, dhcpResults);
}
@Test
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 0dc1cbf..6f5c27e 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -42,10 +42,10 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -66,6 +66,7 @@
import android.net.NetworkInfo;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.metrics.IpConnectivityLog;
+import android.net.shared.PrivateDnsConfig;
import android.net.util.SharedLog;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -73,6 +74,7 @@
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
@@ -131,7 +133,8 @@
private @Mock Random mRandom;
private @Mock NetworkMonitor.Dependencies mDependencies;
private @Mock INetworkMonitorCallbacks mCallbacks;
- private @Spy Network mNetwork = new Network(TEST_NETID);
+ private @Spy Network mCleartextDnsNetwork = new Network(TEST_NETID);
+ private @Mock Network mNetwork;
private @Mock DataStallStatsUtils mDataStallStatsUtils;
private @Mock WifiInfo mWifiInfo;
private @Captor ArgumentCaptor<String> mNetworkTestedRedirectUrlCaptor;
@@ -166,35 +169,97 @@
private static final NetworkCapabilities NO_INTERNET_CAPABILITIES = new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- private void setDnsAnswers(String[] answers) throws UnknownHostException {
- if (answers == null) {
- doThrow(new UnknownHostException()).when(mNetwork).getAllByName(any());
- doNothing().when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());
- return;
+ /**
+ * Fakes DNS responses.
+ *
+ * Allows test methods to configure the IP addresses that will be resolved by
+ * Network#getAllByName and by DnsResolver#query.
+ */
+ class FakeDns {
+ private final ArrayMap<String, List<InetAddress>> mAnswers = new ArrayMap<>();
+ private boolean mNonBypassPrivateDnsWorking = true;
+
+ /** Whether DNS queries on mNonBypassPrivateDnsWorking should succeed. */
+ private void setNonBypassPrivateDnsWorking(boolean working) {
+ mNonBypassPrivateDnsWorking = working;
}
- List<InetAddress> answerList = new ArrayList<>();
- for (String answer : answers) {
- answerList.add(InetAddresses.parseNumericAddress(answer));
+ /** Clears all DNS entries. */
+ private synchronized void clearAll() {
+ mAnswers.clear();
}
- InetAddress[] answerArray = answerList.toArray(new InetAddress[0]);
- doReturn(answerArray).when(mNetwork).getAllByName(any());
+ /** Returns the answer for a given name on the given mock network. */
+ private synchronized List<InetAddress> getAnswer(Object mock, String hostname) {
+ if (mock == mNetwork && !mNonBypassPrivateDnsWorking) {
+ return null;
+ }
+ if (mAnswers.containsKey(hostname)) {
+ return mAnswers.get(hostname);
+ }
+ return mAnswers.get("*");
+ }
- doAnswer((invocation) -> {
- Executor executor = (Executor) invocation.getArgument(3);
- DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(5);
- new Handler(Looper.getMainLooper()).post(() -> {
- executor.execute(() -> callback.onAnswer(answerList, 0));
- });
- return null;
- }).when(mDnsResolver).query(eq(mNetwork), any(), anyInt(), any(), any(), any());
+ /** Sets the answer for a given name. */
+ private synchronized void setAnswer(String hostname, String[] answer)
+ throws UnknownHostException {
+ if (answer == null) {
+ mAnswers.remove(hostname);
+ } else {
+ List<InetAddress> answerList = new ArrayList<>();
+ for (String addr : answer) {
+ answerList.add(InetAddresses.parseNumericAddress(addr));
+ }
+ mAnswers.put(hostname, answerList);
+ }
+ }
+
+ /** Simulates a getAllByName call for the specified name on the specified mock network. */
+ private InetAddress[] getAllByName(Object mock, String hostname)
+ throws UnknownHostException {
+ List<InetAddress> answer = getAnswer(mock, hostname);
+ if (answer == null || answer.size() == 0) {
+ throw new UnknownHostException(hostname);
+ }
+ return answer.toArray(new InetAddress[0]);
+ }
+
+ /** Starts mocking DNS queries. */
+ private void startMocking() throws UnknownHostException {
+ // Queries on mCleartextDnsNetwork using getAllByName.
+ doAnswer(invocation -> {
+ return getAllByName(invocation.getMock(), invocation.getArgument(0));
+ }).when(mCleartextDnsNetwork).getAllByName(any());
+
+ // Queries on mNetwork using getAllByName.
+ doAnswer(invocation -> {
+ return getAllByName(invocation.getMock(), invocation.getArgument(0));
+ }).when(mNetwork).getAllByName(any());
+
+ // Queries on mCleartextDnsNetwork using DnsResolver#query.
+ doAnswer(invocation -> {
+ String hostname = (String) invocation.getArgument(1);
+ Executor executor = (Executor) invocation.getArgument(3);
+ DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(5);
+
+ List<InetAddress> answer = getAnswer(invocation.getMock(), hostname);
+ if (answer != null && answer.size() > 0) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ executor.execute(() -> callback.onAnswer(answer, 0));
+ });
+ }
+ // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE.
+ return null;
+ }).when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());
+ }
}
+ private FakeDns mFakeDns;
+
@Before
public void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
- when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mNetwork);
+ when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mCleartextDnsNetwork);
when(mDependencies.getDnsResolver()).thenReturn(mDnsResolver);
when(mDependencies.getRandom()).thenReturn(mRandom);
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
@@ -206,7 +271,7 @@
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL), any()))
.thenReturn(TEST_HTTPS_URL);
- doReturn(mNetwork).when(mNetwork).getPrivateDnsBypassingCopy();
+ doReturn(mCleartextDnsNetwork).when(mNetwork).getPrivateDnsBypassingCopy();
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mCm);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
@@ -222,6 +287,9 @@
setFallbackSpecs(null); // Test with no fallback spec by default
when(mRandom.nextInt()).thenReturn(0);
+ when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
+ .thenReturn(500);
+
doAnswer((invocation) -> {
URL url = invocation.getArgument(0);
switch(url.toString()) {
@@ -237,11 +305,13 @@
fail("URL not mocked: " + url.toString());
return null;
}
- }).when(mNetwork).openConnection(any());
+ }).when(mCleartextDnsNetwork).openConnection(any());
when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
- setDnsAnswers(new String[]{"2001:db8::1", "192.0.2.2"});
+ mFakeDns = new FakeDns();
+ mFakeDns.startMocking();
+ mFakeDns.setAnswer("*", new String[]{"2001:db8::1", "192.0.2.2"});
when(mContext.registerReceiver(any(BroadcastReceiver.class), any())).then((invocation) -> {
mRegisteredReceivers.add(invocation.getArgument(0));
@@ -264,6 +334,7 @@
@After
public void tearDown() {
+ mFakeDns.clearAll();
assertTrue(mCreatedNetworkMonitors.size() > 0);
// Make a local copy of mCreatedNetworkMonitors because during the iteration below,
// WrappedNetworkMonitor#onQuitting will delete elements from it on the handler threads.
@@ -284,8 +355,8 @@
private final ConditionVariable mQuitCv = new ConditionVariable(false);
WrappedNetworkMonitor() {
- super(mContext, mCallbacks, mNetwork, mLogger, mValidationLogger, mDependencies,
- mDataStallStatsUtils);
+ super(mContext, mCallbacks, mNetwork, mLogger, mValidationLogger,
+ mDependencies, mDataStallStatsUtils);
}
@Override
@@ -314,23 +385,22 @@
}
}
- private WrappedNetworkMonitor makeMonitor() {
+ private WrappedNetworkMonitor makeMonitor(NetworkCapabilities nc) {
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor();
nm.start();
+ setNetworkCapabilities(nm, nc);
waitForIdle(nm.getHandler());
mCreatedNetworkMonitors.add(nm);
return nm;
}
private WrappedNetworkMonitor makeMeteredNetworkMonitor() {
- final WrappedNetworkMonitor nm = makeMonitor();
- setNetworkCapabilities(nm, METERED_CAPABILITIES);
+ final WrappedNetworkMonitor nm = makeMonitor(METERED_CAPABILITIES);
return nm;
}
private WrappedNetworkMonitor makeNotMeteredNetworkMonitor() {
- final WrappedNetworkMonitor nm = makeMonitor();
- setNetworkCapabilities(nm, NOT_METERED_CAPABILITIES);
+ final WrappedNetworkMonitor nm = makeMonitor(NOT_METERED_CAPABILITIES);
return nm;
}
@@ -595,7 +665,7 @@
@Test
public void testNoInternetCapabilityValidated() throws Exception {
runNetworkTest(NO_INTERNET_CAPABILITIES, NETWORK_TEST_RESULT_VALID);
- verify(mNetwork, never()).openConnection(any());
+ verify(mCleartextDnsNetwork, never()).openConnection(any());
}
@Test
@@ -603,7 +673,7 @@
setSslException(mHttpsConnection);
setPortal302(mHttpConnection);
- final NetworkMonitor nm = makeMonitor();
+ final NetworkMonitor nm = makeMonitor(METERED_CAPABILITIES);
nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, METERED_CAPABILITIES);
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
@@ -638,6 +708,63 @@
}
@Test
+ public void testPrivateDnsSuccess() throws Exception {
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+ mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::53"});
+
+ WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+ }
+
+ @Test
+ public void testPrivateDnsResolutionRetryUpdate() throws Exception {
+ // Set a private DNS hostname that doesn't resolve and expect validation to fail.
+ mFakeDns.setAnswer("dns.google", new String[0]);
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+
+ WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Fix DNS and retry, expect validation to succeed.
+ reset(mCallbacks);
+ mFakeDns.setAnswer("dns.google", new String[]{"2001:db8::1"});
+
+ wnm.forceReevaluation(Process.myUid());
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+
+ // Change configuration to an invalid DNS name, expect validation to fail.
+ reset(mCallbacks);
+ mFakeDns.setAnswer("dns.bad", new String[0]);
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.bad", new InetAddress[0]));
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Change configuration back to working again, but make private DNS not work.
+ // Expect validation to fail.
+ reset(mCallbacks);
+ mFakeDns.setNonBypassPrivateDnsWorking(false);
+ wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_INVALID), eq(null));
+
+ // Make private DNS work again. Expect validation to succeed.
+ reset(mCallbacks);
+ mFakeDns.setNonBypassPrivateDnsWorking(true);
+ wnm.forceReevaluation(Process.myUid());
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .notifyNetworkTested(eq(NETWORK_TEST_RESULT_VALID), eq(null));
+ }
+
+ @Test
public void testDataStall_StallSuspectedAndSendMetrics() throws IOException {
WrappedNetworkMonitor wrappedMonitor = makeNotMeteredNetworkMonitor();
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
@@ -728,25 +855,27 @@
WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
final int shortTimeoutMs = 200;
+ // Clear the wildcard DNS response created in setUp.
+ mFakeDns.setAnswer("*", null);
+
String[] expected = new String[]{"2001:db8::"};
- setDnsAnswers(expected);
+ mFakeDns.setAnswer("www.google.com", expected);
InetAddress[] actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
assertIpAddressArrayEquals(expected, actual);
expected = new String[]{"2001:db8::", "192.0.2.1"};
- setDnsAnswers(expected);
- actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+ mFakeDns.setAnswer("www.googleapis.com", expected);
+ actual = wnm.sendDnsProbeWithTimeout("www.googleapis.com", shortTimeoutMs);
assertIpAddressArrayEquals(expected, actual);
- expected = new String[0];
- setDnsAnswers(expected);
+ mFakeDns.setAnswer("www.google.com", new String[0]);
try {
wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
fail("No DNS results, expected UnknownHostException");
} catch (UnknownHostException e) {
}
- setDnsAnswers(null);
+ mFakeDns.setAnswer("www.google.com", null);
try {
wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
fail("DNS query timed out, expected UnknownHostException");
@@ -841,7 +970,7 @@
}
private NetworkMonitor runNetworkTest(NetworkCapabilities nc, int testResult) {
- final NetworkMonitor monitor = makeMonitor();
+ final NetworkMonitor monitor = makeMonitor(nc);
monitor.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
try {
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index e1a602b..9536bae 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -68,19 +68,19 @@
<!-- user interface sound effects -->
<integer name="def_power_sounds_enabled">1</integer>
- <string name="def_low_battery_sound" translatable="false">/system/media/audio/ui/LowBattery.ogg</string>
+ <string name="def_low_battery_sound" translatable="false">/product/media/audio/ui/LowBattery.ogg</string>
<integer name="def_dock_sounds_enabled">0</integer>
<integer name="def_dock_sounds_enabled_when_accessibility">0</integer>
- <string name="def_desk_dock_sound" translatable="false">/system/media/audio/ui/Dock.ogg</string>
- <string name="def_desk_undock_sound" translatable="false">/system/media/audio/ui/Undock.ogg</string>
- <string name="def_car_dock_sound" translatable="false">/system/media/audio/ui/Dock.ogg</string>
- <string name="def_car_undock_sound" translatable="false">/system/media/audio/ui/Undock.ogg</string>
+ <string name="def_desk_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
+ <string name="def_desk_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
+ <string name="def_car_dock_sound" translatable="false">/product/media/audio/ui/Dock.ogg</string>
+ <string name="def_car_undock_sound" translatable="false">/product/media/audio/ui/Undock.ogg</string>
<integer name="def_lockscreen_sounds_enabled">1</integer>
- <string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string>
- <string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string>
- <string name="def_trusted_sound" translatable="false">/system/media/audio/ui/Trusted.ogg</string>
- <string name="def_wireless_charging_started_sound" translatable="false">/system/media/audio/ui/WirelessChargingStarted.ogg</string>
- <string name="def_charging_started_sound" translatable="false">/system/media/audio/ui/ChargingStarted.ogg</string>
+ <string name="def_lock_sound" translatable="false">/product/media/audio/ui/Lock.ogg</string>
+ <string name="def_unlock_sound" translatable="false">/product/media/audio/ui/Unlock.ogg</string>
+ <string name="def_trusted_sound" translatable="false">/product/media/audio/ui/Trusted.ogg</string>
+ <string name="def_wireless_charging_started_sound" translatable="false">/product/media/audio/ui/WirelessChargingStarted.ogg</string>
+ <string name="def_charging_started_sound" translatable="false">/product/media/audio/ui/ChargingStarted.ogg</string>
<!-- sound trigger detection service default values -->
<integer name="def_max_sound_trigger_detection_service_ops_per_day" translatable="false">1000</integer>
diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp
new file mode 100644
index 0000000..aaaf044
--- /dev/null
+++ b/packages/Shell/Android.bp
@@ -0,0 +1,14 @@
+android_app {
+ name: "Shell",
+ srcs: ["src/**/*.java",":dumpstate_aidl"],
+ aidl: {
+ include_dirs: ["frameworks/native/cmds/dumpstate/binder"],
+ },
+ static_libs: ["androidx.legacy_legacy-support-v4"],
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+ jacoco: {
+ include_filter: ["com.android.shell.*"],
+ },
+}
diff --git a/packages/Shell/Android.mk b/packages/Shell/Android.mk
deleted file mode 100644
index b738d77..0000000
--- a/packages/Shell/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SRC_FILES += \
- ../../../native/cmds/dumpstate/binder/android/os/IDumpstate.aidl \
- ../../../native/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl \
- ../../../native/cmds/dumpstate/binder/android/os/IDumpstateToken.aidl
-
-LOCAL_AIDL_INCLUDES = frameworks/native/cmds/dumpstate/binder
-
-LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-LOCAL_USE_AAPT2 := true
-
-LOCAL_PACKAGE_NAME := Shell
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.shell.*
-
-include $(BUILD_PACKAGE)
-
-include $(LOCAL_PATH)/tests/Android.mk
diff --git a/packages/Shell/tests/Android.bp b/packages/Shell/tests/Android.bp
new file mode 100644
index 0000000..8536c4f
--- /dev/null
+++ b/packages/Shell/tests/Android.bp
@@ -0,0 +1,19 @@
+android_test {
+ name: "ShellTests",
+ srcs: ["src/**/*.java"],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ "ub-uiautomator",
+ "junit",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ instrumentation_for: "Shell",
+ certificate: "platform",
+}
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
deleted file mode 100644
index 44ff338..0000000
--- a/packages/Shell/tests/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- mockito-target-minus-junit4 \
- ub-uiautomator \
- junit \
-
-LOCAL_PACKAGE_NAME := ShellTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_INSTRUMENTATION_FOR := Shell
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
new file mode 100644
index 0000000..fe1bb26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M1.22,8.49l0.43-4.96h4.33v1.17H2.67L2.44,7.41c0.41-0.29,0.85-0.43,1.33-0.43c0.77,0,1.38,0.3,1.83,0.9 s0.66,1.41,0.66,2.43c0,1.03-0.24,1.84-0.72,2.43s-1.14,0.88-1.98,0.88c-0.75,0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07,0.57,0.23,1,0.49,1.29c0.26,0.29,0.59,0.43,1.01,0.43c0.47,0,0.84-0.2,1.1-0.61c0.26-0.41,0.4-0.96,0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.96,8.11,3.47,8.11c-0.4,0-0.72,0.1-0.96,0.31L2.19,8.75L1.22,8.49z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M14.14,12.24l-0.22,0.27c-0.63,0.73-1.55,1.1-2.76,1.1c-1.08,0-1.92-0.36-2.53-1.07c-0.61-0.71-0.93-1.72-0.94-3.02V7.56 c0-1.39,0.28-2.44,0.84-3.13c0.56-0.7,1.39-1.04,2.51-1.04c0.95,0,1.69,0.26,2.23,0.79c0.54,0.53,0.83,1.28,0.89,2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45c-0.29-0.35-0.74-0.52-1.34-0.52c-0.72,0-1.24,0.23-1.57,0.7C9.14,5.63,8.96,6.37,8.95,7.4v2.03 c0,1,0.19,1.77,0.57,2.31c0.38,0.54,0.93,0.8,1.65,0.8c0.67,0,1.19-0.16,1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M20.96,8.88h-3.52v3.53h4.1v1.07h-5.35V3.52h5.28V4.6h-4.03V7.8h3.52V8.88z" />
+
+</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4437f49..ccf345b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -390,6 +390,9 @@
<!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
<string name="data_connection_lte_plus">LTE+</string>
+ <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5ge" translate="false">5Ge</string>
+
<!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
<string name="data_connection_5g" translate="false">5G</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 2f7e3b18..b7c20aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -46,6 +46,8 @@
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class MobileSignalController extends SignalController<
@@ -72,6 +74,8 @@
private SignalStrength mSignalStrength;
private MobileIconGroup mDefaultIcons;
private Config mConfig;
+ // Some specific carriers have 5GE network which is special LTE CA network.
+ private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
// TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
// need listener lists anymore.
@@ -235,6 +239,8 @@
TelephonyIcons.LTE_PLUS);
}
}
+ mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE,
+ TelephonyIcons.LTE_CA_5G_E);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
}
@@ -400,6 +406,26 @@
}
}
+ private boolean isCarrierSpecificDataIcon() {
+ if (mConfig.patternOfCarrierSpecificDataIcon == null
+ || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
+ return false;
+ }
+
+ Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
+ String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
+ mServiceState.getOperatorAlphaShortRaw()};
+ for (String opName : operatorNames) {
+ if (!TextUtils.isEmpty(opName)) {
+ Matcher matcher = stringPattern.matcher(opName);
+ if (matcher.find()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Updates the network's name based on incoming spn and plmn.
*/
@@ -566,12 +592,8 @@
+ " dataState=" + state.getDataRegState());
}
mServiceState = state;
- if (state != null) {
- mDataNetType = state.getDataNetworkType();
- if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
- mServiceState.isUsingCarrierAggregation()) {
- mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
- }
+ if (mServiceState != null) {
+ updateDataNetType(mServiceState.getDataNetworkType());
}
updateTelephony();
}
@@ -583,14 +605,21 @@
+ " type=" + networkType);
}
mDataState = state;
- mDataNetType = networkType;
- if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
- mServiceState.isUsingCarrierAggregation()) {
- mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
- }
+ updateDataNetType(networkType);
updateTelephony();
}
+ private void updateDataNetType(int networkType) {
+ mDataNetType = networkType;
+ if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
+ if (isCarrierSpecificDataIcon()) {
+ mDataNetType = NETWORK_TYPE_LTE_CA_5GE;
+ } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) {
+ mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
+ }
+ }
+ }
+
@Override
public void onDataActivity(int direction) {
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b4f0fec..5c6634c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -1084,6 +1084,7 @@
boolean hspaDataDistinguishable;
boolean inflateSignalStrengths = false;
boolean alwaysShowDataRatIcon = false;
+ public String patternOfCarrierSpecificDataIcon = "";
/**
* Mapping from NR 5G status string to an integer. The NR 5G status string should match
@@ -1122,6 +1123,8 @@
CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
config.hideLtePlus = b.getBoolean(
CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
+ config.patternOfCarrierSpecificDataIcon = b.getString(
+ CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
String nr5GIconConfiguration =
b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 7347f66..2c4b1f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -35,6 +35,7 @@
static final int ICON_3G = R.drawable.ic_3g_mobiledata;
static final int ICON_4G = R.drawable.ic_4g_mobiledata;
static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+ static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
static final int ICON_1X = R.drawable.ic_1x_mobiledata;
static final int ICON_5G = R.drawable.ic_5g_mobiledata;
static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
@@ -204,6 +205,19 @@
TelephonyIcons.ICON_LTE_PLUS,
true);
+ static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+ "5Ge",
+ null,
+ null,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ 0,
+ 0,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.data_connection_5ge,
+ TelephonyIcons.ICON_5G_E,
+ true);
+
static final MobileIconGroup NR_5G = new MobileIconGroup(
"5G",
null,
@@ -260,6 +274,7 @@
ICON_NAME_TO_ICON.put("h+", H_PLUS);
ICON_NAME_TO_ICON.put("4g", FOUR_G);
ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
+ ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
ICON_NAME_TO_ICON.put("lte", LTE);
ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
ICON_NAME_TO_ICON.put("5g", NR_5G);
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 1c9a43a..9c21e8f 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,9 @@
-artikz@google.com
+alsutton@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
+nathch@google.com
+rthakohov@google.com
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index b60dd0f..223eb55 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1094,11 +1094,21 @@
public void unbindBluetoothProfileService(int bluetoothProfile,
IBluetoothProfileServiceConnection proxy) {
synchronized (mProfileServices) {
- ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
+ Integer profile = new Integer(bluetoothProfile);
+ ProfileServiceConnections psc = mProfileServices.get(profile);
if (psc == null) {
return;
}
psc.removeProxy(proxy);
+ if (psc.isEmpty()) {
+ // All prxoies are disconnected, unbind with the service.
+ try {
+ mContext.unbindService(psc);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
+ }
+ mProfileServices.remove(profile);
+ }
}
}
@@ -1255,6 +1265,10 @@
mProxies.kill();
}
+ private boolean isEmpty() {
+ return mProxies.getRegisteredCallbackCount() == 0;
+ }
+
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// remove timeout message
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 90c86c7..63fd2fd 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2861,7 +2861,7 @@
try {
nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
// With Private DNS bypass support, we can proceed to update the
@@ -3031,7 +3031,7 @@
try {
nai.networkMonitor().notifyNetworkDisconnected();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
mNetworkAgentInfos.remove(nai.messenger);
nai.clatd.update();
@@ -3070,11 +3070,7 @@
// fallback network the default or requested a new network from the
// NetworkFactories, so network traffic isn't interrupted for an unnecessarily
// long time.
- try {
- mNetd.networkDestroy(nai.network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- loge("Exception destroying network: " + e);
- }
+ destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
}
synchronized (mNetworkForNetId) {
@@ -3082,6 +3078,35 @@
}
}
+ private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ // This should never fail. Specifying an already in use NetID will cause failure.
+ if (networkAgent.isVPN()) {
+ mNetd.networkCreateVpn(networkAgent.network.netId,
+ (networkAgent.networkMisc == null
+ || !networkAgent.networkMisc.allowBypass));
+ } else {
+ mNetd.networkCreatePhysical(networkAgent.network.netId,
+ getNetworkPermission(networkAgent.networkCapabilities));
+ }
+ mDnsResolver.createNetworkCache(networkAgent.network.netId);
+ return true;
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Error creating network " + networkAgent.network.netId + ": "
+ + e.getMessage());
+ return false;
+ }
+ }
+
+ private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ mNetd.networkDestroy(networkAgent.network.netId);
+ mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Exception destroying network: " + e);
+ }
+ }
+
// If this method proves to be too slow then we can maintain a separate
// pendingIntent => NetworkRequestInfo map.
// This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
@@ -3420,7 +3445,7 @@
try {
nai.networkMonitor().setAcceptPartialConnectivity();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
}
@@ -3456,7 +3481,7 @@
try {
nai.networkMonitor().launchCaptivePortalApp();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
});
}
@@ -4084,7 +4109,7 @@
try {
nai.networkMonitor().forceReevaluation(uid);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
@@ -5464,7 +5489,7 @@
try {
networkMonitor.start();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
NetworkInfo networkInfo = nai.networkInfo;
@@ -5521,7 +5546,7 @@
try {
networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
if (networkAgent.everConnected) {
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
@@ -6482,21 +6507,7 @@
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
- try {
- // This should never fail. Specifying an already in use NetID will cause failure.
- if (networkAgent.isVPN()) {
- mNMS.createVirtualNetwork(networkAgent.network.netId,
- (networkAgent.networkMisc == null ||
- !networkAgent.networkMisc.allowBypass));
- } else {
- mNMS.createPhysicalNetwork(networkAgent.network.netId,
- getNetworkPermission(networkAgent.networkCapabilities));
- }
- } catch (Exception e) {
- loge("Error creating network " + networkAgent.network.netId + ": "
- + e.getMessage());
- return;
- }
+ if (!createNativeNetwork(networkAgent)) return;
networkAgent.created = true;
}
@@ -6527,7 +6538,7 @@
networkAgent.networkMonitor().notifyNetworkConnected(
networkAgent.linkProperties, networkAgent.networkCapabilities);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
scheduleUnvalidatedPrompt(networkAgent);
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 887de74..09fa006 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -861,10 +861,13 @@
} catch (IllegalArgumentException e) { // restat throws this on error
throw new IOException("Can't restat: " + mDropBoxDir);
}
- int available = mStatFs.getAvailableBlocks();
- int nonreserved = available - mStatFs.getBlockCount() * reservePercent / 100;
+ long available = mStatFs.getAvailableBlocksLong();
+ long nonreserved = available - mStatFs.getBlockCountLong() * reservePercent / 100;
+ long maxAvailableLong = nonreserved * quotaPercent / 100;
+ int maxAvailable = Math.toIntExact(Math.max(0,
+ Math.min(maxAvailableLong, Integer.MAX_VALUE)));
int maximum = quotaKb * 1024 / mBlockSize;
- mCachedQuotaBlocks = Math.min(maximum, Math.max(0, nonreserved * quotaPercent / 100));
+ mCachedQuotaBlocks = Math.min(maximum, maxAvailable);
mCachedQuotaUptimeMillis = uptimeMillis;
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1ff50b2..6dbe3ad 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2045,28 +2045,6 @@
}
@Override
- public void createPhysicalNetwork(int netId, int permission) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkCreatePhysical(netId, permission);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void createVirtualNetwork(int netId, boolean secure) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkCreateVpn(netId, secure);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
public void addInterfaceToNetwork(String iface, int netId) {
modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
}
@@ -2143,38 +2121,6 @@
}
}
- private int parsePermission(String permission) {
- if (permission.equals("NETWORK")) {
- return INetd.PERMISSION_NETWORK;
- }
- if (permission.equals("SYSTEM")) {
- return INetd.PERMISSION_SYSTEM;
- }
- return INetd.PERMISSION_NONE;
- }
-
- @Override
- public void setPermission(String permission, int[] uids) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkSetPermissionForUser(parsePermission(permission), uids);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void clearPermission(int[] uids) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkClearPermissionForUser(uids);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
@Override
public void allowProtect(int uid) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index e33392d..2321afb 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -263,12 +263,6 @@
}
public void removeNetwork(Network network) {
- try {
- mDnsResolver.clearResolverConfiguration(network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- Slog.e(TAG, "Error clearing DNS configuration: " + e);
- return;
- }
mPrivateDnsMap.remove(network.netId);
mPrivateDnsValidationMap.remove(network.netId);
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0271d3b..1275302 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1141,7 +1141,11 @@
}
} catch (RuntimeException e) {
IoUtils.closeQuietly(tun);
- agentDisconnect();
+ // If this is not seamless handover, disconnect partially-established network when error
+ // occurs.
+ if (oldNetworkAgent != mNetworkAgent) {
+ agentDisconnect();
+ }
// restore old state
mConfig = oldConfig;
mConnection = oldConnection;
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index 38eb0bc..8186343 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -16,7 +16,6 @@
package com.android.server.connectivity.tethering;
-import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -164,11 +163,6 @@
}
private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
- if (ipServer.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
- // TODO: Figure out IPv6 support on PAN interfaces.
- return null;
- }
-
final Downstream ds = findDownstream(ipServer);
if (ds == null) return null;
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 8dda485..0ab1a3e 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -1,3 +1,5 @@
+set noparent
+
ogunwale@google.com
jjaggi@google.com
racarr@google.com
@@ -5,3 +7,6 @@
vishnun@google.com
akulian@google.com
roosa@google.com
+erosky@google.com
+riddlehsu@google.com
+louischang@google.com
diff --git a/services/net/Android.bp b/services/net/Android.bp
index d72f1cf..ab11fe4 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -16,7 +16,10 @@
},
},
api_dir: "aidl/ipmemorystore",
- versions: ["1"],
+ versions: [
+ "1",
+ "2",
+ ],
}
aidl_interface {
@@ -30,6 +33,7 @@
"java/android/net/INetworkStackConnector.aidl",
"java/android/net/INetworkStackStatusCallback.aidl",
"java/android/net/InitialConfigurationParcelable.aidl",
+ "java/android/net/NattKeepalivePacketDataParcelable.aidl",
"java/android/net/PrivateDnsConfigParcel.aidl",
"java/android/net/ProvisioningConfigurationParcelable.aidl",
"java/android/net/TcpKeepalivePacketDataParcelable.aidl",
@@ -49,7 +53,11 @@
},
api_dir: "aidl/networkstack",
imports: ["ipmemorystore-aidl-interfaces"],
- versions: ["1"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
}
java_library_static {
diff --git a/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..a8cbab2
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31891de
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,9 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..029968b
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl
@@ -0,0 +1,24 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..65de883
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..77d5917
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl
@@ -0,0 +1,15 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31891de
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,9 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..029968b
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl
@@ -0,0 +1,24 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..65de883
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..176a5ce
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/java/android/net/DhcpResultsParcelable.aidl b/services/net/java/android/net/DhcpResultsParcelable.aidl
index 978638b..c98d9c2 100644
--- a/services/net/java/android/net/DhcpResultsParcelable.aidl
+++ b/services/net/java/android/net/DhcpResultsParcelable.aidl
@@ -24,4 +24,5 @@
int mtu;
String serverAddress;
String vendorInfo;
-}
\ No newline at end of file
+ String serverHostName;
+}
diff --git a/services/net/java/android/net/INetworkMonitor.aidl b/services/net/java/android/net/INetworkMonitor.aidl
index b32ef12..3fc81a3 100644
--- a/services/net/java/android/net/INetworkMonitor.aidl
+++ b/services/net/java/android/net/INetworkMonitor.aidl
@@ -40,6 +40,20 @@
// for https probe.
const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ // Network validation flags indicate probe result and types. If no NETWORK_VALIDATION_RESULT_*
+ // are set, then it's equal to NETWORK_TEST_RESULT_INVALID. If NETWORK_VALIDATION_RESULT_VALID
+ // is set, then the network validates and equal to NETWORK_TEST_RESULT_VALID. If
+ // NETWORK_VALIDATION_RESULT_PARTIAL is set, then the network has partial connectivity which
+ // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. NETWORK_VALIDATION_PROBE_* is set
+ // when the specific probe result of the network is resolved.
+ const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+ const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
+
void start();
void launchCaptivePortalApp();
void notifyCaptivePortalAppFinished(int response);
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 4a115e6..6f91e00 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -18,11 +18,14 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
/**
* Manager class used to communicate with the ip memory store service in the network stack,
@@ -30,15 +33,18 @@
* @hide
*/
public class IpMemoryStore extends IpMemoryStoreClient {
- private final CompletableFuture<IIpMemoryStore> mService;
+ private static final String TAG = IpMemoryStore.class.getSimpleName();
+ @NonNull private final CompletableFuture<IIpMemoryStore> mService;
+ @NonNull private final AtomicReference<CompletableFuture<IIpMemoryStore>> mTailNode;
public IpMemoryStore(@NonNull final Context context) {
super(context);
mService = new CompletableFuture<>();
+ mTailNode = new AtomicReference<CompletableFuture<IIpMemoryStore>>(mService);
getNetworkStackClient().fetchIpMemoryStore(
new IIpMemoryStoreCallbacks.Stub() {
@Override
- public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) {
+ public void onIpMemoryStoreFetched(@NonNull final IIpMemoryStore memoryStore) {
mService.complete(memoryStore);
}
@@ -49,9 +55,28 @@
});
}
+ /*
+ * If the IpMemoryStore is ready, this function will run the request synchronously.
+ * Otherwise, it will enqueue the requests for execution immediately after the
+ * service becomes ready. The requests are guaranteed to be executed in the order
+ * they are sumbitted.
+ */
@Override
- protected IIpMemoryStore getService() throws InterruptedException, ExecutionException {
- return mService.get();
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ mTailNode.getAndUpdate(future -> future.handle((store, exception) -> {
+ if (exception != null) {
+ // this should never happens since we also catch the exception below
+ Log.wtf(TAG, "Error fetching IpMemoryStore", exception);
+ return store;
+ }
+
+ try {
+ cb.accept(store);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception occured: " + e.getMessage());
+ }
+ return store;
+ }));
}
@VisibleForTesting
diff --git a/services/net/java/android/net/IpMemoryStoreClient.java b/services/net/java/android/net/IpMemoryStoreClient.java
index 379c017..3d56202 100644
--- a/services/net/java/android/net/IpMemoryStoreClient.java
+++ b/services/net/java/android/net/IpMemoryStoreClient.java
@@ -31,6 +31,7 @@
import android.util.Log;
import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
/**
* service used to communicate with the ip memory store service in network stack,
@@ -46,8 +47,25 @@
mContext = context;
}
- @NonNull
- protected abstract IIpMemoryStore getService() throws InterruptedException, ExecutionException;
+ protected abstract void runWhenServiceReady(Consumer<IIpMemoryStore> cb)
+ throws ExecutionException;
+
+ @FunctionalInterface
+ private interface ThrowingRunnable {
+ void run() throws RemoteException;
+ }
+
+ private void ignoringRemoteException(ThrowingRunnable r) {
+ ignoringRemoteException("Failed to execute remote procedure call", r);
+ }
+
+ private void ignoringRemoteException(String message, ThrowingRunnable r) {
+ try {
+ r.run();
+ } catch (RemoteException e) {
+ Log.e(TAG, message, e);
+ }
+ }
/**
* Store network attributes for a given L2 key.
@@ -69,14 +87,12 @@
@NonNull final NetworkAttributes attributes,
@Nullable final OnStatusListener listener) {
try {
- try {
- getService().storeNetworkAttributes(l2Key, attributes.toParcelable(),
- OnStatusListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onComplete(new Status(Status.ERROR_UNKNOWN));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error storing network attributes", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeNetworkAttributes(l2Key, attributes.toParcelable(),
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing network attributes",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
}
}
@@ -95,14 +111,12 @@
@NonNull final String name, @NonNull final Blob data,
@Nullable final OnStatusListener listener) {
try {
- try {
- getService().storeBlob(l2Key, clientId, name, data,
- OnStatusListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onComplete(new Status(Status.ERROR_UNKNOWN));
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error storing blob", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeBlob(l2Key, clientId, name, data,
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing blob",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
}
}
@@ -123,14 +137,12 @@
public void findL2Key(@NonNull final NetworkAttributes attributes,
@NonNull final OnL2KeyResponseListener listener) {
try {
- try {
- getService().findL2Key(attributes.toParcelable(),
- OnL2KeyResponseListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error finding L2 Key", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.findL2Key(attributes.toParcelable(),
+ OnL2KeyResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error finding L2 Key",
+ () -> listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null));
}
}
@@ -146,14 +158,12 @@
public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
@NonNull final OnSameL3NetworkResponseListener listener) {
try {
- try {
- getService().isSameNetwork(l2Key1, l2Key2,
- OnSameL3NetworkResponseListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error checking for network sameness", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.isSameNetwork(l2Key1, l2Key2,
+ OnSameL3NetworkResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error checking for network sameness",
+ () -> listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null));
}
}
@@ -169,14 +179,13 @@
public void retrieveNetworkAttributes(@NonNull final String l2Key,
@NonNull final OnNetworkAttributesRetrievedListener listener) {
try {
- try {
- getService().retrieveNetworkAttributes(l2Key,
- OnNetworkAttributesRetrievedListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN), null, null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error retrieving network attributes", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveNetworkAttributes(l2Key,
+ OnNetworkAttributesRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving network attributes",
+ () -> listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null));
}
}
@@ -194,14 +203,13 @@
public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId,
@NonNull final String name, @NonNull final OnBlobRetrievedListener listener) {
try {
- try {
- getService().retrieveBlob(l2Key, clientId, name,
- OnBlobRetrievedListener.toAIDL(listener));
- } catch (InterruptedException | ExecutionException m) {
- listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN), null, null, null);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error retrieving blob", e);
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveBlob(l2Key, clientId, name,
+ OnBlobRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving blob",
+ () -> listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null, null));
}
}
}
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/services/net/java/android/net/NattKeepalivePacketData.java
similarity index 84%
rename from core/java/android/net/NattKeepalivePacketData.java
rename to services/net/java/android/net/NattKeepalivePacketData.java
index bdb246f..27ed11e 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/services/net/java/android/net/NattKeepalivePacketData.java
@@ -19,8 +19,10 @@
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import android.annotation.NonNull;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils;
+import android.os.Parcelable;
import android.system.OsConstants;
import java.net.Inet4Address;
@@ -29,8 +31,7 @@
import java.nio.ByteOrder;
/** @hide */
-public final class NattKeepalivePacketData extends KeepalivePacketData {
-
+public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
@@ -77,4 +78,18 @@
return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
}
+
+ /**
+ * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public NattKeepalivePacketDataParcelable toStableParcelable() {
+ final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = srcPort;
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = dstPort;
+ return parcel;
+ }
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
similarity index 66%
copy from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
copy to services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
index a73ba50..6f006d4 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -1,12 +1,11 @@
/*
- *
- * Copyright 2019, The Android Open Source Project
+ * Copyright (C) 2019 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
+ * 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,
@@ -15,6 +14,12 @@
* limitations under the License.
*/
-package android.telephony.ims;
+package android.net;
-parcelable RcsMessageQueryResult;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
+
diff --git a/services/net/java/android/net/ip/IIpClient.aidl b/services/net/java/android/net/ip/IIpClient.aidl
index 1e77264..9989c52 100644
--- a/services/net/java/android/net/ip/IIpClient.aidl
+++ b/services/net/java/android/net/ip/IIpClient.aidl
@@ -17,6 +17,7 @@
import android.net.ProxyInfo;
import android.net.ProvisioningConfigurationParcelable;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.TcpKeepalivePacketDataParcelable;
/** @hide */
@@ -33,4 +34,5 @@
void addKeepalivePacketFilter(int slot, in TcpKeepalivePacketDataParcelable pkt);
void removeKeepalivePacketFilter(int slot);
void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ void addNattKeepalivePacketFilter(int slot, in NattKeepalivePacketDataParcelable pkt);
}
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
new file mode 100644
index 0000000..f8d7e84
--- /dev/null
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2019 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.annotation.NonNull;
+import android.net.NattKeepalivePacketData;
+import android.net.ProxyInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.shared.ProvisioningConfiguration;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for IpClient.
+ *
+ * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+public class IpClientManager {
+ @NonNull private final IIpClient mIpClient;
+ @NonNull private final String mTag;
+
+ public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) {
+ mIpClient = ipClient;
+ mTag = tag;
+ }
+
+ public IpClientManager(@NonNull IIpClient ipClient) {
+ this(ipClient, IpClientManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ /**
+ * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be
+ * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to
+ * proceed.
+ */
+ public boolean completedPreDhcpAction() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.completedPreDhcpAction();
+ return true;
+ } catch (RemoteException e) {
+ log("Error completing PreDhcpAction", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Confirm the provisioning configuration.
+ */
+ public boolean confirmConfiguration() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.confirmConfiguration();
+ return true;
+ } catch (RemoteException e) {
+ log("Error confirming IpClient configuration", e);
+ return false;
+ }
+ }
+
+ /**
+ * Indicate that packet filter read is complete.
+ */
+ public boolean readPacketFilterComplete(byte[] data) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.readPacketFilterComplete(data);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient of packet filter read", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Shut down this IpClient instance altogether.
+ */
+ public boolean shutdown() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.shutdown();
+ return true;
+ } catch (RemoteException e) {
+ log("Error shutting down IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Start provisioning with the provided parameters.
+ */
+ public boolean startProvisioning(ProvisioningConfiguration prov) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.startProvisioning(prov.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error starting IpClient provisioning", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop this IpClient.
+ *
+ * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}.
+ */
+ public boolean stop() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.stop();
+ return true;
+ } catch (RemoteException e) {
+ log("Error stopping IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the TCP buffer sizes to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setTcpBufferSizes(String tcpBufferSizes) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setTcpBufferSizes(tcpBufferSizes);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient TCP buffer sizes", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the HTTP Proxy configuration to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setHttpProxy(ProxyInfo proxyInfo) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setHttpProxy(proxyInfo);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient proxy", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering,
+ * if not, Callback.setFallbackMulticastFilter() is called.
+ */
+ public boolean setMulticastFilter(boolean enabled) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setMulticastFilter(enabled);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting multicast filter", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addKeepalivePacketFilter(slot, pkt.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a NAT-T keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addNattKeepalivePacketFilter(slot, pkt.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Remove a keepalive packet filter after stopping keepalive offload.
+ */
+ public boolean removeKeepalivePacketFilter(int slot) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.removeKeepalivePacketFilter(slot);
+ return true;
+ } catch (RemoteException e) {
+ log("Error removing Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the L2 key and group hint for storing info into the memory store.
+ */
+ public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setL2KeyAndGroupHint(l2Key, groupHint);
+ return true;
+ } catch (RemoteException e) {
+ log("Failed setL2KeyAndGroupHint", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
index 44d8e0c..172dc24 100644
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
@@ -41,6 +41,7 @@
p.mtu = results.mtu;
p.serverAddress = parcelAddress(results.serverAddress);
p.vendorInfo = results.vendorInfo;
+ p.serverHostName = results.serverHostName;
return p;
}
@@ -54,6 +55,7 @@
results.mtu = p.mtu;
results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
results.vendorInfo = p.vendorInfo;
+ results.serverHostName = p.serverHostName;
return results;
}
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 23f5572..c22ca90 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -51,7 +51,7 @@
"liblzma",
"libnativehelper",
"libui",
- "libunwind",
+ "libunwindstack",
"libutils",
"netd_aidl_interface-cpp",
],
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index e615428..6a3469c5 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -177,11 +177,15 @@
* Audio Class Specific
*/
case UsbDescriptor.DESCRIPTORTYPE_AUDIO_INTERFACE:
- descriptor = UsbACInterface.allocDescriptor(this, stream, length, type);
+ if (mDeviceDescriptor.getDevClass() == UsbDescriptor.CLASSID_AUDIO) {
+ descriptor = UsbACInterface.allocDescriptor(this, stream, length, type);
+ }
break;
case UsbDescriptor.DESCRIPTORTYPE_AUDIO_ENDPOINT:
- descriptor = UsbACEndpoint.allocDescriptor(this, length, type);
+ if (mDeviceDescriptor.getDevClass() == UsbDescriptor.CLASSID_AUDIO) {
+ descriptor = UsbACEndpoint.allocDescriptor(this, length, type);
+ }
break;
default:
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index e25c17d..0f63853 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
@@ -174,4 +175,21 @@
in.readString(),
UserHandle.CREATOR.createFromParcel(in));
}
+
+ /**
+ * Determines if two {@link PhoneAccountHandle}s are from the same package.
+ *
+ * @param a Phone account handle to check for same {@link ConnectionService} package.
+ * @param b Other phone account handle to check for same {@link ConnectionService} package.
+ * @return {@code true} if the two {@link PhoneAccountHandle}s passed in belong to the same
+ * {@link ConnectionService} / package, {@code false} otherwise. Note: {@code null} phone
+ * account handles are considered equivalent to other {@code null} phone account handles.
+ * @hide
+ */
+ public static boolean areFromSamePackage(@Nullable PhoneAccountHandle a,
+ @Nullable PhoneAccountHandle b) {
+ String aPackageName = a != null ? a.getComponentName().getPackageName() : null;
+ String bPackageName = b != null ? b.getComponentName().getPackageName() : null;
+ return Objects.equals(aPackageName, bPackageName);
+ }
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index ecb0daf..e727a6e 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -4259,6 +4259,22 @@
* @hide
*/
public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
+
+ /**
+ * The current registered raw data network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaLongRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_LONG_RAW = "operator_alpha_long_raw";
+
+ /**
+ * The current registered raw data network operator name in short alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaShortRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_SHORT_RAW = "operator_alpha_short_raw";
}
/**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 349ef55..c449dbf 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1202,7 +1202,7 @@
* Override the SPN Display Condition 2 integer bits (lsb). B2, B1 is the last two bits of the
* spn display condition coding.
*
- * The default value -1 mean this field is not config.
+ * The default value -1 mean this field is not set.
*
* B1 = 0: display of registered PLMN name not required when registered PLMN is either HPLMN
* or a PLMN in the service provider PLMN list (see EF_SPDI).
@@ -1241,7 +1241,7 @@
/**
* Override the PNN - a string array of comma-separated alpha long and short names:
- * "alpha_long1, alpha_short1".
+ * "alpha_long1,alpha_short1".
*
* Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.58 EF_PNN.
* @hide
@@ -1259,6 +1259,8 @@
/**
* Allow ERI rules to select a carrier name display string when using 3gpp2 access technologies.
+ * If this bit is not set, the carrier name display string will be selected from the carrier
+ * display name resolver which doesn't apply the ERI rules.
*
* @hide
*/
@@ -1386,6 +1388,24 @@
"hide_lte_plus_data_icon_bool";
/**
+ * The string is used to filter redundant string from PLMN Network Name that's supplied by
+ * specific carrier.
+ *
+ * @hide
+ */
+ public static final String KEY_OPERATOR_NAME_FILTER_PATTERN_STRING =
+ "operator_name_filter_pattern_string";
+
+ /**
+ * The string is used to compare with operator name. If it matches the pattern then show
+ * specific data icon.
+ *
+ * @hide
+ */
+ public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING =
+ "show_carrier_data_icon_pattern_string";
+
+ /**
* Boolean to decide whether to show precise call failed cause to user
* @hide
*/
@@ -3027,6 +3047,8 @@
sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false);
+ sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
+ sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
@@ -3137,8 +3159,7 @@
* May throw an {@link IllegalArgumentException} if {@code overrideValues} contains invalid
* values for the specified config keys.
*
- * NOTE: This API is meant for testing purposes only and may only be accessed from the shell UID
- * during instrumentation testing.
+ * NOTE: This API is meant for testing purposes only.
*
* @param subscriptionId The subscription ID for which the override should be done.
* @param overrideValues Key-value pairs of the values that are to be overridden. If set to
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index a83d8f0..cbe5e71 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -49,10 +49,10 @@
// long alpha Operator Name String or Enhanced Operator Name String
/** @hide */
- protected final String mAlphaLong;
+ protected String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
/** @hide */
- protected final String mAlphaShort;
+ protected String mAlphaShort;
/** @hide */
protected CellIdentity(String tag, int type, String mcc, String mnc, String alphal,
@@ -145,6 +145,13 @@
}
/**
+ * @hide
+ */
+ public void setOperatorAlphaLong(String alphaLong) {
+ mAlphaLong = alphaLong;
+ }
+
+ /**
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
@@ -154,6 +161,13 @@
}
/**
+ * @hide
+ */
+ public void setOperatorAlphaShort(String alphaShort) {
+ mAlphaShort = alphaShort;
+ }
+
+ /**
* @return a CellLocation object for this CellIdentity
* @hide
*/
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 86cdce1..0ad1abe 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -339,6 +339,9 @@
private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
+ private String mOperatorAlphaLongRaw;
+ private String mOperatorAlphaShortRaw;
+
/**
* get String description of roaming type
* @hide
@@ -420,6 +423,8 @@
mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null :
s.getNetworkRegistrationInfoList();
mNrFrequencyRange = s.mNrFrequencyRange;
+ mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
+ mOperatorAlphaShortRaw = s.mOperatorAlphaShortRaw;
}
/**
@@ -453,6 +458,8 @@
mChannelNumber = in.readInt();
mCellBandwidths = in.createIntArray();
mNrFrequencyRange = in.readInt();
+ mOperatorAlphaLongRaw = in.readString();
+ mOperatorAlphaShortRaw = in.readString();
}
public void writeToParcel(Parcel out, int flags) {
@@ -478,6 +485,8 @@
out.writeInt(mChannelNumber);
out.writeIntArray(mCellBandwidths);
out.writeInt(mNrFrequencyRange);
+ out.writeString(mOperatorAlphaLongRaw);
+ out.writeString(mOperatorAlphaShortRaw);
}
public int describeContents() {
@@ -836,7 +845,9 @@
mIsEmergencyOnly,
mLteEarfcnRsrpBoost,
mNetworkRegistrationInfos,
- mNrFrequencyRange);
+ mNrFrequencyRange,
+ mOperatorAlphaLongRaw,
+ mOperatorAlphaShortRaw);
}
@Override
@@ -862,6 +873,8 @@
&& equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
s.mCdmaDefaultRoamingIndicator)
&& mIsEmergencyOnly == s.mIsEmergencyOnly
+ && equalsHandlesNulls(mOperatorAlphaLongRaw, s.mOperatorAlphaLongRaw)
+ && equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
&& (mNetworkRegistrationInfos == null
? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
&& mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
@@ -1019,6 +1032,8 @@
.append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
.append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
.append(", mNrFrequencyRange=").append(mNrFrequencyRange)
+ .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
+ .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
.append("}").toString();
}
@@ -1056,6 +1071,8 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
+ mOperatorAlphaLongRaw = null;
+ mOperatorAlphaShortRaw = null;
}
public void setStateOutOfService() {
@@ -1297,6 +1314,8 @@
m.putInt("ChannelNumber", mChannelNumber);
m.putIntArray("CellBandwidths", mCellBandwidths);
m.putInt("mNrFrequencyRange", mNrFrequencyRange);
+ m.putString("operator-alpha-long-raw", mOperatorAlphaLongRaw);
+ m.putString("operator-alpha-short-raw", mOperatorAlphaShortRaw);
}
/** @hide */
@@ -1910,4 +1929,36 @@
return state;
}
+
+ /**
+ * @hide
+ */
+ public void setOperatorAlphaLongRaw(String operatorAlphaLong) {
+ mOperatorAlphaLongRaw = operatorAlphaLong;
+ }
+
+ /**
+ * The current registered raw data network operator name in long alphanumeric format.
+ *
+ * @hide
+ */
+ public String getOperatorAlphaLongRaw() {
+ return mOperatorAlphaLongRaw;
+ }
+
+ /**
+ * @hide
+ */
+ public void setOperatorAlphaShortRaw(String operatorAlphaShort) {
+ mOperatorAlphaShortRaw = operatorAlphaShort;
+ }
+
+ /**
+ * The current registered raw data network operator name in short alphanumeric format.
+ *
+ * @hide
+ */
+ public String getOperatorAlphaShortRaw() {
+ return mOperatorAlphaShortRaw;
+ }
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index def7fbe..be7bb67 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -327,12 +327,12 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/);
+ true /* persistMessage*/, ActivityThread.currentPackageName());
}
private void sendTextMessageInternal(String destinationAddress, String scAddress,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean persistMessage) {
+ boolean persistMessage, String packageName) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -345,9 +345,8 @@
// If the subscription is invalid or default, we will use the default phone to send the
// SMS and possibly fail later in the SMS sending process.
ISms iSms = getISmsServiceOrThrow();
- iSms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
- destinationAddress,
- scAddress, text, sentIntent, deliveryIntent,
+ iSms.sendTextForSubscriber(getSubscriptionId(), packageName,
+ destinationAddress, scAddress, text, sentIntent, deliveryIntent,
persistMessage);
} catch (RemoteException ex) {
// ignore it
@@ -379,7 +378,7 @@
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- false /* persistMessage */);
+ false /* persistMessage */, ActivityThread.currentPackageName());
}
/**
@@ -620,13 +619,30 @@
String destinationAddress, String scAddress, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/);
+ deliveryIntents, true /* persistMessage*/, ActivityThread.currentPackageName());
+ }
+
+ /**
+ * @hide
+ * Similar method as #sendMultipartTextMessage(String, String, ArrayList, ArrayList, ArrayList)
+ * With an additional argument
+ * @param packageName serves as the default package name if ActivityThread.currentpackageName is
+ * null.
+ */
+ public void sendMultipartTextMessageExternal(
+ String destinationAddress, String scAddress, ArrayList<String> parts,
+ ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
+ String packageName) {
+ sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
+ deliveryIntents, true /* persistMessage*/,
+ ActivityThread.currentPackageName() == null
+ ? packageName : ActivityThread.currentPackageName());
}
private void sendMultipartTextMessageInternal(
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
- boolean persistMessage) {
+ boolean persistMessage, String packageName) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
@@ -638,8 +654,7 @@
try {
ISms iSms = getISmsServiceOrThrow();
iSms.sendMultipartTextForSubscriber(getSubscriptionId(),
- ActivityThread.currentPackageName(),
- destinationAddress, scAddress, parts,
+ packageName, destinationAddress, scAddress, parts,
sentIntents, deliveryIntents, persistMessage);
} catch (RemoteException ex) {
// ignore it
@@ -653,8 +668,8 @@
if (deliveryIntents != null && deliveryIntents.size() > 0) {
deliveryIntent = deliveryIntents.get(0);
}
- sendTextMessage(destinationAddress, scAddress, parts.get(0),
- sentIntent, deliveryIntent);
+ sendTextMessageInternal(destinationAddress, scAddress, parts.get(0),
+ sentIntent, deliveryIntent, true, packageName);
}
}
@@ -675,7 +690,7 @@
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, false /* persistMessage*/);
+ deliveryIntents, false /* persistMessage*/, ActivityThread.currentPackageName());
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 58c05aa..43acfdd 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2065,7 +2065,6 @@
} else {
logd("putPhoneIdAndSubIdExtra: no valid subs");
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
}
@@ -2076,9 +2075,6 @@
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- //FIXME this is using phoneId and slotIndex interchangeably
- //Eventually, this should be removed as it is not the slot id
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index add7d38..510e7c9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3281,7 +3281,7 @@
}
/**
- * Gets information about currently inserted UICCs and enabled eUICCs.
+ * Gets information about currently inserted UICCs and eUICCs.
* <p>
* Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
* <p>
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index d95a499..2246ccc 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -101,7 +101,7 @@
/**
* Get the embedded ID (EID) of the eUICC. If the UiccCardInfo is not an eUICC
- * (see {@link #isEuicc()}), returns null.
+ * (see {@link #isEuicc()}), or the EID is not available, returns null.
* <p>
* Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}).
@@ -115,7 +115,7 @@
}
/**
- * Get the ICCID of the UICC.
+ * Get the ICCID of the UICC. If the ICCID is not availble, returns null.
* <p>
* Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}).
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 93a7da0..2bc6775 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -140,6 +140,14 @@
return mIsEuicc;
}
+ /**
+ * Returns the ICCID of the card in the slot, or the EID of an active eUICC.
+ * <p>
+ * If the UICC slot is for an active eUICC, returns the EID.
+ * If the UICC slot is for an inactive eUICC, returns the ICCID of the enabled profile, or the
+ * root profile if all other profiles are disabled.
+ * If the UICC slot is not an eUICC, returns the ICCID.
+ */
public String getCardId() {
return mCardId;
}
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 2d6402d..b144ff76 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -558,6 +558,24 @@
} else if (this.getDisplayPriorityScore()
< emergencyNumber.getDisplayPriorityScore()) {
return 1;
+ } else if (this.getNumber().compareTo(emergencyNumber.getNumber()) != 0) {
+ return this.getNumber().compareTo(emergencyNumber.getNumber());
+ } else if (this.getCountryIso().compareTo(emergencyNumber.getCountryIso()) != 0) {
+ return this.getCountryIso().compareTo(emergencyNumber.getCountryIso());
+ } else if (this.getMnc().compareTo(emergencyNumber.getMnc()) != 0) {
+ return this.getMnc().compareTo(emergencyNumber.getMnc());
+ } else if (this.getEmergencyServiceCategoryBitmask()
+ != emergencyNumber.getEmergencyServiceCategoryBitmask()) {
+ return this.getEmergencyServiceCategoryBitmask()
+ > emergencyNumber.getEmergencyServiceCategoryBitmask() ? -1 : 1;
+ } else if (this.getEmergencyUrns().toString().compareTo(
+ emergencyNumber.getEmergencyUrns().toString()) != 0) {
+ return this.getEmergencyUrns().toString().compareTo(
+ emergencyNumber.getEmergencyUrns().toString());
+ } else if (this.getEmergencyCallRouting()
+ != emergencyNumber.getEmergencyCallRouting()) {
+ return this.getEmergencyCallRouting()
+ > emergencyNumber.getEmergencyCallRouting() ? -1 : 1;
} else {
return 0;
}
@@ -579,13 +597,9 @@
if (emergencyNumberList == null) {
return;
}
- Set<EmergencyNumber> mergedEmergencyNumber = new HashSet<>();
+ Set<Integer> duplicatedEmergencyNumberPosition = new HashSet<>();
for (int i = 0; i < emergencyNumberList.size(); i++) {
- // Skip the check because it was merged.
- if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
- continue;
- }
- for (int j = i + 1; j < emergencyNumberList.size(); j++) {
+ for (int j = 0; j < i; j++) {
if (areSameEmergencyNumbers(
emergencyNumberList.get(i), emergencyNumberList.get(j))) {
Rlog.e(LOG_TAG, "Found unexpected duplicate numbers: "
@@ -594,14 +608,15 @@
emergencyNumberList.set(i, mergeSameEmergencyNumbers(
emergencyNumberList.get(i), emergencyNumberList.get(j)));
// Mark the emergency number has been merged
- mergedEmergencyNumber.add(emergencyNumberList.get(j));
+ duplicatedEmergencyNumberPosition.add(j);
}
}
}
- // Remove the marked emergency number in the orignal list
- for (int i = 0; i < emergencyNumberList.size(); i++) {
- if (mergedEmergencyNumber.contains(emergencyNumberList.get(i))) {
- emergencyNumberList.remove(i--);
+
+ // Remove the marked emergency number in the original list
+ for (int i = emergencyNumberList.size() - 1; i >= 0; i--) {
+ if (duplicatedEmergencyNumberPosition.contains(i)) {
+ emergencyNumberList.remove(i);
}
}
Collections.sort(emergencyNumberList);
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index f1a5778..ee287d5 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -321,6 +321,18 @@
"android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
/**
+ * Key for an extra set on privileged actions {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED}
+ * providing the physical slot ID of the target slot.
+ *
+ * <p>Expected type of the extra data: int
+ *
+ * @hide
+ */
+ // TODO: Make this a @SystemApi.
+ public static final String EXTRA_PHYSICAL_SLOT_ID =
+ "android.telephony.euicc.extra.PHYSICAL_SLOT_ID";
+
+ /**
* Optional meta-data attribute for a carrier app providing an icon to use to represent the
* carrier. If not provided, the app's launcher icon will be used as a fallback.
*/
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 568c11b..fd58f7e 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -545,7 +545,8 @@
+ ", emergencyUrns=" + mEmergencyUrns
+ ", emergencyCallRouting=" + mEmergencyCallRouting
+ ", emergencyCallTesting=" + mEmergencyCallTesting
- + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }";
+ + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency
+ + ", mRestrictCause=" + mRestrictCause + " }";
}
@Override
@@ -565,6 +566,7 @@
out.writeInt(mEmergencyCallRouting);
out.writeBoolean(mEmergencyCallTesting);
out.writeBoolean(mHasKnownUserIntentEmergency);
+ out.writeInt(mRestrictCause);
}
private void readFromParcel(Parcel in) {
@@ -577,6 +579,7 @@
mEmergencyCallRouting = in.readInt();
mEmergencyCallTesting = in.readBoolean();
mHasKnownUserIntentEmergency = in.readBoolean();
+ mRestrictCause = in.readInt();
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index 0bb1b43..e90548a 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -33,8 +33,8 @@
*
* @hide
*/
- public Rcs1To1Thread(int threadId) {
- super(threadId);
+ public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
mThreadId = threadId;
}
@@ -56,7 +56,9 @@
*/
@WorkerThread
public long getFallbackThreadId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.get1To1ThreadFallbackThreadId(mThreadId,
+ callingPackage));
}
/**
@@ -69,8 +71,9 @@
*/
@WorkerThread
public void setFallbackThreadId(long fallbackThreadId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.set1To1ThreadFallbackThreadId(mThreadId, fallbackThreadId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.set1To1ThreadFallbackThreadId(mThreadId,
+ fallbackThreadId, callingPackage));
}
/**
@@ -81,6 +84,9 @@
@WorkerThread
public RcsParticipant getRecipient() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.get1To1ThreadOtherParticipantId(mThreadId,
+ callingPackage)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
index 5512c4c..a2d68ad 100644
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ b/telephony/java/android/telephony/ims/RcsControllerCall.java
@@ -27,38 +27,38 @@
* @hide - not meant for public use
*/
class RcsControllerCall {
- static <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
+ private final Context mContext;
+
+ RcsControllerCall(Context context) {
+ mContext = context;
+ }
+
+ <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
if (iRcs == null) {
throw new RcsMessageStoreException("Could not connect to RCS storage service");
}
try {
- return serviceCall.methodOnIRcs(iRcs);
+ return serviceCall.methodOnIRcs(iRcs, mContext.getOpPackageName());
} catch (RemoteException exception) {
throw new RcsMessageStoreException(exception.getMessage());
}
}
- static void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
+ void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
throws RcsMessageStoreException {
- IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
- if (iRcs == null) {
- throw new RcsMessageStoreException("Could not connect to RCS storage service");
- }
-
- try {
- serviceCall.methodOnIRcs(iRcs);
- } catch (RemoteException exception) {
- throw new RcsMessageStoreException(exception.getMessage());
- }
+ call((iRcs, callingPackage) -> {
+ serviceCall.methodOnIRcs(iRcs, callingPackage);
+ return null;
+ });
}
interface RcsServiceCall<R> {
- R methodOnIRcs(IRcs iRcs) throws RemoteException;
+ R methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
}
interface RcsServiceCallWithNoReturn {
- void methodOnIRcs(IRcs iRcs) throws RemoteException;
+ void methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 994b27a..9dd0720 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -40,5 +40,5 @@
*
* @hide
*/
- abstract void persist() throws RcsMessageStoreException;
+ abstract void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException;
}
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
index 8e3f6cd..b44adea 100644
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
@@ -38,7 +38,7 @@
* descriptor.
*/
@VisibleForTesting(visibility = PROTECTED)
- public abstract RcsEvent createRcsEvent();
+ public abstract RcsEvent createRcsEvent(RcsControllerCall rcsControllerCall);
RcsEventDescriptor(Parcel in) {
mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
index e30745b7..b972d55 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
@@ -39,9 +39,9 @@
mEvents = events;
}
- protected RcsEventQueryResult getRcsEventQueryResult() {
+ protected RcsEventQueryResult getRcsEventQueryResult(RcsControllerCall rcsControllerCall) {
List<RcsEvent> rcsEvents = mEvents.stream()
- .map(RcsEventDescriptor::createRcsEvent)
+ .map(rcsEvent -> rcsEvent.createRcsEvent(rcsControllerCall))
.collect(Collectors.toList());
return new RcsEventQueryResult(mContinuationToken, rcsEvents);
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 3816cd4..ef66a76 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -103,12 +103,15 @@
public @interface RcsFileTransferStatus {
}
+ private final RcsControllerCall mRcsControllerCall;
+
private int mId;
/**
* @hide
*/
- RcsFileTransferPart(int id) {
+ RcsFileTransferPart(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -134,7 +137,9 @@
*/
@WorkerThread
public void setFileTransferSessionId(String sessionId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferSessionId(mId, sessionId,
+ callingPackage));
}
/**
@@ -143,7 +148,8 @@
*/
@WorkerThread
public String getFileTransferSessionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferSessionId(mId, callingPackage));
}
/**
@@ -155,7 +161,9 @@
*/
@WorkerThread
public void setContentUri(Uri contentUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferContentUri(mId, contentUri,
+ callingPackage));
}
/**
@@ -165,7 +173,8 @@
@Nullable
@WorkerThread
public Uri getContentUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferContentUri(mId, callingPackage));
}
/**
@@ -177,8 +186,9 @@
*/
@WorkerThread
public void setContentMimeType(String contentMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferContentType(mId, contentMimeType));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferContentType(mId, contentMimeType,
+ callingPackage));
}
/**
@@ -188,7 +198,8 @@
@WorkerThread
@Nullable
public String getContentMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferContentType(mId, callingPackage));
}
/**
@@ -199,8 +210,9 @@
*/
@WorkerThread
public void setFileSize(long contentLength) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferFileSize(mId, contentLength));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferFileSize(mId, contentLength,
+ callingPackage));
}
/**
@@ -209,7 +221,8 @@
*/
@WorkerThread
public long getFileSize() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferFileSize(mId, callingPackage));
}
/**
@@ -222,8 +235,9 @@
*/
@WorkerThread
public void setTransferOffset(long transferOffset) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferTransferOffset(mId, transferOffset));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferTransferOffset(mId, transferOffset,
+ callingPackage));
}
/**
@@ -232,7 +246,8 @@
*/
@WorkerThread
public long getTransferOffset() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferTransferOffset(mId, callingPackage));
}
/**
@@ -244,7 +259,8 @@
@WorkerThread
public void setFileTransferStatus(@RcsFileTransferStatus int status)
throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferStatus(mId, status, callingPackage));
}
/**
@@ -253,7 +269,8 @@
*/
@WorkerThread
public @RcsFileTransferStatus int getFileTransferStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferStatus(mId, callingPackage));
}
/**
@@ -262,7 +279,8 @@
*/
@WorkerThread
public int getWidth() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferWidth(mId, callingPackage));
}
/**
@@ -273,7 +291,8 @@
*/
@WorkerThread
public void setWidth(int width) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferWidth(mId, width, callingPackage));
}
/**
@@ -282,7 +301,8 @@
*/
@WorkerThread
public int getHeight() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferHeight(mId, callingPackage));
}
/**
@@ -293,7 +313,8 @@
*/
@WorkerThread
public void setHeight(int height) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferHeight(mId, height, callingPackage));
}
/**
@@ -302,7 +323,8 @@
*/
@WorkerThread
public long getLength() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferLength(mId, callingPackage));
}
/**
@@ -313,7 +335,8 @@
*/
@WorkerThread
public void setLength(long length) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferLength(mId, length, callingPackage));
}
/**
@@ -323,7 +346,8 @@
*/
@WorkerThread
public Uri getPreviewUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferPreviewUri(mId, callingPackage));
}
/**
@@ -334,7 +358,9 @@
*/
@WorkerThread
public void setPreviewUri(Uri previewUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferPreviewUri(mId, previewUri,
+ callingPackage));
}
/**
@@ -343,7 +369,8 @@
*/
@WorkerThread
public String getPreviewMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransferPreviewType(mId, callingPackage));
}
/**
@@ -354,7 +381,8 @@
*/
@WorkerThread
public void setPreviewMimeType(String previewMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setFileTransferPreviewType(mId, previewMimeType));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setFileTransferPreviewType(mId, previewMimeType,
+ callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index baec19a..30abcb4 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -38,8 +38,8 @@
*
* @hide
*/
- public RcsGroupThread(int threadId) {
- super(threadId);
+ public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
}
/**
@@ -58,7 +58,8 @@
@Nullable
@WorkerThread
public String getGroupName() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadName(mThreadId, callingPackage));
}
/**
@@ -69,7 +70,9 @@
*/
@WorkerThread
public void setGroupName(String groupName) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadName(mThreadId, groupName,
+ callingPackage));
}
/**
@@ -79,7 +82,8 @@
*/
@Nullable
public Uri getGroupIcon() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadIcon(mThreadId, callingPackage));
}
/**
@@ -90,7 +94,9 @@
*/
@WorkerThread
public void setGroupIcon(@Nullable Uri groupIcon) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadIcon(mThreadId, groupIcon,
+ callingPackage));
}
/**
@@ -100,8 +106,11 @@
@Nullable
@WorkerThread
public RcsParticipant getOwner() throws RcsMessageStoreException {
- return new RcsParticipant(RcsControllerCall.call(
- iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
+ return new RcsParticipant(
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadOwner(mThreadId,
+ callingPackage)));
}
/**
@@ -114,8 +123,9 @@
*/
@WorkerThread
public void setOwner(@Nullable RcsParticipant participant) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGroupThreadOwner(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadOwner(mThreadId, participant.getId(),
+ callingPackage));
}
/**
@@ -133,8 +143,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.addParticipantToGroupThread(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.addParticipantToGroupThread(mThreadId,
+ participant.getId(), callingPackage));
}
/**
@@ -150,8 +161,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.removeParticipantFromGroupThread(mThreadId, participant.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.removeParticipantFromGroupThread(mThreadId,
+ participant.getId(), callingPackage));
}
/**
@@ -170,8 +182,10 @@
new RcsParticipantQueryParams.Builder().setThread(this).build();
RcsParticipantQueryResult queryResult = new RcsParticipantQueryResult(
- RcsControllerCall.call(
- iRcs -> iRcs.getParticipants(queryParameters)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
+ callingPackage)));
List<RcsParticipant> participantList = queryResult.getParticipants();
Set<RcsParticipant> participantSet = new LinkedHashSet<>(participantList);
@@ -187,7 +201,9 @@
@Nullable
@WorkerThread
public Uri getConferenceUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGroupThreadConferenceUri(mThreadId,
+ callingPackage));
}
/**
@@ -200,7 +216,8 @@
@Nullable
@WorkerThread
public void setConferenceUri(Uri conferenceUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri,
+ callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 4a6b963..f4beef7f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -23,14 +23,14 @@
* @hide
*/
public abstract class RcsGroupThreadEvent extends RcsEvent {
- private final int mRcsGroupThreadId;
- private final int mOriginatingParticipantId;
+ private final RcsGroupThread mRcsGroupThread;
+ private final RcsParticipant mOriginatingParticipant;
- RcsGroupThreadEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId) {
+ RcsGroupThreadEvent(long timestamp, RcsGroupThread rcsGroupThread,
+ RcsParticipant originatingParticipant) {
super(timestamp);
- mRcsGroupThreadId = rcsGroupThreadId;
- mOriginatingParticipantId = originatingParticipantId;
+ mRcsGroupThread = rcsGroupThread;
+ mOriginatingParticipant = originatingParticipant;
}
/**
@@ -38,7 +38,7 @@
*/
@NonNull
public RcsGroupThread getRcsGroupThread() {
- return new RcsGroupThread(mRcsGroupThreadId);
+ return mRcsGroupThread;
}
/**
@@ -46,6 +46,6 @@
*/
@NonNull
public RcsParticipant getOriginatingParticipant() {
- return new RcsParticipant(mOriginatingParticipantId);
+ return mOriginatingParticipant;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 3c6c74f..23e39ff 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -40,9 +40,10 @@
* @param newIcon {@link Uri} to the new icon of this {@link RcsGroupThread}
* @see RcsMessageStore#persistRcsEvent(RcsEvent)
*/
- public RcsGroupThreadIconChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
- @NonNull RcsParticipant originatingParticipant, @Nullable Uri newIcon) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ public RcsGroupThreadIconChangedEvent(long timestamp,
+ @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
+ @Nullable Uri newIcon) {
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewIcon = newIcon;
}
@@ -61,10 +62,10 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
// TODO ensure failure throws
- RcsControllerCall.call(iRcs -> iRcs.createGroupThreadIconChangedEvent(
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadIconChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
- getOriginatingParticipant().getId(), mNewIcon));
+ getOriginatingParticipant().getId(), mNewIcon, callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
index bcadc80..9350e40 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -38,9 +38,10 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadIconChangedEvent createRcsEvent() {
- return new RcsGroupThreadIconChangedEvent(mTimestamp, new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId), mNewIcon);
+ public RcsGroupThreadIconChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
+ return new RcsGroupThreadIconChangedEvent(mTimestamp,
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId), mNewIcon);
}
public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 5403253..a6a0867 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -41,7 +41,7 @@
*/
public RcsGroupThreadNameChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
@NonNull RcsParticipant originatingParticipant, @Nullable String newName) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewName = newName;
}
@@ -60,9 +60,9 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(iRcs -> iRcs.createGroupThreadNameChangedEvent(
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createGroupThreadNameChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
- getOriginatingParticipant().getId(), mNewName));
+ getOriginatingParticipant().getId(), mNewName, callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
index 597fa0a..f9ccdd5 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -37,11 +37,11 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadNameChangedEvent createRcsEvent() {
+ public RcsGroupThreadNameChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadNameChangedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
mNewName);
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 48be479..694c7de 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -30,19 +30,20 @@
* Creates a new {@link RcsGroupThreadParticipantJoinedEvent}. This event is not persisted into
* storage until {@link RcsMessageStore#persistRcsEvent(RcsEvent)} is called.
*
- * @param timestamp The timestamp of when this event happened, in milliseconds passed after
- * midnight, January 1st, 1970 UTC
- * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
+ * @param timestamp The timestamp of when this event happened, in milliseconds
+ * passed after
+ * midnight, January 1st, 1970 UTC
+ * @param rcsGroupThread The {@link RcsGroupThread} that this event happened on
* @param originatingParticipant The {@link RcsParticipant} that added or invited the new
* {@link RcsParticipant} into the {@link RcsGroupThread}
- * @param joinedParticipant The new {@link RcsParticipant} that joined the
- * {@link RcsGroupThread}
+ * @param joinedParticipant The new {@link RcsParticipant} that joined the
+ * {@link RcsGroupThread}
* @see RcsMessageStore#persistRcsEvent(RcsEvent)
*/
public RcsGroupThreadParticipantJoinedEvent(long timestamp,
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant joinedParticipant) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mJoinedParticipantId = joinedParticipant;
}
@@ -59,10 +60,11 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
- iRcs -> iRcs.createGroupThreadParticipantJoinedEvent(getTimestamp(),
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantJoinedEvent(
+ getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
- getJoinedParticipant().getId()));
+ getJoinedParticipant().getId(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
index abea10a..4a6803e 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -36,12 +36,13 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantJoinedEvent createRcsEvent() {
+ public RcsGroupThreadParticipantJoinedEvent createRcsEvent(
+ RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantJoinedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mJoinedParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mJoinedParticipantId));
}
public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index b724a3f..fec4354 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -44,7 +44,7 @@
public RcsGroupThreadParticipantLeftEvent(long timestamp,
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant leavingParticipant) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mLeavingParticipant = leavingParticipant;
}
@@ -58,10 +58,10 @@
}
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
- iRcs -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
- getLeavingParticipant().getId()));
+ getLeavingParticipant().getId(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
index f287db1..9b1085c 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -37,12 +37,12 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantLeftEvent createRcsEvent() {
+ public RcsGroupThreadParticipantLeftEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantLeftEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mLeavingParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mLeavingParticipantId));
}
@NonNull
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 06e2a41..2810a49 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -26,8 +26,8 @@
/**
* @hide
*/
- RcsIncomingMessage(int id) {
- super(id);
+ RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -39,8 +39,9 @@
*/
@WorkerThread
public void setArrivalTimestamp(long arrivalTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageArrivalTimestamp(mId, true, arrivalTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageArrivalTimestamp(mId, true,
+ arrivalTimestamp, callingPackage));
}
/**
@@ -50,7 +51,9 @@
*/
@WorkerThread
public long getArrivalTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageArrivalTimestamp(mId, true,
+ callingPackage));
}
/**
@@ -62,8 +65,9 @@
*/
@WorkerThread
public void setSeenTimestamp(long notifiedTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp,
+ callingPackage));
}
/**
@@ -73,7 +77,8 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSeenTimestamp(mId, true, callingPackage));
}
/**
@@ -83,7 +88,9 @@
@WorkerThread
public RcsParticipant getSenderParticipant() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getSenderParticipant(mId, callingPackage)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index 63dc1ac..0d6ca3c 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -25,20 +25,19 @@
*/
@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
+ private final RcsMessageStore mRcsMessageStore;
/**
* @hide
*/
- public RcsManager() {
- // empty constructor
+ public RcsManager(Context context) {
+ mRcsMessageStore = new RcsMessageStore(context);
}
- private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
-
/**
* Returns an instance of {@link RcsMessageStore}
*/
public RcsMessageStore getRcsMessageStore() {
- return sRcsMessageStoreInstance;
+ return mRcsMessageStore;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b0d0d5a..4601bfd 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -86,6 +86,11 @@
/**
* @hide
*/
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
protected final int mId;
@IntDef({
@@ -95,7 +100,8 @@
public @interface RcsMessageStatus {
}
- RcsMessage(int id) {
+ RcsMessage(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -115,7 +121,8 @@
* @see android.telephony.SubscriptionInfo#getSubscriptionId
*/
public int getSubscriptionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSubId(mId, isIncoming(), callingPackage));
}
/**
@@ -128,7 +135,9 @@
*/
@WorkerThread
public void setSubscriptionId(int subId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageSubId(mId, isIncoming(), subId,
+ callingPackage));
}
/**
@@ -139,8 +148,9 @@
*/
@WorkerThread
public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus,
+ callingPackage));
}
/**
@@ -150,7 +160,8 @@
*/
@WorkerThread
public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageStatus(mId, isIncoming(), callingPackage));
}
/**
@@ -163,8 +174,9 @@
*/
@WorkerThread
public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(), timestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(),
+ timestamp, callingPackage));
}
/**
@@ -175,8 +187,9 @@
*/
@WorkerThread
public long getOriginationTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getMessageOriginationTimestamp(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageOriginationTimestamp(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -189,8 +202,9 @@
*/
@WorkerThread
public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(), rcsMessageGlobalId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(),
+ rcsMessageGlobalId, callingPackage));
}
/**
@@ -200,7 +214,9 @@
*/
@WorkerThread
public String getRcsMessageId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -209,7 +225,9 @@
*/
@WorkerThread
public String getText() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getTextForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -220,18 +238,21 @@
*/
@WorkerThread
public void setText(String text) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setTextForMessage(mId, isIncoming(), text,
+ callingPackage));
}
/**
* @return Returns the associated latitude for this message, or
* {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
- *
* @throws RcsMessageStoreException if the value could not be read from the storage
*/
@WorkerThread
public double getLatitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getLatitudeForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -242,19 +263,21 @@
*/
@WorkerThread
public void setLatitude(double latitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude,
+ callingPackage));
}
/**
* @return Returns the associated longitude for this message, or
* {@link RcsMessage#LOCATION_NOT_SET} if it does not contain a location.
- *
* @throws RcsMessageStoreException if the value could not be read from the storage
*/
@WorkerThread
public double getLongitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getLongitudeForMessage(mId, isIncoming(),
+ callingPackage));
}
/**
@@ -265,8 +288,9 @@
*/
@WorkerThread
public void setLongitude(double longitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude,
+ callingPackage));
}
/**
@@ -282,8 +306,9 @@
public RcsFileTransferPart insertFileTransfer(
RcsFileTransferCreationParams fileTransferCreationParameters)
throws RcsMessageStoreException {
- return new RcsFileTransferPart(RcsControllerCall.call(
- iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
+ return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.storeFileTransfer(mId, isIncoming(),
+ fileTransferCreationParameters, callingPackage)));
}
/**
@@ -296,11 +321,12 @@
public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
- int[] fileTransferIds = RcsControllerCall.call(
- iRcs -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming()));
+ int[] fileTransferIds = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming(),
+ callingPackage));
for (int fileTransfer : fileTransferIds) {
- fileTransferParts.add(new RcsFileTransferPart(fileTransfer));
+ fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
}
return Collections.unmodifiableSet(fileTransferParts);
@@ -319,8 +345,9 @@
return;
}
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.deleteFileTransfer(fileTransferPart.getId()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.deleteFileTransfer(fileTransferPart.getId(),
+ callingPackage));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index 5df929b..36bb78a 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -20,13 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
@@ -35,23 +31,14 @@
*
* @hide
*/
-public final class RcsMessageQueryResult implements Parcelable {
- // The token to continue the query to get the next batch of results
- private RcsQueryContinuationToken mContinuationToken;
- // The message type and message ID pairs for all the messages in this query result
- private List<RcsTypeIdPair> mMessageTypeIdPairs;
+public final class RcsMessageQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
+ private final RcsMessageQueryResultParcelable mRcsMessageQueryResultParcelable;
- /**
- * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
- * to create query results
- *
- * @hide
- */
- public RcsMessageQueryResult(
- RcsQueryContinuationToken continuationToken,
- List<RcsTypeIdPair> messageTypeIdPairs) {
- mContinuationToken = continuationToken;
- mMessageTypeIdPairs = messageTypeIdPairs;
+ RcsMessageQueryResult(RcsControllerCall rcsControllerCall,
+ RcsMessageQueryResultParcelable rcsMessageQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
+ mRcsMessageQueryResultParcelable = rcsMessageQueryResultParcelable;
}
/**
@@ -61,7 +48,7 @@
*/
@Nullable
public RcsQueryContinuationToken getContinuationToken() {
- return mContinuationToken;
+ return mRcsMessageQueryResultParcelable.mContinuationToken;
}
/**
@@ -71,45 +58,10 @@
*/
@NonNull
public List<RcsMessage> getMessages() {
- List<RcsMessage> messages = new ArrayList<>();
- for (RcsTypeIdPair typeIdPair : mMessageTypeIdPairs) {
- if (typeIdPair.getType() == MESSAGE_TYPE_INCOMING) {
- messages.add(new RcsIncomingMessage(typeIdPair.getId()));
- } else {
- messages.add(new RcsOutgoingMessage(typeIdPair.getId()));
- }
- }
-
- return messages;
- }
-
- private RcsMessageQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(
- RcsQueryContinuationToken.class.getClassLoader());
- in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
- }
-
- public static final @android.annotation.NonNull Creator<RcsMessageQueryResult> CREATOR =
- new Creator<RcsMessageQueryResult>() {
- @Override
- public RcsMessageQueryResult createFromParcel(Parcel in) {
- return new RcsMessageQueryResult(in);
- }
-
- @Override
- public RcsMessageQueryResult[] newArray(int size) {
- return new RcsMessageQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
- dest.writeTypedList(mMessageTypeIdPairs);
+ return mRcsMessageQueryResultParcelable.mMessageTypeIdPairs.stream()
+ .map(typeIdPair -> typeIdPair.getType() == MESSAGE_TYPE_INCOMING
+ ? new RcsIncomingMessage(mRcsControllerCall, typeIdPair.getId())
+ : new RcsOutgoingMessage(mRcsControllerCall, typeIdPair.getId()))
+ .collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
rename to telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
index a73ba50..86928bf 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsMessageQueryResult;
+parcelable RcsMessageQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
new file mode 100644
index 0000000..4972f9b
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.ims.RcsTypeIdPair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsMessageQueryResultParcelable implements Parcelable {
+ // The token to continue the query to get the next batch of results
+ final RcsQueryContinuationToken mContinuationToken;
+ // The message type and message ID pairs for all the messages in this query result
+ final List<RcsTypeIdPair> mMessageTypeIdPairs;
+
+ public RcsMessageQueryResultParcelable(
+ RcsQueryContinuationToken continuationToken,
+ List<RcsTypeIdPair> messageTypeIdPairs) {
+ mContinuationToken = continuationToken;
+ mMessageTypeIdPairs = messageTypeIdPairs;
+ }
+
+ private RcsMessageQueryResultParcelable(Parcel in) {
+ mContinuationToken = in.readParcelable(
+ RcsQueryContinuationToken.class.getClassLoader());
+
+ mMessageTypeIdPairs = new ArrayList<>();
+ in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
+ }
+
+ public static final Creator<RcsMessageQueryResultParcelable> CREATOR =
+ new Creator<RcsMessageQueryResultParcelable>() {
+ @Override
+ public RcsMessageQueryResultParcelable createFromParcel(Parcel in) {
+ return new RcsMessageQueryResultParcelable(in);
+ }
+
+ @Override
+ public RcsMessageQueryResultParcelable[] newArray(int size) {
+ return new RcsMessageQueryResultParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeTypedList(mMessageTypeIdPairs);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 6fcb62b..d112798 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.content.Context;
import android.net.Uri;
import java.util.List;
@@ -30,6 +31,12 @@
* @hide
*/
public class RcsMessageStore {
+ RcsControllerCall mRcsControllerCall;
+
+ RcsMessageStore(Context context) {
+ mRcsControllerCall = new RcsControllerCall(context);
+ }
+
/**
* Returns the first chunk of existing {@link RcsThread}s in the common storage.
*
@@ -41,8 +48,10 @@
@NonNull
public RcsThreadQueryResult getRcsThreads(@Nullable RcsThreadQueryParams queryParameters)
throws RcsMessageStoreException {
- return new RcsThreadQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getRcsThreads(queryParameters)));
+ return new RcsThreadQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsThreads(queryParameters,
+ callingPackage)));
}
/**
@@ -56,8 +65,10 @@
@NonNull
public RcsThreadQueryResult getRcsThreads(@NonNull RcsQueryContinuationToken continuationToken)
throws RcsMessageStoreException {
- return new RcsThreadQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getRcsThreadsWithToken(continuationToken)));
+ return new RcsThreadQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsThreadsWithToken(continuationToken,
+ callingPackage)));
}
/**
@@ -72,8 +83,10 @@
public RcsParticipantQueryResult getRcsParticipants(
@Nullable RcsParticipantQueryParams queryParameters)
throws RcsMessageStoreException {
- return new RcsParticipantQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters)));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipants(queryParameters,
+ callingPackage)));
}
/**
@@ -89,22 +102,26 @@
public RcsParticipantQueryResult getRcsParticipants(
@NonNull RcsQueryContinuationToken continuationToken)
throws RcsMessageStoreException {
- return new RcsParticipantQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken)));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getParticipantsWithToken(continuationToken,
+ callingPackage)));
}
/**
* Returns the first chunk of existing {@link RcsMessage}s in the common storage.
*
- * @param queryParameters Parameters to specify to return a subset of all RcsMessages.
- * Passing a value of null will return all messages.
+ * @param queryParams Parameters to specify to return a subset of all RcsMessages.
+ * Passing a value of null will return all messages.
* @throws RcsMessageStoreException if the query could not be completed on the storage
*/
@WorkerThread
@NonNull
public RcsMessageQueryResult getRcsMessages(
- @Nullable RcsMessageQueryParams queryParameters) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+ @Nullable RcsMessageQueryParams queryParams) throws RcsMessageStoreException {
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
}
/**
@@ -118,7 +135,10 @@
@NonNull
public RcsMessageQueryResult getRcsMessages(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken));
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessagesWithToken(continuationToken,
+ callingPackage)));
}
/**
@@ -132,8 +152,9 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getEvents(queryParams, callingPackage))
+ .getRcsEventQueryResult(mRcsControllerCall);
}
/**
@@ -147,14 +168,16 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getEventsWithToken(continuationToken,
+ callingPackage))
+ .getRcsEventQueryResult(mRcsControllerCall);
}
/**
* Persists an {@link RcsEvent} to common storage.
*
- * @param persistableEvent The {@link RcsEvent} to persist into storage.
+ * @param rcsEvent The {@link RcsEvent} to persist into storage.
* @throws RcsMessageStoreException if the query could not be completed on the storage
* @see RcsGroupThreadNameChangedEvent
* @see RcsGroupThreadIconChangedEvent
@@ -164,8 +187,8 @@
*/
@WorkerThread
@NonNull
- public void persistRcsEvent(RcsEvent persistableEvent) throws RcsMessageStoreException {
- persistableEvent.persist();
+ public void persistRcsEvent(RcsEvent rcsEvent) throws RcsMessageStoreException {
+ rcsEvent.persist(mRcsControllerCall);
}
/**
@@ -180,7 +203,10 @@
public Rcs1To1Thread createRcs1To1Thread(@NonNull RcsParticipant recipient)
throws RcsMessageStoreException {
return new Rcs1To1Thread(
- RcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
+ mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createRcs1To1Thread(recipient.getId(),
+ callingPackage)));
}
/**
@@ -202,8 +228,12 @@
}
int[] finalRecipientIds = recipientIds;
- return new RcsGroupThread(RcsControllerCall.call(
- iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon)));
+
+ int threadId = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createGroupThread(finalRecipientIds, groupName,
+ groupIcon, callingPackage));
+
+ return new RcsGroupThread(mRcsControllerCall, threadId);
}
/**
@@ -218,8 +248,9 @@
return;
}
- boolean isDeleteSucceeded = RcsControllerCall.call(
- iRcs -> iRcs.deleteThread(thread.getThreadId(), thread.getThreadType()));
+ boolean isDeleteSucceeded = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.deleteThread(thread.getThreadId(),
+ thread.getThreadType(), callingPackage));
if (!isDeleteSucceeded) {
throw new RcsMessageStoreException("Could not delete RcsThread");
@@ -237,7 +268,8 @@
@NonNull
public RcsParticipant createRcsParticipant(String canonicalAddress, @Nullable String alias)
throws RcsMessageStoreException {
- return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.createRcsParticipant(canonicalAddress, alias)));
+ return new RcsParticipant(mRcsControllerCall, mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.createRcsParticipant(canonicalAddress, alias,
+ callingPackage)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 1b4bfe5..7080ec6 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -27,8 +27,8 @@
* @hide
*/
public class RcsOutgoingMessage extends RcsMessage {
- RcsOutgoingMessage(int id) {
- super(id);
+ RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -45,12 +45,13 @@
int[] deliveryParticipants;
List<RcsOutgoingMessageDelivery> messageDeliveries = new ArrayList<>();
- deliveryParticipants = RcsControllerCall.call(
- iRcs -> iRcs.getMessageRecipients(mId));
+ deliveryParticipants = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageRecipients(mId, callingPackage));
if (deliveryParticipants != null) {
for (Integer deliveryParticipant : deliveryParticipants) {
- messageDeliveries.add(new RcsOutgoingMessageDelivery(deliveryParticipant, mId));
+ messageDeliveries.add(new RcsOutgoingMessageDelivery(
+ mRcsControllerCall, deliveryParticipant, mId));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index 2db49c6..df4a3e4 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -25,6 +25,7 @@
* @hide
*/
public class RcsOutgoingMessageDelivery {
+ private final RcsControllerCall mRcsControllerCall;
// The participant that this delivery is intended for
private final int mRecipientId;
// The message this delivery is associated with
@@ -35,7 +36,9 @@
*
* @hide
*/
- RcsOutgoingMessageDelivery(int recipientId, int messageId) {
+ RcsOutgoingMessageDelivery(
+ RcsControllerCall rcsControllerCall, int recipientId, int messageId) {
+ mRcsControllerCall = rcsControllerCall;
mRecipientId = recipientId;
mRcsOutgoingMessageId = messageId;
}
@@ -49,8 +52,9 @@
*/
@WorkerThread
public void setDeliveredTimestamp(long deliveredTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
- mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp, callingPackage));
}
/**
@@ -61,8 +65,9 @@
*/
@WorkerThread
public long getDeliveredTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
- mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, callingPackage));
}
/**
@@ -74,8 +79,9 @@
*/
@WorkerThread
public void setSeenTimestamp(long seenTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
- mRcsOutgoingMessageId, mRecipientId, seenTimestamp));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliverySeenTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, seenTimestamp, callingPackage));
}
/**
@@ -86,8 +92,9 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getOutgoingDeliverySeenTimestamp(mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliverySeenTimestamp(
+ mRcsOutgoingMessageId, mRecipientId, callingPackage));
}
/**
@@ -99,8 +106,9 @@
*/
@WorkerThread
public void setStatus(@RcsMessage.RcsMessageStatus int status) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
- mRcsOutgoingMessageId, mRecipientId, status));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setOutgoingDeliveryStatus(
+ mRcsOutgoingMessageId, mRecipientId, status, callingPackage));
}
/**
@@ -109,8 +117,9 @@
*/
@WorkerThread
public @RcsMessage.RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(
- iRcs -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId, mRecipientId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId,
+ mRecipientId, callingPackage));
}
/**
@@ -118,7 +127,7 @@
*/
@NonNull
public RcsParticipant getRecipient() {
- return new RcsParticipant(mRecipientId);
+ return new RcsParticipant(mRcsControllerCall, mRecipientId);
}
/**
@@ -126,6 +135,6 @@
*/
@NonNull
public RcsOutgoingMessage getMessage() {
- return new RcsOutgoingMessage(mRcsOutgoingMessageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, mRcsOutgoingMessageId);
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index bcf134a..8512e96 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -24,8 +24,9 @@
* @hide
*/
public class RcsParticipant {
+ private final RcsControllerCall mRcsControllerCall;
// The row ID of this participant in the database
- private int mId;
+ private final int mId;
/**
* Constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
@@ -33,7 +34,8 @@
*
* @hide
*/
- public RcsParticipant(int id) {
+ public RcsParticipant(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -45,7 +47,9 @@
@Nullable
@WorkerThread
public String getCanonicalAddress() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantCanonicalAddress(mId,
+ callingPackage));
}
/**
@@ -57,7 +61,8 @@
@Nullable
@WorkerThread
public String getAlias() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantAlias(mId, callingPackage));
}
/**
@@ -70,7 +75,8 @@
*/
@WorkerThread
public void setAlias(String alias) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setRcsParticipantAlias(mId, alias, callingPackage));
}
/**
@@ -82,7 +88,8 @@
@Nullable
@WorkerThread
public String getContactId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getRcsParticipantContactId(mId, callingPackage));
}
/**
@@ -95,7 +102,9 @@
*/
@WorkerThread
public void setContactId(String contactId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.setRcsParticipantContactId(mId, contactId,
+ callingPackage));
}
@Override
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 61801f3..865bc05 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -69,8 +69,8 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
- getTimestamp(), getParticipant().getId(), getNewAlias()));
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call((iRcs, callingPackage) -> iRcs.createParticipantAliasChangedEvent(
+ getTimestamp(), getParticipant().getId(), getNewAlias(), callingPackage));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
index b29896c..43b918c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -41,9 +41,9 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsParticipantAliasChangedEvent createRcsEvent() {
+ public RcsParticipantAliasChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsParticipantAliasChangedEvent(
- mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
+ mTimestamp, new RcsParticipant(rcsControllerCall, mParticipantId), mNewAlias);
}
public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 731c94e..0721dfd 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -30,10 +30,13 @@
* @hide
*/
public final class RcsParticipantQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
private final RcsParticipantQueryResultParcelable mRcsParticipantQueryResultParcelable;
RcsParticipantQueryResult(
+ RcsControllerCall rcsControllerCall,
RcsParticipantQueryResultParcelable rcsParticipantQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
mRcsParticipantQueryResultParcelable = rcsParticipantQueryResultParcelable;
}
@@ -55,7 +58,7 @@
@NonNull
public List<RcsParticipant> getParticipants() {
return mRcsParticipantQueryResultParcelable.mParticipantIds.stream()
- .map(RcsParticipant::new)
+ .map(participantId -> new RcsParticipant(mRcsControllerCall, participantId))
.collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index cf1dc76..efb2cca 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -33,6 +33,7 @@
public abstract class RcsThread {
/**
* The rcs_participant_thread_id that represents this thread in the database
+ *
* @hide
*/
protected int mThreadId;
@@ -40,8 +41,14 @@
/**
* @hide
*/
- protected RcsThread(int threadId) {
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
+ protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) {
mThreadId = threadId;
+ mRcsControllerCall = rcsControllerCall;
}
/**
@@ -51,7 +58,8 @@
@WorkerThread
@NonNull
public RcsMessageSnippet getSnippet() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
+ return mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessageSnippet(mThreadId, callingPackage));
}
/**
@@ -64,8 +72,10 @@
public RcsIncomingMessage addIncomingMessage(
@NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
throws RcsMessageStoreException {
- return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
- mThreadId, rcsIncomingMessageCreationParams)));
+ int messageId = mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.addIncomingMessage(mThreadId,
+ rcsIncomingMessageCreationParams, callingPackage));
+ return new RcsIncomingMessage(mRcsControllerCall, messageId);
}
/**
@@ -78,10 +88,10 @@
public RcsOutgoingMessage addOutgoingMessage(
@NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
throws RcsMessageStoreException {
- int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
- mThreadId, rcsOutgoingMessageCreationParams));
+ int messageId = mRcsControllerCall.call((iRcs, callingPackage) -> iRcs.addOutgoingMessage(
+ mThreadId, rcsOutgoingMessageCreationParams, callingPackage));
- return new RcsOutgoingMessage(messageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, messageId);
}
/**
@@ -92,9 +102,10 @@
*/
@WorkerThread
public void deleteMessage(@NonNull RcsMessage rcsMessage) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
- iRcs -> iRcs.deleteMessage(rcsMessage.getId(), rcsMessage.isIncoming(), mThreadId,
- isGroup()));
+ mRcsControllerCall.callWithNoReturn(
+ (iRcs, callingPackage) -> iRcs.deleteMessage(rcsMessage.getId(),
+ rcsMessage.isIncoming(), mThreadId,
+ isGroup(), callingPackage));
}
/**
@@ -108,9 +119,11 @@
@WorkerThread
@NonNull
public RcsMessageQueryResult getMessages() throws RcsMessageStoreException {
- RcsMessageQueryParams queryParameters =
+ RcsMessageQueryParams queryParams =
new RcsMessageQueryParams.Builder().setThread(this).build();
- return RcsControllerCall.call(iRcs -> iRcs.getMessages(queryParameters));
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(
+ (iRcs, callingPackage) -> iRcs.getMessages(queryParams, callingPackage)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index c77bdb3..3de25de 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -33,9 +33,12 @@
* @hide
*/
public final class RcsThreadQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
private final RcsThreadQueryResultParcelable mRcsThreadQueryResultParcelable;
- RcsThreadQueryResult(RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+ RcsThreadQueryResult(RcsControllerCall rcsControllerCall,
+ RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
mRcsThreadQueryResultParcelable = rcsThreadQueryResultParcelable;
}
@@ -58,8 +61,8 @@
public List<RcsThread> getThreads() {
return mRcsThreadQueryResultParcelable.mRcsThreadIds.stream()
.map(typeIdPair -> typeIdPair.getType() == THREAD_TYPE_1_TO_1
- ? new Rcs1To1Thread(typeIdPair.getId())
- : new RcsGroupThread(typeIdPair.getId()))
+ ? new Rcs1To1Thread(mRcsControllerCall, typeIdPair.getId())
+ : new RcsGroupThread(mRcsControllerCall, typeIdPair.getId()))
.collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 50dc587..9ee15da 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -23,7 +23,7 @@
import android.telephony.ims.RcsIncomingMessageCreationParams;
import android.telephony.ims.RcsMessageSnippet;
import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsMessageQueryResult;
+import android.telephony.ims.RcsMessageQueryResultParcelable;
import android.telephony.ims.RcsOutgoingMessageCreationParams;
import android.telephony.ims.RcsParticipantQueryParams;
import android.telephony.ims.RcsParticipantQueryResultParcelable;
@@ -39,34 +39,34 @@
/////////////////////////
// RcsMessageStore APIs
/////////////////////////
- RcsThreadQueryResultParcelable getRcsThreads(in RcsThreadQueryParams queryParams);
+ RcsThreadQueryResultParcelable getRcsThreads(in RcsThreadQueryParams queryParams, String callingPackage);
RcsThreadQueryResultParcelable getRcsThreadsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsParticipantQueryResultParcelable getParticipants(in RcsParticipantQueryParams queryParams);
+ RcsParticipantQueryResultParcelable getParticipants(in RcsParticipantQueryParams queryParams, String callingPackage);
RcsParticipantQueryResultParcelable getParticipantsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
+ RcsMessageQueryResultParcelable getMessages(in RcsMessageQueryParams queryParams, String callingPackage);
- RcsMessageQueryResult getMessagesWithToken(
- in RcsQueryContinuationToken continuationToken);
+ RcsMessageQueryResultParcelable getMessagesWithToken(
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
- RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams);
+ RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams, String callingPackage);
RcsEventQueryResultDescriptor getEventsWithToken(
- in RcsQueryContinuationToken continuationToken);
+ in RcsQueryContinuationToken continuationToken, String callingPackage);
// returns true if the thread was successfully deleted
- boolean deleteThread(int threadId, int threadType);
+ boolean deleteThread(int threadId, int threadType, String callingPackage);
// Creates an Rcs1To1Thread and returns its row ID
- int createRcs1To1Thread(int participantId);
+ int createRcs1To1Thread(int participantId, String callingPackage);
// Creates an RcsGroupThread and returns its row ID
- int createGroupThread(in int[] participantIds, String groupName, in Uri groupIcon);
+ int createGroupThread(in int[] participantIds, String groupName, in Uri groupIcon, String callingPackage);
/////////////////////////
// RcsThread APIs
@@ -74,128 +74,128 @@
// Creates a new RcsIncomingMessage on the given thread and returns its row ID
int addIncomingMessage(int rcsThreadId,
- in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams);
+ in RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams, String callingPackage);
// Creates a new RcsOutgoingMessage on the given thread and returns its row ID
int addOutgoingMessage(int rcsThreadId,
- in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams);
+ in RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams, String callingPackage);
// TODO: modify RcsProvider URI's to allow deleting a message without specifying its thread
- void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup);
+ void deleteMessage(int rcsMessageId, boolean isIncoming, int rcsThreadId, boolean isGroup, String callingPackage);
- RcsMessageSnippet getMessageSnippet(int rcsThreadId);
+ RcsMessageSnippet getMessageSnippet(int rcsThreadId, String callingPackage);
/////////////////////////
// Rcs1To1Thread APIs
/////////////////////////
- void set1To1ThreadFallbackThreadId(int rcsThreadId, long fallbackId);
+ void set1To1ThreadFallbackThreadId(int rcsThreadId, long fallbackId, String callingPackage);
- long get1To1ThreadFallbackThreadId(int rcsThreadId);
+ long get1To1ThreadFallbackThreadId(int rcsThreadId, String callingPackage);
- int get1To1ThreadOtherParticipantId(int rcsThreadId);
+ int get1To1ThreadOtherParticipantId(int rcsThreadId, String callingPackage);
/////////////////////////
// RcsGroupThread APIs
/////////////////////////
- void setGroupThreadName(int rcsThreadId, String groupName);
+ void setGroupThreadName(int rcsThreadId, String groupName, String callingPackage);
- String getGroupThreadName(int rcsThreadId);
+ String getGroupThreadName(int rcsThreadId, String callingPackage);
- void setGroupThreadIcon(int rcsThreadId, in Uri groupIcon);
+ void setGroupThreadIcon(int rcsThreadId, in Uri groupIcon, String callingPackage);
- Uri getGroupThreadIcon(int rcsThreadId);
+ Uri getGroupThreadIcon(int rcsThreadId, String callingPackage);
- void setGroupThreadOwner(int rcsThreadId, int participantId);
+ void setGroupThreadOwner(int rcsThreadId, int participantId, String callingPackage);
- int getGroupThreadOwner(int rcsThreadId);
+ int getGroupThreadOwner(int rcsThreadId, String callingPackage);
- void setGroupThreadConferenceUri(int rcsThreadId, in Uri conferenceUri);
+ void setGroupThreadConferenceUri(int rcsThreadId, in Uri conferenceUri, String callingPackage);
- Uri getGroupThreadConferenceUri(int rcsThreadId);
+ Uri getGroupThreadConferenceUri(int rcsThreadId, String callingPackage);
- void addParticipantToGroupThread(int rcsThreadId, int participantId);
+ void addParticipantToGroupThread(int rcsThreadId, int participantId, String callingPackage);
- void removeParticipantFromGroupThread(int rcsThreadId, int participantId);
+ void removeParticipantFromGroupThread(int rcsThreadId, int participantId, String callingPackage);
/////////////////////////
// RcsParticipant APIs
/////////////////////////
// Creates a new RcsParticipant and returns its rowId
- int createRcsParticipant(String canonicalAddress, String alias);
+ int createRcsParticipant(String canonicalAddress, String alias, String callingPackage);
- String getRcsParticipantCanonicalAddress(int participantId);
+ String getRcsParticipantCanonicalAddress(int participantId, String callingPackage);
- String getRcsParticipantAlias(int participantId);
+ String getRcsParticipantAlias(int participantId, String callingPackage);
- void setRcsParticipantAlias(int id, String alias);
+ void setRcsParticipantAlias(int id, String alias, String callingPackage);
- String getRcsParticipantContactId(int participantId);
+ String getRcsParticipantContactId(int participantId, String callingPackage);
- void setRcsParticipantContactId(int participantId, String contactId);
+ void setRcsParticipantContactId(int participantId, String contactId, String callingPackage);
/////////////////////////
// RcsMessage APIs
/////////////////////////
- void setMessageSubId(int messageId, boolean isIncoming, int subId);
+ void setMessageSubId(int messageId, boolean isIncoming, int subId, String callingPackage);
- int getMessageSubId(int messageId, boolean isIncoming);
+ int getMessageSubId(int messageId, boolean isIncoming, String callingPackage);
- void setMessageStatus(int messageId, boolean isIncoming, int status);
+ void setMessageStatus(int messageId, boolean isIncoming, int status, String callingPackage);
- int getMessageStatus(int messageId, boolean isIncoming);
+ int getMessageStatus(int messageId, boolean isIncoming, String callingPackage);
- void setMessageOriginationTimestamp(int messageId, boolean isIncoming, long originationTimestamp);
+ void setMessageOriginationTimestamp(int messageId, boolean isIncoming, long originationTimestamp, String callingPackage);
- long getMessageOriginationTimestamp(int messageId, boolean isIncoming);
+ long getMessageOriginationTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setGlobalMessageIdForMessage(int messageId, boolean isIncoming, String globalId);
+ void setGlobalMessageIdForMessage(int messageId, boolean isIncoming, String globalId, String callingPackage);
- String getGlobalMessageIdForMessage(int messageId, boolean isIncoming);
+ String getGlobalMessageIdForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setMessageArrivalTimestamp(int messageId, boolean isIncoming, long arrivalTimestamp);
+ void setMessageArrivalTimestamp(int messageId, boolean isIncoming, long arrivalTimestamp, String callingPackage);
- long getMessageArrivalTimestamp(int messageId, boolean isIncoming);
+ long getMessageArrivalTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setMessageSeenTimestamp(int messageId, boolean isIncoming, long seenTimestamp);
+ void setMessageSeenTimestamp(int messageId, boolean isIncoming, long seenTimestamp, String callingPackage);
- long getMessageSeenTimestamp(int messageId, boolean isIncoming);
+ long getMessageSeenTimestamp(int messageId, boolean isIncoming, String callingPackage);
- void setTextForMessage(int messageId, boolean isIncoming, String text);
+ void setTextForMessage(int messageId, boolean isIncoming, String text, String callingPackage);
- String getTextForMessage(int messageId, boolean isIncoming);
+ String getTextForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setLatitudeForMessage(int messageId, boolean isIncoming, double latitude);
+ void setLatitudeForMessage(int messageId, boolean isIncoming, double latitude, String callingPackage);
- double getLatitudeForMessage(int messageId, boolean isIncoming);
+ double getLatitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
- void setLongitudeForMessage(int messageId, boolean isIncoming, double longitude);
+ void setLongitudeForMessage(int messageId, boolean isIncoming, double longitude, String callingPackage);
- double getLongitudeForMessage(int messageId, boolean isIncoming);
+ double getLongitudeForMessage(int messageId, boolean isIncoming, String callingPackage);
// Returns the ID's of the file transfers attached to the given message
- int[] getFileTransfersAttachedToMessage(int messageId, boolean isIncoming);
+ int[] getFileTransfersAttachedToMessage(int messageId, boolean isIncoming, String callingPackage);
- int getSenderParticipant(int messageId);
+ int getSenderParticipant(int messageId, String callingPackage);
/////////////////////////
// RcsOutgoingMessageDelivery APIs
/////////////////////////
// Returns the participant ID's that this message is intended to be delivered to
- int[] getMessageRecipients(int messageId);
+ int[] getMessageRecipients(int messageId, String callingPackage);
- long getOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId);
+ long getOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, long deliveredTimestamp);
+ void setOutgoingDeliveryDeliveredTimestamp(int messageId, int participantId, long deliveredTimestamp, String callingPackage);
- long getOutgoingDeliverySeenTimestamp(int messageId, int participantId);
+ long getOutgoingDeliverySeenTimestamp(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliverySeenTimestamp(int messageId, int participantId, long seenTimestamp);
+ void setOutgoingDeliverySeenTimestamp(int messageId, int participantId, long seenTimestamp, String callingPackage);
- int getOutgoingDeliveryStatus(int messageId, int participantId);
+ int getOutgoingDeliveryStatus(int messageId, int participantId, String callingPackage);
- void setOutgoingDeliveryStatus(int messageId, int participantId, int status);
+ void setOutgoingDeliveryStatus(int messageId, int participantId, int status, String callingPackage);
/////////////////////////
// RcsFileTransferPart APIs
@@ -203,64 +203,64 @@
// Performs the initial write to storage and returns the row ID.
int storeFileTransfer(int messageId, boolean isIncoming,
- in RcsFileTransferCreationParams fileTransferCreationParams);
+ in RcsFileTransferCreationParams fileTransferCreationParams, String callingPackage);
- void deleteFileTransfer(int partId);
+ void deleteFileTransfer(int partId, String callingPackage);
- void setFileTransferSessionId(int partId, String sessionId);
+ void setFileTransferSessionId(int partId, String sessionId, String callingPackage);
- String getFileTransferSessionId(int partId);
+ String getFileTransferSessionId(int partId, String callingPackage);
- void setFileTransferContentUri(int partId, in Uri contentUri);
+ void setFileTransferContentUri(int partId, in Uri contentUri, String callingPackage);
- Uri getFileTransferContentUri(int partId);
+ Uri getFileTransferContentUri(int partId, String callingPackage);
- void setFileTransferContentType(int partId, String contentType);
+ void setFileTransferContentType(int partId, String contentType, String callingPackage);
- String getFileTransferContentType(int partId);
+ String getFileTransferContentType(int partId, String callingPackage);
- void setFileTransferFileSize(int partId, long fileSize);
+ void setFileTransferFileSize(int partId, long fileSize, String callingPackage);
- long getFileTransferFileSize(int partId);
+ long getFileTransferFileSize(int partId, String callingPackage);
- void setFileTransferTransferOffset(int partId, long transferOffset);
+ void setFileTransferTransferOffset(int partId, long transferOffset, String callingPackage);
- long getFileTransferTransferOffset(int partId);
+ long getFileTransferTransferOffset(int partId, String callingPackage);
- void setFileTransferStatus(int partId, int transferStatus);
+ void setFileTransferStatus(int partId, int transferStatus, String callingPackage);
- int getFileTransferStatus(int partId);
+ int getFileTransferStatus(int partId, String callingPackage);
- void setFileTransferWidth(int partId, int width);
+ void setFileTransferWidth(int partId, int width, String callingPackage);
- int getFileTransferWidth(int partId);
+ int getFileTransferWidth(int partId, String callingPackage);
- void setFileTransferHeight(int partId, int height);
+ void setFileTransferHeight(int partId, int height, String callingPackage);
- int getFileTransferHeight(int partId);
+ int getFileTransferHeight(int partId, String callingPackage);
- void setFileTransferLength(int partId, long length);
+ void setFileTransferLength(int partId, long length, String callingPackage);
- long getFileTransferLength(int partId);
+ long getFileTransferLength(int partId, String callingPackage);
- void setFileTransferPreviewUri(int partId, in Uri uri);
+ void setFileTransferPreviewUri(int partId, in Uri uri, String callingPackage);
- Uri getFileTransferPreviewUri(int partId);
+ Uri getFileTransferPreviewUri(int partId, String callingPackage);
- void setFileTransferPreviewType(int partId, String type);
+ void setFileTransferPreviewType(int partId, String type, String callingPackage);
- String getFileTransferPreviewType(int partId);
+ String getFileTransferPreviewType(int partId, String callingPackage);
/////////////////////////
// RcsEvent APIs
/////////////////////////
- int createGroupThreadNameChangedEvent(long timestamp, int threadId, int originationParticipantId, String newName);
+ int createGroupThreadNameChangedEvent(long timestamp, int threadId, int originationParticipantId, String newName, String callingPackage);
- int createGroupThreadIconChangedEvent(long timestamp, int threadId, int originationParticipantId, in Uri newIcon);
+ int createGroupThreadIconChangedEvent(long timestamp, int threadId, int originationParticipantId, in Uri newIcon, String callingPackage);
- int createGroupThreadParticipantJoinedEvent(long timestamp, int threadId, int originationParticipantId, int participantId);
+ int createGroupThreadParticipantJoinedEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
- int createGroupThreadParticipantLeftEvent(long timestamp, int threadId, int originationParticipantId, int participantId);
+ int createGroupThreadParticipantLeftEvent(long timestamp, int threadId, int originationParticipantId, int participantId, String callingPackage);
- int createParticipantAliasChangedEvent(long timestamp, int participantId, String newAlias);
+ int createParticipantAliasChangedEvent(long timestamp, int participantId, String newAlias, String callingPackage);
}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 0ad6096..71ea881 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1586,7 +1586,7 @@
int getCardIdForDefaultEuicc(int subId, String callingPackage);
/**
- * Gets information about currently inserted UICCs and enabled eUICCs.
+ * Gets information about currently inserted UICCs and eUICCs.
* <p>
* Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
* <p>
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index 89d32ab..658c3ed 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -49,9 +49,7 @@
RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
RcsGroupThreadIconChangedEvent iconChangedEvent =
- iconChangedEventDescriptor.createRcsEvent();
-
-
+ iconChangedEventDescriptor.createRcsEvent(null);
assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 726b9cd..9fe67ad 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsGroupThreadNameChangedEvent nameChangedEvent =
- nameChangedEventDescriptor.createRcsEvent();
+ nameChangedEventDescriptor.createRcsEvent(null);
assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index a109310..18d5621 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -47,7 +47,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
- participantJoinedEventDescriptor.createRcsEvent();
+ participantJoinedEventDescriptor.createRcsEvent(null);
assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index de2688c..53a6bba 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantLeftEvent participantLeftEvent =
- participantLeftEventDescriptor.createRcsEvent();
+ participantLeftEventDescriptor.createRcsEvent(null);
assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 5724054..dcf68ff 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -47,7 +47,7 @@
.createFromParcel(parcel);
RcsParticipantAliasChangedEvent aliasChangedEvent =
- aliasChangedEventDescriptor.createRcsEvent();
+ aliasChangedEventDescriptor.createRcsEvent(null);
assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
index beb4f8a..551a228 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -33,7 +33,7 @@
@Test
public void testCanUnparcel() {
- RcsParticipant rcsParticipant = new RcsParticipant(1);
+ RcsParticipant rcsParticipant = new RcsParticipant(null, 1);
RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
.setThreadType(THREAD_TYPE_GROUP)
.setParticipant(rcsParticipant)
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index 3b2e34a..07525a6 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -23,6 +23,7 @@
"androidx.test.rules",
"frameworks-net-testutils",
"junit",
+ "mockito-target-minus-junit4",
],
libs: [
"android.test.base.stubs",
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
new file mode 100644
index 0000000..eed7159f
--- /dev/null
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CaptivePortalTest {
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ private static final String TEST_PACKAGE_NAME = "com.google.android.test";
+
+ private final class MyCaptivePortalImpl extends ICaptivePortal.Stub {
+ int mCode = -1;
+ String mPackageName = null;
+
+ @Override
+ public void appResponse(final int response) throws RemoteException {
+ mCode = response;
+ }
+
+ @Override
+ public void logEvent(int eventId, String packageName) throws RemoteException {
+ mCode = eventId;
+ mPackageName = packageName;
+ }
+ }
+
+ private interface TestFunctor {
+ void useCaptivePortal(CaptivePortal o);
+ }
+
+ private MyCaptivePortalImpl runCaptivePortalTest(TestFunctor f) {
+ final MyCaptivePortalImpl cp = new MyCaptivePortalImpl();
+ f.useCaptivePortal(new CaptivePortal(cp.asBinder()));
+ return cp;
+ }
+
+ @Test
+ public void testReportCaptivePortalDismissed() {
+ final MyCaptivePortalImpl result =
+ runCaptivePortalTest(c -> c.reportCaptivePortalDismissed());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_DISMISSED);
+ }
+
+ @Test
+ public void testIgnoreNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.ignoreNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_UNWANTED);
+ }
+
+ @Test
+ public void testUseNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.useNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
+ }
+
+ @Test
+ public void testLogEvent() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(
+ MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
+ TEST_PACKAGE_NAME));
+ assertEquals(result.mCode, MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
+ assertEquals(result.mPackageName, TEST_PACKAGE_NAME);
+ }
+}
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index ad76388..6bc7c1b 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -33,6 +33,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
@@ -585,4 +587,20 @@
nc2.set(nc1); // Overwrites, as opposed to combineCapabilities
assertEquals(nc1, nc2);
}
+
+ @Test
+ public void testGetTransportTypes() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ nc.addTransportType(TRANSPORT_CELLULAR);
+ nc.addTransportType(TRANSPORT_WIFI);
+ nc.addTransportType(TRANSPORT_VPN);
+ nc.addTransportType(TRANSPORT_TEST);
+
+ final int[] transportTypes = nc.getTransportTypes();
+ assertEquals(4, transportTypes.length);
+ assertEquals(TRANSPORT_CELLULAR, transportTypes[0]);
+ assertEquals(TRANSPORT_WIFI, transportTypes[1]);
+ assertEquals(TRANSPORT_VPN, transportTypes[2]);
+ assertEquals(TRANSPORT_TEST, transportTypes[3]);
+ }
}
diff --git a/tests/net/common/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java
index 0bee7cd..bef66b2 100644
--- a/tests/net/common/java/android/net/NetworkTest.java
+++ b/tests/net/common/java/android/net/NetworkTest.java
@@ -155,4 +155,12 @@
private static <T> void assertNotEqual(T t1, T t2) {
assertFalse(Objects.equals(t1, t2));
}
+
+ @Test
+ public void testGetPrivateDnsBypassingCopy() {
+ final Network copy = mNetwork.getPrivateDnsBypassingCopy();
+ assertEquals(mNetwork.netId, copy.netId);
+ assertNotEqual(copy.netId, copy.getNetIdForResolv());
+ assertNotEqual(mNetwork.getNetIdForResolv(), copy.getNetIdForResolv());
+ }
}
diff --git a/tests/net/common/java/android/net/StaticIpConfigurationTest.java b/tests/net/common/java/android/net/StaticIpConfigurationTest.java
index 8449ca7..5096be2 100644
--- a/tests/net/common/java/android/net/StaticIpConfigurationTest.java
+++ b/tests/net/common/java/android/net/StaticIpConfigurationTest.java
@@ -31,7 +31,9 @@
import org.junit.runner.RunWith;
import java.net.InetAddress;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
@RunWith(AndroidJUnit4.class)
@@ -46,6 +48,7 @@
private static final InetAddress DNS2 = IpAddress("8.8.4.4");
private static final InetAddress DNS3 = IpAddress("4.2.2.2");
private static final String IFACE = "eth0";
+ private static final String FAKE_DOMAINS = "google.com";
private static InetAddress IpAddress(String addr) {
return InetAddress.parseNumericAddress(addr);
@@ -69,7 +72,7 @@
s.dnsServers.add(DNS1);
s.dnsServers.add(DNS2);
s.dnsServers.add(DNS3);
- s.domains = "google.com";
+ s.domains = FAKE_DOMAINS;
return s;
}
@@ -178,8 +181,8 @@
expected.addDnsServer(DNS3);
assertEquals(expected, s.toLinkProperties(IFACE));
- s.domains = "google.com";
- expected.setDomains("google.com");
+ s.domains = FAKE_DOMAINS;
+ expected.setDomains(FAKE_DOMAINS);
assertEquals(expected, s.toLinkProperties(IFACE));
s.gateway = null;
@@ -218,4 +221,53 @@
StaticIpConfiguration s2 = passThroughParcel(s);
assertEquals(s, s2);
}
+
+ @Test
+ public void testBuilder() {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<>();
+ dnsServers.add(DNS1);
+
+ final StaticIpConfiguration s = new StaticIpConfiguration.Builder()
+ .setIpAddress(ADDR)
+ .setGateway(GATEWAY)
+ .setDomains(FAKE_DOMAINS)
+ .setDnsServers(dnsServers)
+ .build();
+
+ assertEquals(s.ipAddress, s.getIpAddress());
+ assertEquals(ADDR, s.getIpAddress());
+ assertEquals(s.gateway, s.getGateway());
+ assertEquals(GATEWAY, s.getGateway());
+ assertEquals(s.domains, s.getDomains());
+ assertEquals(FAKE_DOMAINS, s.getDomains());
+ assertTrue(s.dnsServers.equals(s.getDnsServers()));
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+ }
+
+ @Test
+ public void testAddDnsServers() {
+ final StaticIpConfiguration s = new StaticIpConfiguration((StaticIpConfiguration) null);
+ checkEmpty(s);
+
+ s.addDnsServer(DNS1);
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+
+ s.addDnsServer(DNS2);
+ s.addDnsServer(DNS3);
+ assertEquals(3, s.getDnsServers().size());
+ assertEquals(DNS2, s.getDnsServers().get(1));
+ assertEquals(DNS3, s.getDnsServers().get(2));
+ }
+
+ @Test
+ public void testGetRoutes() {
+ final StaticIpConfiguration s = makeTestObject();
+ final List<RouteInfo> routeInfoList = s.getRoutes(IFACE);
+
+ assertEquals(2, routeInfoList.size());
+ assertEquals(new RouteInfo(ADDR, (InetAddress) null, IFACE), routeInfoList.get(0));
+ assertEquals(new RouteInfo((IpPrefix) null, GATEWAY, IFACE), routeInfoList.get(1));
+ }
}
diff --git a/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
new file mode 100644
index 0000000..8d055c9
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.metrics;
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfProgramEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasFlag(flag: Int) = (this and (1 shl flag)) != 0
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfProgramEvent = ApfProgramEvent.Builder()
+ .setLifetime(1)
+ .setActualLifetime(2)
+ .setFilteredRas(3)
+ .setCurrentRas(4)
+ .setProgramLength(5)
+ .setFlags(true, true)
+ .build()
+
+ assertEquals(1, apfProgramEvent.lifetime)
+ assertEquals(2, apfProgramEvent.actualLifetime)
+ assertEquals(3, apfProgramEvent.filteredRas)
+ assertEquals(4, apfProgramEvent.currentRas)
+ assertEquals(5, apfProgramEvent.programLength)
+ assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags)
+
+ testParcel(apfProgramEvent, 6)
+ }
+
+ @Test
+ fun testFlagsFor() {
+ var flags = ApfProgramEvent.flagsFor(false, false)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, false)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(false, true)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, true)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
new file mode 100644
index 0000000..f8eb40c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfStatsTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfStats = ApfStats.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setReceivedRas(1)
+ .setMatchingRas(2)
+ .setDroppedRas(3)
+ .setZeroLifetimeRas(4)
+ .setParseErrors(5)
+ .setProgramUpdates(6)
+ .setProgramUpdatesAll(7)
+ .setProgramUpdatesAllowingMulticast(8)
+ .setMaxProgramSize(9)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, apfStats.durationMs)
+ assertEquals(1, apfStats.receivedRas)
+ assertEquals(2, apfStats.matchingRas)
+ assertEquals(3, apfStats.droppedRas)
+ assertEquals(4, apfStats.zeroLifetimeRas)
+ assertEquals(5, apfStats.parseErrors)
+ assertEquals(6, apfStats.programUpdates)
+ assertEquals(7, apfStats.programUpdatesAll)
+ assertEquals(8, apfStats.programUpdatesAllowingMulticast)
+ assertEquals(9, apfStats.maxProgramSize)
+
+ testParcel(apfStats, 10)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
new file mode 100644
index 0000000..36e9f8c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FAKE_MESSAGE = "test"
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class DhcpClientEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val dhcpClientEvent = DhcpClientEvent.Builder()
+ .setMsg(FAKE_MESSAGE)
+ .setDurationMs(Integer.MAX_VALUE)
+ .build()
+
+ assertEquals(FAKE_MESSAGE, dhcpClientEvent.msg)
+ assertEquals(Integer.MAX_VALUE, dhcpClientEvent.durationMs)
+
+ testParcel(dhcpClientEvent, 2)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
index e191953..e9d5e6d 100644
--- a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
+++ b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
@@ -13,9 +13,7 @@
import org.junit.runner.RunWith
private const val TEST_ERROR_CODE = 12345
-/**
- * DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java)
- */
+//DHCP Optional Type: DHCP Subnet Mask (Copy from DhcpPacket.java due to it's protected)
private const val DHCP_SUBNET_MASK = 1
@RunWith(AndroidJUnit4::class)
diff --git a/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
new file mode 100644
index 0000000..d4780d3
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 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.metrics;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.BitUtils;
+
+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;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityLogTest {
+ private static final int FAKE_NET_ID = 100;
+ private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI);
+ private static final long FAKE_TIME_STAMP = System.currentTimeMillis();
+ private static final String FAKE_INTERFACE_NAME = "test";
+ private static final IpReachabilityEvent FAKE_EV =
+ new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+
+ @Mock IIpConnectivityMetrics mMockService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testLoggingEvents() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ assertTrue(logger.log(FAKE_EV));
+ assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV));
+ assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV));
+ assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI,
+ FAKE_INTERFACE_NAME)));
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(6);
+ assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1));
+ assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(2));
+ assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(3));
+ assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME),
+ got.get(4));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID,
+ TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5));
+ }
+
+ @Test
+ public void testLoggingEventsWithMultipleCallers() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ final int nCallers = 10;
+ final int nEvents = 10;
+ for (int n = 0; n < nCallers; n++) {
+ final int i = n;
+ new Thread() {
+ public void run() {
+ for (int j = 0; j < nEvents; j++) {
+ assertTrue(logger.log(makeExpectedEvent(
+ FAKE_TIME_STAMP + i * 100 + j,
+ FAKE_NET_ID + i * 100 + j,
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR,
+ FAKE_INTERFACE_NAME)));
+ }
+ }
+ }.start();
+ }
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
+ Collections.sort(got, EVENT_COMPARATOR);
+ Iterator<ConnectivityMetricsEvent> iter = got.iterator();
+ for (int i = 0; i < nCallers; i++) {
+ for (int j = 0; j < nEvents; j++) {
+ final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j;
+ final int expectedNetId = FAKE_NET_ID + i * 100 + j;
+ final long expectedTransports =
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR;
+ assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId,
+ expectedTransports, FAKE_INTERFACE_NAME), iter.next());
+ }
+ }
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+ ArgumentCaptor<ConnectivityMetricsEvent> captor =
+ ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+ verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
+ return captor.getAllValues();
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+ return verifyEvents(n, 10);
+ }
+
+
+ private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports,
+ String ifname) {
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = timestamp;
+ ev.data = FAKE_EV;
+ ev.netId = netId;
+ ev.transports = transports;
+ ev.ifname = ifname;
+ return ev;
+ }
+
+ /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+ private void assertEventsEqual(ConnectivityMetricsEvent expected,
+ ConnectivityMetricsEvent got) {
+ assertEquals(expected.data, got.data);
+ assertEquals(expected.timestamp, got.timestamp);
+ assertEquals(expected.netId, got.netId);
+ assertEquals(expected.transports, got.transports);
+ assertEquals(expected.ifname, got.ifname);
+ }
+
+ static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
+ Comparator.comparingLong((ev) -> ev.timestamp);
+}
diff --git a/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
new file mode 100644
index 0000000..5144ca5
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpManagerEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpManagerEvent.PROVISIONING_OK..IpManagerEvent.ERROR_INTERFACE_NOT_FOUND).forEach {
+ val ipManagerEvent = IpManagerEvent(it, Long.MAX_VALUE)
+ assertEquals(it, ipManagerEvent.eventType)
+ assertEquals(Long.MAX_VALUE, ipManagerEvent.durationMs)
+
+ testParcel(ipManagerEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
new file mode 100644
index 0000000..d76ebf6
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpReachabilityEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpReachabilityEvent.PROBE..IpReachabilityEvent.PROVISIONING_LOST_ORGANIC).forEach {
+ val ipReachabilityEvent = IpReachabilityEvent(it)
+ assertEquals(it, ipReachabilityEvent.eventType)
+
+ testParcel(ipReachabilityEvent, 1)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/NetworkEventTest.kt b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
new file mode 100644
index 0000000..8b52e81
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (NetworkEvent.NETWORK_CONNECTED..NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY).forEach {
+ var networkEvent = NetworkEvent(it)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(0, networkEvent.durationMs)
+
+ networkEvent = NetworkEvent(it, Long.MAX_VALUE)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(Long.MAX_VALUE, networkEvent.durationMs)
+
+ testParcel(networkEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/RaEventTest.kt b/tests/net/common/java/android/net/metrics/RaEventTest.kt
new file mode 100644
index 0000000..f38d328
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/RaEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val NO_LIFETIME: Long = -1L
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class RaEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ var raEvent = RaEvent.Builder().build()
+ assertEquals(NO_LIFETIME, raEvent.routerLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixValidLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixPreferredLifetime)
+ assertEquals(NO_LIFETIME, raEvent.routeInfoLifetime)
+ assertEquals(NO_LIFETIME, raEvent.rdnssLifetime)
+ assertEquals(NO_LIFETIME, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(1)
+ .updatePrefixValidLifetime(2)
+ .updatePrefixPreferredLifetime(3)
+ .updateRouteInfoLifetime(4)
+ .updateRdnssLifetime(5)
+ .updateDnsslLifetime(6)
+ .build()
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(Long.MIN_VALUE)
+ .updateRouterLifetime(Long.MAX_VALUE)
+ .build()
+ assertEquals(Long.MIN_VALUE, raEvent.routerLifetime)
+
+ raEvent = RaEvent(1, 2, 3, 4, 5, 6)
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ testParcel(raEvent, 6)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
new file mode 100644
index 0000000..c0cef8f
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 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.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import java.lang.reflect.Modifier
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FIRST_VALIDATION: Int = 1 shl 8
+private const val REVALIDATION: Int = 2 shl 8
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ValidationProbeEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasType(type: Int) = (type and this) == type
+
+ @Test
+ fun testBuilderAndParcel() {
+ var validationProbeEvent = ValidationProbeEvent.Builder()
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, false).build()
+
+ assertTrue(validationProbeEvent.probeType hasType REVALIDATION)
+
+ validationProbeEvent = ValidationProbeEvent.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, true)
+ .setReturnCode(ValidationProbeEvent.DNS_SUCCESS)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, validationProbeEvent.durationMs)
+ assertTrue(validationProbeEvent.probeType hasType ValidationProbeEvent.PROBE_DNS)
+ assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION)
+ assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode)
+
+ testParcel(validationProbeEvent, 3)
+ }
+
+ @Test
+ fun testGetProbeName() {
+ val probeFields = ValidationProbeEvent::class.java.declaredFields.filter {
+ it.type == Int::class.javaPrimitiveType
+ && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
+ && it.name.contains("PROBE")
+ }
+
+ probeFields.forEach {
+ val intValue = it.getInt(null)
+ val stringValue = ValidationProbeEvent.getProbeName(intValue)
+ assertEquals(it.name, stringValue)
+ }
+
+ }
+}
diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java
index 18c6768..8ff2de9 100644
--- a/tests/net/java/android/net/IpMemoryStoreTest.java
+++ b/tests/net/java/android/net/IpMemoryStoreTest.java
@@ -16,10 +16,26 @@
package android.net;
-import static org.mockito.ArgumentMatchers.any;
+import static org.junit.Assert.assertEquals;
+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.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.IOnStatusListener;
+import android.net.ipmemorystore.NetworkAttributes;
+import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.net.ipmemorystore.Status;
+import android.os.RemoteException;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -27,28 +43,57 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpMemoryStoreTest {
+ private static final String TAG = IpMemoryStoreTest.class.getSimpleName();
+ private static final String TEST_CLIENT_ID = "testClientId";
+ private static final String TEST_DATA_NAME = "testData";
+ private static final String TEST_OTHER_DATA_NAME = TEST_DATA_NAME + "Other";
+ private static final byte[] TEST_BLOB_DATA = new byte[] { -3, 6, 8, -9, 12,
+ -128, 0, 89, 112, 91, -34 };
+ private static final NetworkAttributes TEST_NETWORK_ATTRIBUTES = buildTestNetworkAttributes(
+ "hint", 219);
+
@Mock
Context mMockContext;
@Mock
NetworkStackClient mNetworkStackClient;
@Mock
IIpMemoryStore mMockService;
+ @Mock
+ IOnStatusListener mIOnStatusListener;
IpMemoryStore mStore;
+ @Captor
+ ArgumentCaptor<IIpMemoryStoreCallbacks> mCbCaptor;
+ @Captor
+ ArgumentCaptor<NetworkAttributesParcelable> mNapCaptor;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- doAnswer(invocation -> {
- ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
- .onIpMemoryStoreFetched(mMockService);
- return null;
- }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ }
+
+ private void startIpMemoryStore(boolean supplyService) {
+ if (supplyService) {
+ doAnswer(invocation -> {
+ ((IIpMemoryStoreCallbacks) invocation.getArgument(0))
+ .onIpMemoryStoreFetched(mMockService);
+ return null;
+ }).when(mNetworkStackClient).fetchIpMemoryStore(any());
+ } else {
+ doNothing().when(mNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture());
+ }
mStore = new IpMemoryStore(mMockContext) {
@Override
protected NetworkStackClient getNetworkStackClient() {
@@ -57,24 +102,228 @@
};
}
- @Test
- public void testNetworkAttributes() {
- // TODO : implement this
+ private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) {
+ return new NetworkAttributes.Builder()
+ .setGroupHint(hint)
+ .setMtu(mtu)
+ .build();
}
@Test
- public void testPrivateData() {
- // TODO : implement this
+ public void testNetworkAttributes() throws Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeNetworkAttributes(eq(l2Key),
+ mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+
+ verify(mMockService, times(1)).retrieveNetworkAttributes(eq(l2Key), any());
}
@Test
- public void testFindL2Key() {
- // TODO : implement this
+ public void testPrivateData() throws RemoteException {
+ startIpMemoryStore(true);
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ verify(mMockService, times(1)).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+ verify(mMockService, times(1)).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
}
@Test
- public void testIsSameNetwork() {
- // TODO : implement this
+ public void testFindL2Key()
+ throws UnknownHostException, RemoteException, Exception {
+ startIpMemoryStore(true);
+ final String l2Key = "fakeKey";
+
+ mStore.findL2Key(TEST_NETWORK_ATTRIBUTES,
+ (status, key) -> {
+ assertTrue("Retrieve network sameness not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ });
+ verify(mMockService, times(1)).findL2Key(mNapCaptor.capture(), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
}
+ @Test
+ public void testIsSameNetwork() throws UnknownHostException, RemoteException {
+ startIpMemoryStore(true);
+ final String l2Key1 = "fakeKey1";
+ final String l2Key2 = "fakeKey2";
+
+ mStore.isSameNetwork(l2Key1, l2Key2,
+ (status, answer) -> {
+ assertFalse("Retrieve network sameness suspiciously successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(Status.ERROR_ILLEGAL_ARGUMENT, status.resultCode);
+ assertNull(answer);
+ });
+ verify(mMockService, times(1)).isSameNetwork(eq(l2Key1), eq(l2Key2), any());
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequests() throws Exception {
+ startIpMemoryStore(false);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // get ipms service ready
+ mCbCaptor.getValue().onIpMemoryStoreFetched(mMockService);
+
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).retrieveNetworkAttributes(eq(l2Key), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsWithException() throws Exception {
+ startIpMemoryStore(true);
+ doThrow(RemoteException.class).when(mMockService).retrieveNetworkAttributes(any(), any());
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(TEST_NETWORK_ATTRIBUTES, attr);
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if the remote exception
+ // occurs when calling one or more requests
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(), any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
+
+ @Test
+ public void testEnqueuedIpMsRequestsCallbackFunctionWithException() throws Exception {
+ startIpMemoryStore(true);
+
+ final Blob b = new Blob();
+ b.data = TEST_BLOB_DATA;
+ final String l2Key = "fakeKey";
+
+ // enqueue multiple ipms requests
+ mStore.storeNetworkAttributes(l2Key, TEST_NETWORK_ATTRIBUTES,
+ status -> {
+ assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
+ });
+ mStore.retrieveNetworkAttributes(l2Key,
+ (status, key, attr) -> {
+ throw new RuntimeException("retrieveNetworkAttributes test");
+ });
+ mStore.storeBlob(l2Key, TEST_CLIENT_ID, TEST_DATA_NAME, b,
+ status -> {
+ throw new RuntimeException("storeBlob test");
+ });
+ mStore.retrieveBlob(l2Key, TEST_CLIENT_ID, TEST_OTHER_DATA_NAME,
+ (status, key, name, data) -> {
+ assertTrue("Retrieve blob status not successful : " + status.resultCode,
+ status.isSuccess());
+ assertEquals(l2Key, key);
+ assertEquals(name, TEST_DATA_NAME);
+ assertTrue(Arrays.equals(b.data, data.data));
+ });
+
+ // verify the rest of the queue is still processed in order even if when one or more
+ // callback throw the remote exception
+ InOrder inOrder = inOrder(mMockService);
+
+ inOrder.verify(mMockService).storeNetworkAttributes(eq(l2Key), mNapCaptor.capture(),
+ any());
+ inOrder.verify(mMockService).storeBlob(eq(l2Key), eq(TEST_CLIENT_ID), eq(TEST_DATA_NAME),
+ eq(b), any());
+ inOrder.verify(mMockService).retrieveBlob(eq(l2Key), eq(TEST_CLIENT_ID),
+ eq(TEST_OTHER_DATA_NAME), any());
+ assertEquals(TEST_NETWORK_ATTRIBUTES, new NetworkAttributes(mNapCaptor.getValue()));
+ }
}
diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
index d8f01e9..f9dbdc7 100644
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
@@ -55,9 +55,10 @@
mDhcpResults.serverAddress = (Inet4Address) parseNumericAddress("192.168.44.44");
mDhcpResults.vendorInfo = "TEST_VENDOR_INFO";
mDhcpResults.leaseDuration = 3600;
+ mDhcpResults.serverHostName = "dhcp.example.com";
mDhcpResults.mtu = 1450;
// Any added DhcpResults field must be included in equals() to be tested properly
- assertFieldCountEquals(8, DhcpResults.class);
+ assertFieldCountEquals(9, DhcpResults.class);
}
@Test
@@ -101,6 +102,12 @@
doDhcpResultsParcelUnparcelTest();
}
+ @Test
+ public void testParcelUnparcelDhcpResults_NullServerHostName() {
+ mDhcpResults.serverHostName = null;
+ doDhcpResultsParcelUnparcelTest();
+ }
+
private void doDhcpResultsParcelUnparcelTest() {
final DhcpResults unparceled = fromStableParcelable(toStableParcelable(mDhcpResults));
assertEquals(mDhcpResults, unparceled);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 64672bd8a..3c5bb6a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
@@ -103,6 +105,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -146,6 +149,7 @@
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
+import android.os.Binder;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -272,6 +276,7 @@
@Mock IDnsResolver mMockDnsResolver;
@Mock INetd mMockNetd;
@Mock NetworkStackClient mNetworkStack;
+ @Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
@@ -357,7 +362,12 @@
public Resources getResources() {
return mResources;
}
- }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+ }
public void waitForIdle(int timeoutMsAsInt) {
long timeoutMs = timeoutMsAsInt;
@@ -557,6 +567,16 @@
protected void preventAutomaticReconnect() {
mPreventReconnectReceived.open();
}
+
+ @Override
+ protected void addKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Add keepalive packet filter.");
+ }
+
+ @Override
+ protected void removeKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Remove keepalive packet filter.");
+ }
};
assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
@@ -1232,6 +1252,7 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
+ mockDefaultPackages();
FakeSettingsProvider.clearSettingsProvider();
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1284,7 +1305,24 @@
FakeSettingsProvider.clearSettingsProvider();
}
- private static int transportToLegacyType(int transport) {
+ private void mockDefaultPackages() throws Exception {
+ final String testPackageName = mContext.getPackageName();
+ final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
+ testPackageName, PackageManager.GET_PERMISSIONS);
+ when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
+ new String[] {testPackageName});
+ when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
+ eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ Arrays.asList(new PackageInfo[] {
+ buildPackageInfo(/* SYSTEM */ false, APP1_UID),
+ buildPackageInfo(/* SYSTEM */ false, APP2_UID),
+ buildPackageInfo(/* SYSTEM */ false, VPN_UID)
+ }));
+ }
+
+ private static int transportToLegacyType(int transport) {
switch (transport) {
case TRANSPORT_ETHERNET:
return TYPE_ETHERNET;
@@ -3816,6 +3854,9 @@
networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
testFactory.waitForRequests();
+ // unregister network callback - a no-op, but should not fail
+ mCm.unregisterNetworkCallback(networkCallback);
+
testFactory.unregister();
handlerThread.quit();
}
@@ -4891,7 +4932,10 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
- // CS tells netd about the empty DNS config for this network.
+
+ verify(mMockDnsResolver, times(1)).createNetworkCache(
+ eq(mCellNetworkAgent.getNetwork().netId));
+ // CS tells dnsresolver about the empty DNS config for this network.
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
reset(mMockDnsResolver);
@@ -4975,6 +5019,8 @@
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
+ verify(mMockDnsResolver, times(1)).createNetworkCache(
+ eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
mResolverParamsParcelCaptor.capture());
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -5848,12 +5894,17 @@
cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
+ reset(mMockNetd);
when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
.thenReturn(getClatInterfaceConfig(myIpv4));
// Connect with ipv6 link properties. Expect prefix discovery to be started.
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(true);
+
+ verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
+ verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
+
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
@@ -6045,7 +6096,7 @@
verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, times(1))
- .clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId));
+ .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi
ConditionVariable cv = waitForConnectivityBroadcasts(1);
@@ -6169,7 +6220,6 @@
}
@Test
- @Ignore
public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6196,7 +6246,6 @@
}
@Test
- @Ignore
public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6210,7 +6259,6 @@
}
@Test
- @Ignore
public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
throws Exception {
LinkProperties lp = new LinkProperties();
@@ -6226,7 +6274,6 @@
}
@Test
- @Ignore
public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6276,7 +6323,6 @@
}
@Test
- @Ignore
public void testUidUpdateChangesInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index d5b2c87..3a07166 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -21,11 +21,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -59,16 +56,11 @@
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;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -98,48 +90,6 @@
}
@Test
- public void testLoggingEvents() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- assertTrue(logger.log(1, FAKE_EV));
- assertTrue(logger.log(2, FAKE_EV));
- assertTrue(logger.log(3, FAKE_EV));
-
- List<ConnectivityMetricsEvent> got = verifyEvents(3);
- assertEventsEqual(expectedEvent(1), got.get(0));
- assertEventsEqual(expectedEvent(2), got.get(1));
- assertEventsEqual(expectedEvent(3), got.get(2));
- }
-
- @Test
- public void testLoggingEventsWithMultipleCallers() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- final int nCallers = 10;
- final int nEvents = 10;
- for (int n = 0; n < nCallers; n++) {
- final int i = n;
- new Thread() {
- public void run() {
- for (int j = 0; j < nEvents; j++) {
- assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
- }
- }
- }.start();
- }
-
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
- Collections.sort(got, EVENT_COMPARATOR);
- Iterator<ConnectivityMetricsEvent> iter = got.iterator();
- for (int i = 0; i < nCallers; i++) {
- for (int j = 0; j < nEvents; j++) {
- int expectedTimestamp = 1 + i * 100 + j;
- assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
- }
- }
- }
-
- @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -653,16 +603,7 @@
return nai;
}
- List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
- ArgumentCaptor<ConnectivityMetricsEvent> captor =
- ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
- verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
- return captor.getAllValues();
- }
- List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
- return verifyEvents(n, 10);
- }
static void verifySerialization(String want, String output) {
try {
@@ -674,28 +615,4 @@
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s).append("\n");
- }
- return b.toString();
- }
-
- static ConnectivityMetricsEvent expectedEvent(int timestamp) {
- ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
- ev.timestamp = timestamp;
- ev.data = FAKE_EV;
- return ev;
- }
-
- /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
- static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
- assertEquals(expected.timestamp, got.timestamp);
- assertEquals(expected.data, got.data);
- }
-
- static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
- Comparator.comparingLong((ev) -> ev.timestamp);
}
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index a83faf3..fb84611 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.connectivity.ipmemorystore;
+package com.android.server.net.ipmemorystore;
import static org.junit.Assert.assertEquals;
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index c856cc3..e883c6b 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -29,6 +29,7 @@
FLAG_BLACKLIST = "blacklist"
FLAG_GREYLIST_MAX_O = "greylist-max-o"
FLAG_GREYLIST_MAX_P = "greylist-max-p"
+FLAG_GREYLIST_MAX_Q = "greylist-max-q"
FLAG_CORE_PLATFORM_API = "core-platform-api"
FLAG_PUBLIC_API = "public-api"
FLAG_SYSTEM_API = "system-api"
@@ -41,6 +42,7 @@
FLAG_BLACKLIST,
FLAG_GREYLIST_MAX_O,
FLAG_GREYLIST_MAX_P,
+ FLAG_GREYLIST_MAX_Q,
]
ALL_FLAGS = FLAGS_API_LIST + [
FLAG_CORE_PLATFORM_API,
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java
index ef29146..5a5703e 100644
--- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/SignatureBuilder.java
@@ -20,12 +20,13 @@
import static javax.tools.Diagnostic.Kind.ERROR;
import static javax.tools.Diagnostic.Kind.WARNING;
-import android.annotation.UnsupportedAppUsage;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.sun.tools.javac.code.Type;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -69,6 +70,7 @@
public SignatureBuilderException(String message) {
super(message);
}
+
public void report(Element offendingElement) {
mMessager.printMessage(ERROR, getMessage(), offendingElement);
}
@@ -153,7 +155,7 @@
/**
* Get the signature for an executable, either a method or a constructor.
*
- * @param name "<init>" for constructor, else the method name
+ * @param name "<init>" for constructor, else the method name
* @param method The executable element in question.
*/
private String getExecutableSignature(CharSequence name, ExecutableElement method)
@@ -191,8 +193,13 @@
return sig.toString();
}
- public String buildSignature(Element element) {
- UnsupportedAppUsage uba = element.getAnnotation(UnsupportedAppUsage.class);
+ /**
+ * Creates the signature for an annotated element.
+ *
+ * @param annotationType type of annotation being processed.
+ * @param element element for which we want to create a signature.
+ */
+ public String buildSignature(Class<? extends Annotation> annotationType, Element element) {
try {
String signature;
switch (element.getKind()) {
@@ -208,18 +215,35 @@
default:
return null;
}
- // if we have an expected signature on the annotation, warn if it doesn't match.
- if (!Strings.isNullOrEmpty(uba.expectedSignature())) {
- if (!signature.equals(uba.expectedSignature())) {
- mMessager.printMessage(
- WARNING,
- String.format("Expected signature doesn't match generated signature.\n"
- + " Expected: %s\n Generated: %s",
- uba.expectedSignature(), signature),
- element);
- }
+ // Obtain annotation objects
+ Annotation annotation = element.getAnnotation(annotationType);
+ if (annotation == null) {
+ throw new IllegalStateException(
+ "Element doesn't have any UnsupportedAppUsage annotation");
}
- return signature;
+ try {
+ Method expectedSignatureMethod = annotationType.getMethod("expectedSignature");
+ // If we have an expected signature on the annotation, warn if it doesn't match.
+ String expectedSignature = expectedSignatureMethod.invoke(annotation).toString();
+ if (!Strings.isNullOrEmpty(expectedSignature)) {
+ if (!signature.equals(expectedSignature)) {
+ mMessager.printMessage(
+ WARNING,
+ String.format(
+ "Expected signature doesn't match generated signature.\n"
+ + " Expected: %s\n Generated: %s",
+ expectedSignature, signature),
+ element);
+ }
+ }
+ return signature;
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(
+ "Annotation type does not have expectedSignature parameter", e);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new IllegalStateException(
+ "Could not get expectedSignature parameter for annotation", e);
+ }
} catch (SignatureBuilderException problem) {
problem.report(element);
return null;
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
index d368136..5bb956a 100644
--- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
@@ -18,9 +18,8 @@
import static javax.tools.StandardLocation.CLASS_OUTPUT;
-import android.annotation.UnsupportedAppUsage;
-
import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Pair;
@@ -28,6 +27,7 @@
import java.io.IOException;
import java.io.PrintStream;
+import java.lang.annotation.Annotation;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
@@ -47,14 +47,14 @@
/**
* Annotation processor for {@link UnsupportedAppUsage} annotations.
*
- * This processor currently outputs two things:
- * 1. A greylist.txt containing dex signatures of all annotated elements.
- * 2. A CSV file with a mapping of dex signatures to corresponding source positions.
+ * This processor currently outputs a CSV file with a mapping of dex signatures to corresponding
+ * source positions.
*
- * The first will be used at a later stage of the build to add access flags to the dex file. The
- * second is used for automating updates to the annotations themselves.
+ * This is used for automating updates to the annotations themselves.
*/
-@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage"})
+@SupportedAnnotationTypes({"android.annotation.UnsupportedAppUsage",
+ "dalvik.annotation.compat.UnsupportedAppUsage"
+})
public class UnsupportedAppUsageProcessor extends AbstractProcessor {
// Package name for writing output. Output will be written to the "class output" location within
@@ -62,6 +62,13 @@
private static final String PACKAGE = "unsupportedappusage";
private static final String INDEX_CSV = "unsupportedappusage_index.csv";
+ private static final ImmutableSet<Class<? extends Annotation>> SUPPORTED_ANNOTATIONS =
+ ImmutableSet.of(android.annotation.UnsupportedAppUsage.class,
+ dalvik.annotation.compat.UnsupportedAppUsage.class);
+ private static final ImmutableSet<String> SUPPORTED_ANNOTATION_NAMES =
+ SUPPORTED_ANNOTATIONS.stream().map(annotation -> annotation.getCanonicalName()).collect(
+ ImmutableSet.toImmutableSet());
+
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
@@ -92,8 +99,7 @@
private AnnotationMirror getUnsupportedAppUsageAnnotationMirror(Element e) {
for (AnnotationMirror m : e.getAnnotationMirrors()) {
TypeElement type = (TypeElement) m.getAnnotationType().asElement();
- if (type.getQualifiedName().toString().equals(
- UnsupportedAppUsage.class.getCanonicalName())) {
+ if (SUPPORTED_ANNOTATION_NAMES.contains(type.getQualifiedName().toString())) {
return m;
}
}
@@ -133,12 +139,12 @@
/**
* Maps an annotated element to the source position of the @UnsupportedAppUsage annotation
* attached to it. It returns CSV in the format:
- * dex-signature,filename,start-line,start-col,end-line,end-col
+ * dex-signature,filename,start-line,start-col,end-line,end-col
*
* The positions refer to the annotation itself, *not* the annotated member. This can therefore
* be used to read just the annotation from the file, and to perform in-place edits on it.
*
- * @param signature the dex signature for the element.
+ * @param signature the dex signature for the element.
* @param annotatedElement The annotated element
* @return A single line of CSV text
*/
@@ -164,28 +170,34 @@
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(
- UnsupportedAppUsage.class);
- if (annotated.size() == 0) {
- return true;
- }
- // build signatures for each annotated member, and put them in a map of signature to member
Map<String, Element> signatureMap = new TreeMap<>();
SignatureBuilder sb = new SignatureBuilder(processingEnv.getMessager());
- for (Element e : annotated) {
- String sig = sb.buildSignature(e);
- if (sig != null) {
- signatureMap.put(sig, e);
+ for (Class<? extends Annotation> supportedAnnotation : SUPPORTED_ANNOTATIONS) {
+ Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(
+ supportedAnnotation);
+ if (annotated.size() == 0) {
+ continue;
+ }
+ // Build signatures for each annotated member and put them in a map from signature to
+ // member.
+ for (Element e : annotated) {
+ String sig = sb.buildSignature(supportedAnnotation, e);
+ if (sig != null) {
+ signatureMap.put(sig, e);
+ }
}
}
- try {
- writeToFile(INDEX_CSV,
- getCsvHeaders(),
- signatureMap.entrySet()
- .stream()
- .map(e -> getAnnotationIndex(e.getKey() ,e.getValue())));
- } catch (IOException e) {
- throw new RuntimeException("Failed to write output", e);
+
+ if (!signatureMap.isEmpty()) {
+ try {
+ writeToFile(INDEX_CSV,
+ getCsvHeaders(),
+ signatureMap.entrySet()
+ .stream()
+ .map(e -> getAnnotationIndex(e.getKey(), e.getValue())));
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to write output", e);
+ }
}
return true;
}
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
index 4e52b8f..9eb9a92 100755
--- a/wifi/tests/runtests.sh
+++ b/wifi/tests/runtests.sh
@@ -19,7 +19,8 @@
adb root
adb wait-for-device
-adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
+TARGET_ARCH=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash --dumpvar-mode TARGET_ARCH)
+adb install -r -g "$OUT/testcases/FrameworksWifiApiTests/$TARGET_ARCH/FrameworksWifiApiTests.apk"
adb shell am instrument --no-hidden-api-checks -w "$@" \
'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'