diff options
220 files changed, 4672 insertions, 2778 deletions
diff --git a/Android.bp b/Android.bp index 57f651319562..53da6e244f8c 100644 --- a/Android.bp +++ b/Android.bp @@ -763,6 +763,7 @@ java_library_host { 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 2417d8ef1924..ea82aa183d95 100755 --- a/api/current.txt +++ b/api/current.txt @@ -11323,6 +11323,7 @@ package android.content.pm { 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 @@ package android.icu.util { 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 @@ package android.media.tv { 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 @@ package android.media.tv { 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 72202ad9712a..f40b14614323 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -275,6 +275,14 @@ package android.hardware { } +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 3b4a8680bf44..ce379f549c39 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4609,17 +4609,6 @@ package android.provider { 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 cb9ff493c546..21d761fbac2f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1201,17 +1201,6 @@ package android.provider { 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 1ac6ea8ba521..f04f017d8911 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -33,6 +33,7 @@ import "frameworks/base/core/proto/android/os/enums.proto"; 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 @@ message Atom { 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 @@ message Temperature { } /** - * 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; - - // 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.EventType event_type = 1; + + 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 70fa5fa56d58..f6b7eefc7864 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -555,7 +555,7 @@ final class SystemServiceRegistry { 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 1c9a43acfa65..9c21e8fe5e45 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 9faa1d675d8d..e7f2d18ad6a2 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -22,23 +22,16 @@ import android.annotation.RequiresPermission; 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 @@ public final class BluetoothA2dp implements BluetoothProfile { @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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { 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 final class BluetoothA2dp implements BluetoothProfile { */ 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 final class BluetoothA2dp implements BluetoothProfile { 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 @@ public final class BluetoothA2dp implements BluetoothProfile { 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 @@ public final class BluetoothA2dp implements BluetoothProfile { */ 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 @@ public final class BluetoothA2dp implements BluetoothProfile { @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 @@ public final class BluetoothA2dp implements BluetoothProfile { @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 @@ public final class BluetoothA2dp implements BluetoothProfile { 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 @@ public final class BluetoothA2dp implements BluetoothProfile { } } - 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 fda2f8927535..5a8055a29cfc 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 final class BluetoothA2dpSink implements BluetoothProfile { 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 final class BluetoothA2dpSink implements BluetoothProfile { */ 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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @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 final class BluetoothA2dpSink implements BluetoothProfile { */ 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 final class BluetoothA2dpSink implements BluetoothProfile { */ 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 final class BluetoothA2dpSink implements BluetoothProfile { */ 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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @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 @@ public final class BluetoothA2dpSink implements BluetoothProfile { } } - 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 e7c8944788fd..4e7e4415c54d 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 final class BluetoothAvrcpController implements BluetoothProfile { 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 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @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 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @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 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @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 final class BluetoothAvrcpController implements BluetoothProfile { 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 final class BluetoothAvrcpController implements BluetoothProfile { */ 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 final class BluetoothAvrcpController implements BluetoothProfile { 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 @@ public final class BluetoothAvrcpController implements BluetoothProfile { 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 8d9d340ee68b..9862a63ef238 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -337,19 +337,9 @@ public final class BluetoothHeadset implements BluetoothProfile { 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 @@ public final class BluetoothHeadset implements BluetoothProfile { 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 @@ public final class BluetoothHeadset implements BluetoothProfile { 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 @@ public final class BluetoothHeadset implements BluetoothProfile { @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 ec18d42698c1..05833b5f571d 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 final class BluetoothHeadsetClient implements BluetoothProfile { 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ /*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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 final class BluetoothHeadsetClient implements BluetoothProfile { */ 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * 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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * @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 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { 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 58ff2e14fd50..60fb6fb122e3 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -22,20 +22,14 @@ import android.annotation.Nullable; 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 final class BluetoothHearingAid implements BluetoothProfile { */ 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 final class BluetoothHearingAid implements BluetoothProfile { */ 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 final class BluetoothHearingAid implements BluetoothProfile { */ 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { @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 final class BluetoothHearingAid implements BluetoothProfile { 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 final class BluetoothHearingAid implements BluetoothProfile { 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 final class BluetoothHearingAid implements BluetoothProfile { */ 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { @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 final class BluetoothHearingAid implements BluetoothProfile { */ 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { @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 @@ public final class BluetoothHearingAid implements BluetoothProfile { 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 final class BluetoothHearingAid implements BluetoothProfile { 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 final class BluetoothHearingAid implements BluetoothProfile { 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { 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 @@ public final class BluetoothHearingAid implements BluetoothProfile { 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 3bc8544ebf87..e9b0be2c4cd6 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -18,10 +18,8 @@ package android.bluetooth; 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 @@ public final class BluetoothHidDevice implements BluetoothProfile { } } - 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 @@ public final class BluetoothHidDevice implements BluetoothProfile { } } - 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 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); - } + 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)); } - }; + }; 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 @@ public final class BluetoothHidDevice implements BluetoothProfile { /** {@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 @@ public final class BluetoothHidDevice implements BluetoothProfile { /** {@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 @@ public final class BluetoothHidDevice implements BluetoothProfile { 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 final class BluetoothHidDevice implements BluetoothProfile { 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 final class BluetoothHidDevice implements BluetoothProfile { 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 final class BluetoothHidDevice implements BluetoothProfile { 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 final class BluetoothHidDevice implements BluetoothProfile { 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 @@ public final class BluetoothHidDevice implements BluetoothProfile { * {@hide} */ public String getUserAppName() { - final IBluetoothHidDevice service = mService; + final IBluetoothHidDevice service = getService(); if (service != null) { try { @@ -733,7 +645,7 @@ public final class BluetoothHidDevice implements BluetoothProfile { 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 final class BluetoothHidDevice implements BluetoothProfile { 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 289e769a99ef..4afb382c0660 100644 --- a/core/java/android/bluetooth/BluetoothHidHost.java +++ b/core/java/android/bluetooth/BluetoothHidHost.java @@ -18,10 +18,7 @@ package android.bluetooth; 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 final class BluetoothHidHost implements BluetoothProfile { 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 @@ public final class BluetoothHidHost implements BluetoothProfile { @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 @@ public final class BluetoothHidHost implements BluetoothProfile { @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 @@ public final class BluetoothHidHost implements BluetoothProfile { @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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 @@ public final class BluetoothHidHost implements BluetoothProfile { 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 @@ public final class BluetoothHidHost implements BluetoothProfile { 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 final class BluetoothHidHost implements BluetoothProfile { */ 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 98c23c600f14..dd2f150ad4eb 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 final class BluetoothMap implements BluetoothProfile { 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 @@ public final class BluetoothMap implements BluetoothProfile { /** 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 @@ public final class BluetoothMap implements BluetoothProfile { * 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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 @@ public final class BluetoothMap implements BluetoothProfile { @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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 final class BluetoothMap implements BluetoothProfile { */ 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 @@ public final class BluetoothMap implements BluetoothProfile { 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 559a59b68b4e..ec0180c5adde 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -18,11 +18,9 @@ package android.bluetooth; 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 final class BluetoothMapClient implements BluetoothProfile { 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 @@ public final class BluetoothMapClient implements BluetoothProfile { 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 @@ public final class BluetoothMapClient implements BluetoothProfile { * 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 final class BluetoothMapClient implements BluetoothProfile { */ 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 final class BluetoothMapClient implements BluetoothProfile { */ 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 final class BluetoothMapClient implements BluetoothProfile { */ 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 @@ public final class BluetoothMapClient implements BluetoothProfile { @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 @@ public final class BluetoothMapClient implements BluetoothProfile { @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 @@ public final class BluetoothMapClient implements BluetoothProfile { @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 final class BluetoothMapClient implements BluetoothProfile { */ 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 final class BluetoothMapClient implements BluetoothProfile { */ 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 final class BluetoothMapClient implements BluetoothProfile { 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 final class BluetoothMapClient implements BluetoothProfile { */ 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 @@ public final class BluetoothMapClient implements BluetoothProfile { * 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 58be73296027..fb78789ba8ad 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -19,10 +19,7 @@ package android.bluetooth; 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 final class BluetoothPan implements BluetoothProfile { */ 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()"); + mProfileConnector.disconnect(); + } - 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; + 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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { @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 @@ public final class BluetoothPan implements BluetoothProfile { 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 b303c34ee0ae..d94c65742e6c 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -24,6 +24,7 @@ import android.content.Intent; 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 class BluetoothPbap implements BluetoothProfile { 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 @@ public class BluetoothPbap implements BluetoothProfile { 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 @@ public class BluetoothPbap implements BluetoothProfile { 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); - } + } catch (RemoteException re) { + Log.e(TAG, "", re); } } + doUnbind(); mServiceListener = null; } @@ -312,7 +310,7 @@ public class BluetoothPbap implements BluetoothProfile { 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 1446adc8b9c3..d70e1e7f3f5f 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 final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { /** 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { * 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("getConnectedDevices()"); } - final IBluetoothPbapClient service = mService; + final IBluetoothPbapClient service = getService(); if (service != null && isEnabled()) { try { return service.getConnectedDevices(); @@ -250,7 +180,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 @@ public final class BluetoothPbapClient implements BluetoothProfile { 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 000000000000..d9987249a6e2 --- /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 1b732062f614..e0610c890559 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 final class BluetoothSap implements BluetoothProfile { 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 final class BluetoothSap implements BluetoothProfile { */ 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 @@ public final class BluetoothSap implements BluetoothProfile { * @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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 @@ public final class BluetoothSap implements BluetoothProfile { @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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 final class BluetoothSap implements BluetoothProfile { */ 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 @@ public final class BluetoothSap implements BluetoothProfile { 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 72981a773277..4f7f07bdee55 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2719,6 +2719,16 @@ public abstract class PackageManager { = "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 d710d57d8f0b..ca43d40bbcaa 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -80,7 +80,6 @@ import android.util.ArrayMap; 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 com.android.internal.util.XmlUtils; 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 @@ public class PackageParser { } // 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 0e10de8c4e3f..a69ca99500d6 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3449,6 +3449,10 @@ public class ConnectivityManager { 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 @@ public class ConnectivityManager { 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 a33f3fcfb263..65bc75b8c00f 100644 --- a/core/java/android/net/DhcpResults.java +++ b/core/java/android/net/DhcpResults.java @@ -64,6 +64,8 @@ public final class DhcpResults implements Parcelable { @UnsupportedAppUsage public int mtu; + public String serverHostName; + public DhcpResults() { super(); } @@ -97,6 +99,7 @@ public final class DhcpResults implements Parcelable { vendorInfo = source.vendorInfo; leaseDuration = source.leaseDuration; mtu = source.mtu; + serverHostName = source.serverHostName; } } @@ -129,6 +132,7 @@ public final class DhcpResults implements Parcelable { vendorInfo = null; leaseDuration = 0; mtu = 0; + serverHostName = null; } @Override @@ -139,6 +143,7 @@ public final class DhcpResults implements Parcelable { 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 @@ public final class DhcpResults implements Parcelable { 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 @@ public final class DhcpResults implements Parcelable { dest.writeInt(mtu); InetAddressUtils.parcelInetAddress(dest, serverAddress, flags); dest.writeString(vendorInfo); + dest.writeString(serverHostName); } @Override @@ -193,6 +200,7 @@ public final class DhcpResults implements Parcelable { 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 d4c3edca4367..889e9bc7875e 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -941,7 +941,8 @@ public final class IpSecManager { 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 30d3b84c978c..cd8ce8d87778 100644 --- a/core/java/android/net/metrics/ApfProgramEvent.java +++ b/core/java/android/net/metrics/ApfProgramEvent.java @@ -176,7 +176,7 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { out.writeInt(filteredRas); out.writeInt(currentRas); out.writeInt(programLength); - out.writeInt(flags); + out.writeInt(this.flags); } /** @hide */ @@ -192,6 +192,18 @@ public final class ApfProgramEvent implements IpConnectivityLog.Event { 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 ddc788dba649..2e78469afd0d 100644 --- a/core/java/android/net/metrics/ApfStats.java +++ b/core/java/android/net/metrics/ApfStats.java @@ -275,6 +275,22 @@ public final class ApfStats implements IpConnectivityLog.Event { .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 93063cbe09a4..fa6bff32b822 100644 --- a/core/java/android/net/metrics/DhcpClientEvent.java +++ b/core/java/android/net/metrics/DhcpClientEvent.java @@ -22,6 +22,7 @@ import android.annotation.TestApi; 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 @@ public final class DhcpClientEvent implements IpConnectivityLog.Event { 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 013e3530a941..77908e6593ad 100644 --- a/core/java/android/net/metrics/IpManagerEvent.java +++ b/core/java/android/net/metrics/IpManagerEvent.java @@ -101,6 +101,14 @@ public final class IpManagerEvent implements IpConnectivityLog.Event { 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 c7362979af61..f9ee39bf9fbd 100644 --- a/core/java/android/net/metrics/IpReachabilityEvent.java +++ b/core/java/android/net/metrics/IpReachabilityEvent.java @@ -93,6 +93,13 @@ public final class IpReachabilityEvent implements IpConnectivityLog.Event { 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 512811580021..ec0f82a3aa66 100644 --- a/core/java/android/net/metrics/NetworkEvent.java +++ b/core/java/android/net/metrics/NetworkEvent.java @@ -121,6 +121,14 @@ public final class NetworkEvent implements IpConnectivityLog.Event { 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 d16a10432373..6ccca7dba5b9 100644 --- a/core/java/android/net/metrics/RaEvent.java +++ b/core/java/android/net/metrics/RaEvent.java @@ -97,6 +97,18 @@ public final class RaEvent implements IpConnectivityLog.Event { .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 ebca7e6d5607..67844202de5d 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -170,6 +170,15 @@ public final class ValidationProbeEvent implements IpConnectivityLog.Event { 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 e366fe05723e..32735aa24cd5 100644 --- a/core/java/android/os/BugreportManager.java +++ b/core/java/android/os/BugreportManager.java @@ -32,7 +32,7 @@ import com.android.internal.util.Preconditions; 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 @@ public final class BugreportManager { @NonNull BugreportParams params, @NonNull @CallbackExecutor Executor executor, @NonNull BugreportCallback callback) { - File tmpScreenshotFile = null; try { Preconditions.checkNotNull(bugreportFd); Preconditions.checkNotNull(params); @@ -155,13 +154,10 @@ public final class BugreportManager { 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 @@ public final class BugreportManager { 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 @@ public final class BugreportManager { } } - 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 @@ public final class BugreportManager { }); } finally { Binder.restoreCallingIdentity(identity); - deleteFile(mTmpScreenshotFile); } } @@ -253,7 +231,6 @@ public final class BugreportManager { }); } finally { Binder.restoreCallingIdentity(identity); - deleteFile(mTmpScreenshotFile); } } diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 03e8c154e3fc..7f60b9cec284 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -363,18 +363,6 @@ interface INetworkManagementService 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 @@ interface INetworkManagementService */ 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 f98641d3ddc7..e94d3a71831b 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10336,8 +10336,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; /** @@ -10346,8 +10344,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; /** @@ -10356,8 +10352,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; /** @@ -10367,8 +10361,6 @@ public final class Settings { * 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 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url"; /** @@ -10407,8 +10397,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; /** @@ -10417,8 +10405,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; /** @@ -10427,8 +10413,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls"; @@ -10438,8 +10422,6 @@ public final class Settings { * by "@@,@@". * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs"; @@ -10450,8 +10432,6 @@ public final class Settings { * * @hide */ - @SystemApi - @TestApi public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https"; /** @@ -10460,8 +10440,6 @@ public final class Settings { * * @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 386169528e89..fc23c54e834e 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -19,7 +19,7 @@ package android.webkit; 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 @@ public class MimeTypeMap { * @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 @@ public class MimeTypeMap { */ @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 @@ public class MimeTypeMap { * @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 @@ public class MimeTypeMap { */ @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 28c59db6b932..c5fc9b3628df 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -49,8 +49,8 @@ int ifc_disable(const char *ifname); 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 9c60e6bd8565..129b8af85ffe 100644 --- a/core/jni/android_os_HwBinder.cpp +++ b/core/jni/android_os_HwBinder.cpp @@ -188,7 +188,7 @@ status_t JHwBinder::onTransact( 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 182a621c6978..a26707eedb28 100644 --- a/core/jni/android_util_jar_StrictJarFile.cpp +++ b/core/jni/android_util_jar_StrictJarFile.cpp @@ -146,7 +146,7 @@ jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle, 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 000000000000..0b5aa8677a6e --- /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 000000000000..af6fea017bef --- /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 f1e9d659e0fd..be492505e230 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 716376997f81..a92c50059a2a 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 875f2c025006..c17f076d2b71 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -33,6 +33,11 @@ applications that come with the platform <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 @@ applications that come with the platform <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 66a547723b2f..47b7d646d79f 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -120,9 +120,8 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl( 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<const ApkAssets> ApkAssets::LoadImpl( 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 6e2ca60cc3d3..44614c11fb14 100644 --- a/libs/androidfw/ZipFileRO.cpp +++ b/libs/androidfw/ZipFileRO.cpp @@ -98,7 +98,7 @@ ZipEntryRO ZipFileRO::findEntryByName(const char* entryName) const 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 9e320a21b534..a81bb6ffab06 100644 --- a/libs/androidfw/tests/TestHelpers.cpp +++ b/libs/androidfw/tests/TestHelpers.cpp @@ -34,9 +34,8 @@ AssertionResult ReadFileFromZipToString(const std::string& zip_path, const std:: << "': " << ::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 5f5a92e55bf2..adfae5bccebe 100644 --- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp +++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp @@ -81,7 +81,7 @@ void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options // 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 @@ void outputBenchmarkReport(const TestScene::Info& info, const TestScene::Options // 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 4af6274b7ece..63a670c67bfc 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 cfe2da1eb471..000000000000 --- 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 c9c881c6f3d2..2bc9a2b4be45 100644 --- a/media/java/android/media/tv/TvTrackInfo.java +++ b/media/java/android/media/tv/TvTrackInfo.java @@ -58,6 +58,7 @@ public final class TvTrackInfo implements Parcelable { 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 @@ public final class TvTrackInfo implements Parcelable { 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 @@ public final class TvTrackInfo implements Parcelable { 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 @@ public final class TvTrackInfo implements Parcelable { } /** + * 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 @@ public final class TvTrackInfo implements Parcelable { 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 @@ public final class TvTrackInfo implements Parcelable { && 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 @@ public final class TvTrackInfo implements Parcelable { 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 @@ public final class TvTrackInfo implements Parcelable { } /** + * 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 @@ public final class TvTrackInfo implements Parcelable { * @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 000000000000..fc52006d14d2 --- /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 8bba3ba99974..000000000000 --- 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 44e0a659212a..0a03425f4699 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 000000000000..456ca83f5227 --- /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 000000000000..207aade406ef --- /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 e0bb862c5362..62de2ba45455 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -56,15 +56,24 @@ cc_library_shared { srcs: [ "jni/network_stack_utils_jni.cpp" ], - + sdk_version: "current", shared_libs: [ "liblog", - "libcutils", - "libnativehelper", - ], - static_libs: [ - "libpcap", + "libnativehelper_compat_libc++", ], + + // 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 @@ java_defaults { 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 5544eaa809e7..f2ba5757ed80 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 @@ static const JNINativeMethod gNetworkStackUtilsMethods[] = { 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 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { 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 475f8261fdc1..41715b2a4798 100644 --- a/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java +++ b/packages/NetworkStack/src/android/net/NetworkStackIpMemoryStore.java @@ -19,6 +19,9 @@ package android.net; 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 @@ public class NetworkStackIpMemoryStore extends IpMemoryStoreClient { } @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 663e2f10ffe2..359c85983a94 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.Intent; 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 @@ public class ApfFilter { } /** - * 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 @@ public class ApfFilter { } /** + * 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 d7ff98b1f501..a15d42381ff0 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java @@ -195,6 +195,18 @@ public abstract class DhcpPacket { 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 @@ public abstract class DhcpPacket { 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 @@ public abstract class DhcpPacket { 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 @@ public abstract class DhcpPacket { 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 @@ public abstract class DhcpPacket { // 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 @@ public abstract class DhcpPacket { 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 @@ public abstract class DhcpPacket { 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 96e09fafb6b6..dc74c041c35a 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.INetd; 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 @@ public class IpClient extends StateMachine { 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 @@ public class IpClient extends StateMachine { 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 @@ public class IpClient extends StateMachine { } /** - * 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 @@ public class IpClient extends StateMachine { 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 fb03c544fd30..abfed3e1d84c 100644 --- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java +++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java @@ -62,6 +62,49 @@ public class NetworkStackUtils { */ 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 50eb5d480768..d6355bc111c2 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_MIN_EVALUATE_TI 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { @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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { + 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 @@ public class NetworkMonitor extends StateMachine { } 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 @@ public class NetworkMonitor extends StateMachine { 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 class NetworkMonitor extends StateMachine { */ 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { .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 fe3c1e8eb3e5..039f6bf791fb 100644 --- a/packages/NetworkStack/tests/Android.bp +++ b/packages/NetworkStack/tests/Android.bp @@ -56,6 +56,7 @@ android_test { "liblog", "liblzma", "libnativehelper", + "libnativehelper_compat_libc++", "libnetworkstacktestsjni", "libnetworkstackutilsjni", "libpackagelistparser", @@ -99,5 +100,4 @@ cc_library_shared { "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 a0e508f130a5..93ab3be28fc7 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 @@ public class ApfTest { 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 @@ public class ApfTest { 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 @@ public class ApfTest { 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 4d98403bfd4e..a30d3e492406 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 @@ public class DhcpPacketTest { } 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 @@ public class DhcpPacketTest { 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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { "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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { 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 @@ public class DhcpPacketTest { // Options "638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" + "3a0400000e103b040000189cff00000000")); + // CHECKSTYLE:ON Generated code checkMtu(packet, 0, null); checkMtu(packet, 0, mtuBytes(1501)); @@ -629,6 +638,7 @@ public class DhcpPacketTest { @Test public void testBadHwaddrLength() throws Exception { + // CHECKSTYLE:OFF Generated code final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray( // IP header. "450001518d0600004011144dc0a82b01c0a82bf7" + @@ -649,6 +659,7 @@ public class DhcpPacketTest { // Options "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" + "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff")); + // CHECKSTYLE:ON Generated code String expectedClientMac = "30766FF2A90C"; final int hwAddrLenOffset = 20 + 8 + 2; @@ -705,6 +716,7 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { // 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 @@ public class DhcpPacketTest { // Options. "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" + "d18180060f0777766d2e6564751c040a0fffffff000000")); + // CHECKSTYLE:ON Generated code DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2); assertTrue(offerPacket instanceof DhcpOfferPacket); @@ -830,11 +849,12 @@ public class DhcpPacketTest { 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 @@ public class DhcpPacketTest { // Options. "6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" + "d18180060f0777766d2e6564751c040a0fffffff000000")); + // CHECKSTYLE:ON Generated code try { DhcpPacket.decodeFullPacket(packet, ENCAP_L2); @@ -867,6 +888,7 @@ public class DhcpPacketTest { @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 @@ public class DhcpPacketTest { // 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 0dc1cbf8a984..6f5c27edb9d5 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.ArgumentMatchers.eq; 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.NetworkCapabilities; 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.Bundle; 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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { @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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { } } - 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 @@ public class NetworkMonitorTest { @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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { } @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 @@ public class NetworkMonitorTest { 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 @@ public class NetworkMonitorTest { } 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 e1a602b53d9d..9536bae6bbe6 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 000000000000..aaaf0448fc31 --- /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 b738d7771465..000000000000 --- 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 000000000000..8536c4fbb5a3 --- /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 44ff3383d566..000000000000 --- 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 000000000000..fe1bb265880c --- /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 4437f49fd335..ccf345b0af36 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 2f7e3b18d3c1..b7c20aa197ca 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 com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionD 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 @@ public class MobileSignalController extends SignalController< 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 @@ public class MobileSignalController extends SignalController< 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 @@ public class MobileSignalController extends SignalController< } } + 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 @@ public class MobileSignalController extends SignalController< + " 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,12 +605,19 @@ public class MobileSignalController extends SignalController< + " type=" + networkType); } mDataState = state; + updateDataNetType(networkType); + updateTelephony(); + } + + private void updateDataNetType(int networkType) { mDataNetType = networkType; - if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null && - mServiceState.isUsingCarrierAggregation()) { - mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA; + 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; + } } - updateTelephony(); } @Override 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 b4f0fec90fb0..5c6634c7aa1b 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 @@ public class NetworkControllerImpl extends BroadcastReceiver 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 @@ public class NetworkControllerImpl extends BroadcastReceiver 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 7347f66de8ce..2c4b1f97c739 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 @@ class TelephonyIcons { 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 @@ class TelephonyIcons { 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 @@ class TelephonyIcons { 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 1c9a43acfa65..9c21e8fe5e45 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 b60dd0f52c73..223eb552f832 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -1094,11 +1094,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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 @@ class BluetoothManagerService extends IBluetoothManager.Stub { 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 90c86c7ae7a6..63fd2fda1ce6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2861,7 +2861,7 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().notifyNetworkDisconnected(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } mNetworkAgentInfos.remove(nai.messenger); nai.clatd.update(); @@ -3070,11 +3070,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // 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 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + 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 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().setAcceptPartialConnectivity(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } } } @@ -3456,7 +3481,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().launchCaptivePortalApp(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } }); } @@ -4084,7 +4109,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().forceReevaluation(uid); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } } @@ -5464,7 +5489,7 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub // 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 887de74f1cf9..09fa006c7669 100644 --- a/services/core/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java @@ -861,10 +861,13 @@ public final class DropBoxManagerService extends SystemService { } 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 1ff50b240672..6dbe3ade09f0 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -2045,28 +2045,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @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 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } } - 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 e33392d359dd..2321afb7df43 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 class DnsManager { } 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 0271d3bcb57c..1275302cd8c9 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 @@ public class Vpn { } } 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 38eb0bcfd3cc..81863439c017 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 @@ public class IPv6TetheringCoordinator { } 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 8dda48523c83..0ab1a3e916e3 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 @@ chaviw@google.com 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 d72f1cf8382b..ab11fe4df283 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -16,7 +16,10 @@ aidl_interface { }, }, api_dir: "aidl/ipmemorystore", - versions: ["1"], + versions: [ + "1", + "2", + ], } aidl_interface { @@ -30,6 +33,7 @@ aidl_interface { "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 @@ aidl_interface { }, 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 000000000000..a8cbab26190f --- /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 000000000000..cf02c26c2fe3 --- /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 000000000000..291dbef817e6 --- /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 000000000000..52f40d49abd5 --- /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 000000000000..785351435d73 --- /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 000000000000..3dd2ae6e9bab --- /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 000000000000..46d4ecb9ed7c --- /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 000000000000..54e654b80c9e --- /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 000000000000..9531ea3963fb --- /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 000000000000..414272b49f1d --- /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 000000000000..92c6779b5dc0 --- /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 000000000000..31891de7230a --- /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 000000000000..029968b6f324 --- /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 000000000000..ee9871ddcd15 --- /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 000000000000..7da11e476c0e --- /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 000000000000..f6ca6f7a78e2 --- /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 000000000000..c80a78785b3b --- /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 000000000000..65de8833e6c5 --- /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 000000000000..2de790bb7754 --- /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 000000000000..3a6c30496fd8 --- /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 000000000000..e121c064f7ac --- /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 000000000000..67193ae904bc --- /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 000000000000..914315855496 --- /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 000000000000..dcc4489d52a6 --- /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 000000000000..77d5917de913 --- /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 000000000000..d6bc8089a0be --- /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 000000000000..31891de7230a --- /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 000000000000..029968b6f324 --- /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 000000000000..ee9871ddcd15 --- /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 000000000000..7da11e476c0e --- /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 000000000000..f6ca6f7a78e2 --- /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 000000000000..c80a78785b3b --- /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 000000000000..65de8833e6c5 --- /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 000000000000..2de790bb7754 --- /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 000000000000..3a6c30496fd8 --- /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 000000000000..e121c064f7ac --- /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 000000000000..67193ae904bc --- /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 000000000000..914315855496 --- /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 000000000000..dcc4489d52a6 --- /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 000000000000..176a5ce85373 --- /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 000000000000..d6bc8089a0be --- /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 978638b51ad1..c98d9c201342 100644 --- a/services/net/java/android/net/DhcpResultsParcelable.aidl +++ b/services/net/java/android/net/DhcpResultsParcelable.aidl @@ -24,4 +24,5 @@ parcelable DhcpResultsParcelable { 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 b32ef12ab24d..3fc81a3dadc5 100644 --- a/services/net/java/android/net/INetworkMonitor.aidl +++ b/services/net/java/android/net/INetworkMonitor.aidl @@ -40,6 +40,20 @@ oneway interface INetworkMonitor { // 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 4a115e6ec55b..6f91e006c853 100644 --- a/services/net/java/android/net/IpMemoryStore.java +++ b/services/net/java/android/net/IpMemoryStore.java @@ -18,11 +18,14 @@ package android.net; 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 @@ import java.util.concurrent.ExecutionException; * @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 @@ public class IpMemoryStore extends IpMemoryStoreClient { }); } + /* + * 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 379c017b2990..3d562022a2e5 100644 --- a/services/net/java/android/net/IpMemoryStoreClient.java +++ b/services/net/java/android/net/IpMemoryStoreClient.java @@ -31,6 +31,7 @@ import android.os.RemoteException; 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 @@ public abstract class IpMemoryStoreClient { 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 @@ public abstract class IpMemoryStoreClient { @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 @@ public abstract class IpMemoryStoreClient { @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 abstract class IpMemoryStoreClient { 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 abstract class IpMemoryStoreClient { 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 abstract class IpMemoryStoreClient { 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 abstract class IpMemoryStoreClient { 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 index bdb246f516a2..27ed11e119b7 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/services/net/java/android/net/NattKeepalivePacketData.java @@ -19,8 +19,10 @@ package android.net; 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.ByteBuffer; 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 @@ public final class NattKeepalivePacketData extends KeepalivePacketData { 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/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl new file mode 100644 index 000000000000..6f006d4971fb --- /dev/null +++ b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl @@ -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. + */ + +package android.net; + +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 1e7726472ff6..9989c52fc403 100644 --- a/services/net/java/android/net/ip/IIpClient.aidl +++ b/services/net/java/android/net/ip/IIpClient.aidl @@ -17,6 +17,7 @@ package android.net.ip; import android.net.ProxyInfo; import android.net.ProvisioningConfigurationParcelable; +import android.net.NattKeepalivePacketDataParcelable; import android.net.TcpKeepalivePacketDataParcelable; /** @hide */ @@ -33,4 +34,5 @@ oneway interface IIpClient { 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 000000000000..f8d7e845da2c --- /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 44d8e0ce3635..172dc24df6b0 100644 --- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java +++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java @@ -41,6 +41,7 @@ public final class IpConfigurationParcelableUtil { p.mtu = results.mtu; p.serverAddress = parcelAddress(results.serverAddress); p.vendorInfo = results.vendorInfo; + p.serverHostName = results.serverHostName; return p; } @@ -54,6 +55,7 @@ public final class IpConfigurationParcelableUtil { 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 23f55727d456..c22ca90a79c2 100644 --- a/services/tests/uiservicestests/Android.bp +++ b/services/tests/uiservicestests/Android.bp @@ -51,7 +51,7 @@ android_test { "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 e61542824083..6a3469c5fa24 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 @@ public final class UsbDescriptorParser { * 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 e25c17df4994..0f63853e823f 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 @@ public final class PhoneAccountHandle implements Parcelable { 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 ecb0daffeb7b..e727a6e9bacc 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -4259,6 +4259,22 @@ public final class Telephony { * @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 349ef55c7f06..c449dbf02c2e 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1202,7 +1202,7 @@ public class CarrierConfigManager { * 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 @@ public class CarrierConfigManager { /** * 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 @@ public class CarrierConfigManager { /** * 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 @@ public class CarrierConfigManager { "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 @@ public class CarrierConfigManager { 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 @@ public class CarrierConfigManager { * 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 a83d8f004f33..cbe5e71ae1e1 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -49,10 +49,10 @@ public abstract class CellIdentity implements Parcelable { // 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 @@ public abstract class CellIdentity implements Parcelable { } /** + * @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 @@ public abstract class CellIdentity implements Parcelable { } /** + * @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 86cdce1ed3a6..0ad1abe07417 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -339,6 +339,9 @@ public class ServiceState implements Parcelable { private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>(); + private String mOperatorAlphaLongRaw; + private String mOperatorAlphaShortRaw; + /** * get String description of roaming type * @hide @@ -420,6 +423,8 @@ public class ServiceState implements Parcelable { mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null : s.getNetworkRegistrationInfoList(); mNrFrequencyRange = s.mNrFrequencyRange; + mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw; + mOperatorAlphaShortRaw = s.mOperatorAlphaShortRaw; } /** @@ -453,6 +458,8 @@ public class ServiceState implements Parcelable { 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 @@ public class ServiceState implements Parcelable { out.writeInt(mChannelNumber); out.writeIntArray(mCellBandwidths); out.writeInt(mNrFrequencyRange); + out.writeString(mOperatorAlphaLongRaw); + out.writeString(mOperatorAlphaShortRaw); } public int describeContents() { @@ -836,7 +845,9 @@ public class ServiceState implements Parcelable { mIsEmergencyOnly, mLteEarfcnRsrpBoost, mNetworkRegistrationInfos, - mNrFrequencyRange); + mNrFrequencyRange, + mOperatorAlphaLongRaw, + mOperatorAlphaShortRaw); } @Override @@ -862,6 +873,8 @@ public class ServiceState implements Parcelable { && 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 @@ public class ServiceState implements Parcelable { .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 @@ public class ServiceState implements Parcelable { .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN) .build()); + mOperatorAlphaLongRaw = null; + mOperatorAlphaShortRaw = null; } public void setStateOutOfService() { @@ -1297,6 +1314,8 @@ public class ServiceState implements Parcelable { 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 @@ public class ServiceState implements Parcelable { 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 def7fbe5bd3f..be7bb6779f39 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -327,12 +327,12 @@ public final class SmsManager { 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 @@ public final class SmsManager { // 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 @@ public final class SmsManager { 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 @@ public final class SmsManager { 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 @@ public final class SmsManager { 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 @@ public final class SmsManager { 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 @@ public final class SmsManager { 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 58c05aa3ccba..43acfdddf819 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -2065,7 +2065,6 @@ public class SubscriptionManager { } else { logd("putPhoneIdAndSubIdExtra: no valid subs"); intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); - intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); } } @@ -2076,9 +2075,6 @@ public class SubscriptionManager { 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 add7d38edfdf..510e7c9f864f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3281,7 +3281,7 @@ public class TelephonyManager { } /** - * 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 d95a4992f808..2246ccc315c8 100644 --- a/telephony/java/android/telephony/UiccCardInfo.java +++ b/telephony/java/android/telephony/UiccCardInfo.java @@ -101,7 +101,7 @@ public final class UiccCardInfo implements Parcelable { /** * 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 @@ public final class UiccCardInfo implements Parcelable { } /** - * 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 93a7da04c56e..2bc677562b78 100644 --- a/telephony/java/android/telephony/UiccSlotInfo.java +++ b/telephony/java/android/telephony/UiccSlotInfo.java @@ -140,6 +140,14 @@ public class UiccSlotInfo implements Parcelable { 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 2d6402d545ae..b144ff761874 100644 --- a/telephony/java/android/telephony/emergency/EmergencyNumber.java +++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java @@ -558,6 +558,24 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu } 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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu 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 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu 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 f1a5778b2281..ee287d59b607 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -321,6 +321,18 @@ public class EuiccManager { "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 568c11be9077..fd58f7ea2752 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -545,7 +545,8 @@ public final class ImsCallProfile implements Parcelable { + ", emergencyUrns=" + mEmergencyUrns + ", emergencyCallRouting=" + mEmergencyCallRouting + ", emergencyCallTesting=" + mEmergencyCallTesting - + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }"; + + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + + ", mRestrictCause=" + mRestrictCause + " }"; } @Override @@ -565,6 +566,7 @@ public final class ImsCallProfile implements Parcelable { out.writeInt(mEmergencyCallRouting); out.writeBoolean(mEmergencyCallTesting); out.writeBoolean(mHasKnownUserIntentEmergency); + out.writeInt(mRestrictCause); } private void readFromParcel(Parcel in) { @@ -577,6 +579,7 @@ public final class ImsCallProfile implements Parcelable { 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 0bb1b4379679..e90548a4445f 100644 --- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java +++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java @@ -33,8 +33,8 @@ public class Rcs1To1Thread extends RcsThread { * * @hide */ - public Rcs1To1Thread(int threadId) { - super(threadId); + public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) { + super(rcsControllerCall, threadId); mThreadId = threadId; } @@ -56,7 +56,9 @@ public class Rcs1To1Thread extends RcsThread { */ @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 @@ public class Rcs1To1Thread extends RcsThread { */ @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 @@ public class Rcs1To1Thread extends RcsThread { @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 5512c4c7b19d..a2d68ad0cdb0 100644 --- a/telephony/java/android/telephony/ims/RcsControllerCall.java +++ b/telephony/java/android/telephony/ims/RcsControllerCall.java @@ -27,38 +27,38 @@ import android.telephony.ims.aidl.IRcs; * @hide - not meant for public use */ class RcsControllerCall { - static <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"); - } + private final Context mContext; - try { - return serviceCall.methodOnIRcs(iRcs); - } catch (RemoteException exception) { - throw new RcsMessageStoreException(exception.getMessage()); - } + RcsControllerCall(Context context) { + mContext = context; } - static void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall) - throws RcsMessageStoreException { + <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 { - serviceCall.methodOnIRcs(iRcs); + return serviceCall.methodOnIRcs(iRcs, mContext.getOpPackageName()); } catch (RemoteException exception) { throw new RcsMessageStoreException(exception.getMessage()); } } + void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall) + throws RcsMessageStoreException { + 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 994b27ab7405..9dd07209fcfd 100644 --- a/telephony/java/android/telephony/ims/RcsEvent.java +++ b/telephony/java/android/telephony/ims/RcsEvent.java @@ -40,5 +40,5 @@ public abstract class RcsEvent { * * @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 8e3f6cd4d889..b44adeaa62bb 100644 --- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java @@ -38,7 +38,7 @@ public abstract class RcsEventDescriptor implements Parcelable { * 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 e30745b7e633..b972d557fae0 100644 --- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java @@ -39,9 +39,9 @@ public class RcsEventQueryResultDescriptor implements Parcelable { 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 3816cd413722..ef66a76a5902 100644 --- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java +++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java @@ -103,12 +103,15 @@ public class RcsFileTransferPart { 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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 @@ public class RcsFileTransferPart { */ @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 baec19ac6669..30abcb4abb3d 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThread.java +++ b/telephony/java/android/telephony/ims/RcsGroupThread.java @@ -38,8 +38,8 @@ public class RcsGroupThread extends RcsThread { * * @hide */ - public RcsGroupThread(int threadId) { - super(threadId); + public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) { + super(rcsControllerCall, threadId); } /** @@ -58,7 +58,8 @@ public class RcsGroupThread extends RcsThread { @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 @@ public class RcsGroupThread extends RcsThread { */ @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 @@ public class RcsGroupThread extends RcsThread { */ @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 @@ public class RcsGroupThread extends RcsThread { */ @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 @@ public class RcsGroupThread extends RcsThread { @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 @@ public class RcsGroupThread extends RcsThread { */ @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 @@ public class RcsGroupThread extends RcsThread { return; } - RcsControllerCall.callWithNoReturn( - iRcs -> iRcs.addParticipantToGroupThread(mThreadId, participant.getId())); + mRcsControllerCall.callWithNoReturn( + (iRcs, callingPackage) -> iRcs.addParticipantToGroupThread(mThreadId, + participant.getId(), callingPackage)); } /** @@ -150,8 +161,9 @@ public class RcsGroupThread extends RcsThread { return; } - RcsControllerCall.callWithNoReturn( - iRcs -> iRcs.removeParticipantFromGroupThread(mThreadId, participant.getId())); + mRcsControllerCall.callWithNoReturn( + (iRcs, callingPackage) -> iRcs.removeParticipantFromGroupThread(mThreadId, + participant.getId(), callingPackage)); } /** @@ -170,8 +182,10 @@ public class RcsGroupThread extends RcsThread { 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 @@ public class RcsGroupThread extends RcsThread { @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 @@ public class RcsGroupThread extends RcsThread { @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 4a6b963a143a..f4beef7f9843 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java @@ -23,14 +23,14 @@ import android.annotation.NonNull; * @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 @@ public abstract class RcsGroupThreadEvent extends RcsEvent { */ @NonNull public RcsGroupThread getRcsGroupThread() { - return new RcsGroupThread(mRcsGroupThreadId); + return mRcsGroupThread; } /** @@ -46,6 +46,6 @@ public abstract class RcsGroupThreadEvent extends RcsEvent { */ @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 3c6c74fac8e2..23e39ffb3680 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java @@ -40,9 +40,10 @@ public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent { * @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 @@ public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent { * @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 bcadc80bda54..9350e402c04e 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java @@ -38,9 +38,10 @@ public class RcsGroupThreadIconChangedEventDescriptor extends RcsGroupThreadEven @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 54032536601e..a6a0867ca739 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java @@ -41,7 +41,7 @@ public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent { */ 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 @@ public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent { * @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 597fa0a3f9f8..f9ccdd53f0a2 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java @@ -37,11 +37,11 @@ public class RcsGroupThreadNameChangedEventDescriptor extends RcsGroupThreadEven @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 48be479a1ac6..694c7de96eee 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java @@ -30,19 +30,20 @@ public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEv * 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 @@ public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEv * @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 abea10a641ac..4a6803ebc52c 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java @@ -36,12 +36,13 @@ public class RcsGroupThreadParticipantJoinedEventDescriptor extends RcsGroupThre @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 b724a3f2159f..fec4354a293a 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java @@ -44,7 +44,7 @@ public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEven 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 @@ public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEven } @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 f287db19da05..9b1085c3d178 100644 --- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java @@ -37,12 +37,12 @@ public class RcsGroupThreadParticipantLeftEventDescriptor extends RcsGroupThread @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 06e2a41accee..2810a49927c5 100644 --- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java +++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java @@ -26,8 +26,8 @@ public class RcsIncomingMessage extends RcsMessage { /** * @hide */ - RcsIncomingMessage(int id) { - super(id); + RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) { + super(rcsControllerCall, id); } /** @@ -39,8 +39,9 @@ public class RcsIncomingMessage extends RcsMessage { */ @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 @@ public class RcsIncomingMessage extends RcsMessage { */ @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 @@ public class RcsIncomingMessage extends RcsMessage { */ @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 @@ public class RcsIncomingMessage extends RcsMessage { */ @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 @@ public class RcsIncomingMessage extends RcsMessage { @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 63dc1ac568bf..0d6ca3cc58e1 100644 --- a/telephony/java/android/telephony/ims/RcsManager.java +++ b/telephony/java/android/telephony/ims/RcsManager.java @@ -25,20 +25,19 @@ import android.content.Context; */ @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 b0d0d5a6a9bb..4601bfd0ff2c 100644 --- a/telephony/java/android/telephony/ims/RcsMessage.java +++ b/telephony/java/android/telephony/ims/RcsMessage.java @@ -86,6 +86,11 @@ public abstract class RcsMessage { /** * @hide */ + protected final RcsControllerCall mRcsControllerCall; + + /** + * @hide + */ protected final int mId; @IntDef({ @@ -95,7 +100,8 @@ public abstract class RcsMessage { public @interface RcsMessageStatus { } - RcsMessage(int id) { + RcsMessage(RcsControllerCall rcsControllerCall, int id) { + mRcsControllerCall = rcsControllerCall; mId = id; } @@ -115,7 +121,8 @@ public abstract class RcsMessage { * @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 @@ public abstract class RcsMessage { */ @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 abstract class RcsMessage { 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 abstract class RcsMessage { 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 @@ public abstract class RcsMessage { 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 5df929baad52..36bb78a0594b 100644 --- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java +++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java @@ -20,13 +20,9 @@ import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MES 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 @@ import java.util.List; * * @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 @@ public final class RcsMessageQueryResult implements Parcelable { */ @Nullable public RcsQueryContinuationToken getContinuationToken() { - return mContinuationToken; + return mRcsMessageQueryResultParcelable.mContinuationToken; } /** @@ -71,45 +58,10 @@ public final class RcsMessageQueryResult implements Parcelable { */ @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 index a73ba50b6591..86928bfa41b8 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 000000000000..4972f9bc4956 --- /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 6fcb62b7c092..d1127984f126 100644 --- a/telephony/java/android/telephony/ims/RcsMessageStore.java +++ b/telephony/java/android/telephony/ims/RcsMessageStore.java @@ -19,6 +19,7 @@ package android.telephony.ims; 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 @@ import java.util.List; * @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 @@ public class RcsMessageStore { @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 @@ public class RcsMessageStore { @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 class RcsMessageStore { 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 class RcsMessageStore { 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 @@ public class RcsMessageStore { @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 @@ public class RcsMessageStore { @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 @@ public class RcsMessageStore { @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 @@ public class RcsMessageStore { */ @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 class RcsMessageStore { 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 @@ public class RcsMessageStore { } 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 @@ public class RcsMessageStore { 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 @@ public class RcsMessageStore { @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 1b4bfe576ac6..7080ec6c5281 100644 --- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java +++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java @@ -27,8 +27,8 @@ import java.util.List; * @hide */ public class RcsOutgoingMessage extends RcsMessage { - RcsOutgoingMessage(int id) { - super(id); + RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) { + super(rcsControllerCall, id); } /** @@ -45,12 +45,13 @@ public class RcsOutgoingMessage extends RcsMessage { 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 2db49c6d0dce..df4a3e45bc03 100644 --- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java +++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java @@ -25,6 +25,7 @@ import android.annotation.WorkerThread; * @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 @@ public class RcsOutgoingMessageDelivery { * * @hide */ - RcsOutgoingMessageDelivery(int recipientId, int messageId) { + RcsOutgoingMessageDelivery( + RcsControllerCall rcsControllerCall, int recipientId, int messageId) { + mRcsControllerCall = rcsControllerCall; mRecipientId = recipientId; mRcsOutgoingMessageId = messageId; } @@ -49,8 +52,9 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @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 @@ public class RcsOutgoingMessageDelivery { */ @NonNull public RcsParticipant getRecipient() { - return new RcsParticipant(mRecipientId); + return new RcsParticipant(mRcsControllerCall, mRecipientId); } /** @@ -126,6 +135,6 @@ public class RcsOutgoingMessageDelivery { */ @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 bcf134a71ea3..8512e960bfe6 100644 --- a/telephony/java/android/telephony/ims/RcsParticipant.java +++ b/telephony/java/android/telephony/ims/RcsParticipant.java @@ -24,8 +24,9 @@ import android.annotation.WorkerThread; * @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 @@ public class RcsParticipant { * * @hide */ - public RcsParticipant(int id) { + public RcsParticipant(RcsControllerCall rcsControllerCall, int id) { + mRcsControllerCall = rcsControllerCall; mId = id; } @@ -45,7 +47,9 @@ public class RcsParticipant { @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 @@ public class RcsParticipant { @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 @@ public class RcsParticipant { */ @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 @@ public class RcsParticipant { @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 @@ public class RcsParticipant { */ @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 61801f3fbf2c..865bc05132a2 100644 --- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java +++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java @@ -69,8 +69,8 @@ public final class RcsParticipantAliasChangedEvent extends RcsEvent { * @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 b29896c12ab8..43b918c3e0f4 100644 --- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java +++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java @@ -41,9 +41,9 @@ public class RcsParticipantAliasChangedEventDescriptor extends RcsEventDescripto @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 731c94e22889..0721dfdf5803 100644 --- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java +++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java @@ -30,10 +30,13 @@ import java.util.stream.Collectors; * @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 @@ public final class RcsParticipantQueryResult { @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 cf1dc76fedfb..efb2cca21c19 100644 --- a/telephony/java/android/telephony/ims/RcsThread.java +++ b/telephony/java/android/telephony/ims/RcsThread.java @@ -33,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting; public abstract class RcsThread { /** * The rcs_participant_thread_id that represents this thread in the database + * * @hide */ protected int mThreadId; @@ -40,8 +41,14 @@ public abstract class RcsThread { /** * @hide */ - protected RcsThread(int threadId) { + protected final RcsControllerCall mRcsControllerCall; + + /** + * @hide + */ + protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) { mThreadId = threadId; + mRcsControllerCall = rcsControllerCall; } /** @@ -51,7 +58,8 @@ public abstract class RcsThread { @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 abstract class RcsThread { 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 abstract class RcsThread { 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 @@ public abstract class RcsThread { */ @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 @@ public abstract class RcsThread { @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 c77bdb32eb7d..3de25de19430 100644 --- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java +++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java @@ -33,9 +33,12 @@ import java.util.stream.Collectors; * @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 final class RcsThreadQueryResult { 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 50dc587821fa..9ee15daf67b9 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.RcsFileTransferCreationParams; 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 @@ interface IRcs { ///////////////////////// // 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 @@ interface IRcs { // 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 @@ interface IRcs { // 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 0ad60963c398..71ea881fbf5d 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1586,7 +1586,7 @@ interface ITelephony { 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 89d32ab5a925..658c3edb4642 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 @@ public class RcsGroupThreadIconChangedEventTest { 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 726b9cd6641f..9fe67ad62b7c 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 @@ public class RcsGroupThreadNameChangedEventTest { .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 a109310076d2..18d5621f8e20 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 @@ public class RcsGroupThreadParticipantJoinedEventTest { .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 de2688c5b8c8..53a6bba52a3e 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 @@ public class RcsGroupThreadParticipantLeftEventTest { .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 57240545e5d8..dcf68ffa3324 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 @@ public class RcsParticipantAliasChangedEventTest { .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 beb4f8ad28e2..551a228282cd 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 @@ public class RcsThreadQueryParamsTest { @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 3b2e34a159ee..07525a6ea49c 100644 --- a/tests/net/common/Android.bp +++ b/tests/net/common/Android.bp @@ -23,6 +23,7 @@ java_library { "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 000000000000..eed7159ffddc --- /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 ad76388b3c9b..6bc7c1bb30f8 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_VALIDATED; 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 @@ public class NetworkCapabilitiesTest { 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 0bee7cd29d29..bef66b27df62 100644 --- a/tests/net/common/java/android/net/NetworkTest.java +++ b/tests/net/common/java/android/net/NetworkTest.java @@ -155,4 +155,12 @@ public class NetworkTest { 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 8449ca76d580..5096be221cbf 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.Test; 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 @@ public class StaticIpConfigurationTest { 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 @@ public class StaticIpConfigurationTest { 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 @@ public class StaticIpConfigurationTest { 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 @@ public class StaticIpConfigurationTest { 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 000000000000..8d055c93c4c5 --- /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 000000000000..f8eb40cccd35 --- /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 000000000000..36e9f8c94f6a --- /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 e19195322e1d..e9d5e6db1c7e 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.Test 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 000000000000..d4780d3a5d7b --- /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 000000000000..5144ca56bf28 --- /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 000000000000..d76ebf67ff1d --- /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 000000000000..8b52e81eea1e --- /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 000000000000..f38d32844230 --- /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 000000000000..c0cef8fe91fd --- /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 18c67688940a..8ff2de9777c9 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 androidx.test.runner.AndroidJUnit4; 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 @@ public class IpMemoryStoreTest { }; } + private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) { + return new NetworkAttributes.Builder() + .setGroupHint(hint) + .setMtu(mtu) + .build(); + } + + @Test + 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 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 testNetworkAttributes() { - // 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 testPrivateData() { - // TODO : implement this + 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 testFindL2Key() { - // TODO : implement this + 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 testIsSameNetwork() { - // TODO : implement this + 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 d8f01e9e22fe..f9dbdc7fbf3e 100644 --- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java +++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java @@ -55,9 +55,10 @@ public class IpConfigurationParcelableUtilTest { 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 @@ public class IpConfigurationParcelableUtilTest { 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 64672bd8ab76..3c5bb6a0c64f 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.Intent; 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.metrics.IpConnectivityLog; 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 @@ public class ConnectivityServiceTest { @Mock IDnsResolver mMockDnsResolver; @Mock INetd mMockNetd; @Mock NetworkStackClient mNetworkStack; + @Mock PackageManager mPackageManager; @Mock UserManager mUserManager; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = @@ -357,7 +362,12 @@ public class ConnectivityServiceTest { public Resources getResources() { return mResources; } - } + + @Override + public PackageManager getPackageManager() { + return mPackageManager; + } + } public void waitForIdle(int timeoutMsAsInt) { long timeoutMs = timeoutMsAsInt; @@ -557,6 +567,16 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { if (Looper.myLooper() == null) { Looper.prepare(); } + mockDefaultPackages(); FakeSettingsProvider.clearSettingsProvider(); mServiceContext = new MockContext(InstrumentationRegistry.getContext(), @@ -1284,7 +1305,24 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6196,7 +6246,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6210,7 +6259,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); @@ -6226,7 +6274,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6276,7 +6323,6 @@ public class ConnectivityServiceTest { } @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 d5b2c87ffe46..3a071667a542 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 android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME; 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 com.android.server.connectivity.metrics.nano.IpConnectivityLogClass; 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 @@ public class IpConnectivityMetricsTest { } @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 @@ public class IpConnectivityMetricsTest { 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 @@ public class IpConnectivityMetricsTest { 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 a83faf34776d..fb84611cb662 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 c856cc36d6f6..e883c6bed755 100755 --- a/tools/hiddenapi/generate_hiddenapi_lists.py +++ b/tools/hiddenapi/generate_hiddenapi_lists.py @@ -29,6 +29,7 @@ FLAG_GREYLIST = "greylist" 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 @@ FLAGS_API_LIST = [ 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 ef2914610f80..5a5703ed520c 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.lang.model.element.ElementKind.PACKAGE; 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 class SignatureBuilder { public SignatureBuilderException(String message) { super(message); } + public void report(Element offendingElement) { mMessager.printMessage(ERROR, getMessage(), offendingElement); } @@ -153,7 +155,7 @@ public class SignatureBuilder { /** * 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 @@ public class SignatureBuilder { 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 @@ public class SignatureBuilder { 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"); + } + 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); } - return signature; } 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 d368136c7081..5bb956a1fea2 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 @@ package android.processor.unsupportedappusage; 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 com.sun.tools.javac.util.Position; 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 @@ import javax.lang.model.element.TypeElement; /** * 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 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { 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 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { 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 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { /** * 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 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor { */ @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 4e52b8f23399..9eb9a92bd53f 100755 --- a/wifi/tests/runtests.sh +++ b/wifi/tests/runtests.sh @@ -19,7 +19,8 @@ set -x # print commands 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' |