diff options
310 files changed, 6565 insertions, 3121 deletions
diff --git a/Android.bp b/Android.bp index ec8636d40f8d..57f651319562 100644 --- a/Android.bp +++ b/Android.bp @@ -687,6 +687,7 @@ java_defaults { static_libs: [ "apex_aidl_interface-java", "framework-protos", + "game-driver-protos", "android.hidl.base-V1.0-java", "android.hardware.cas-V1.0-java", "android.hardware.contexthub-V1.0-java", diff --git a/Android.mk b/Android.mk index c58f7af1d7d5..9bda2dc6d69a 100644 --- a/Android.mk +++ b/Android.mk @@ -32,27 +32,6 @@ ifneq ($(ANDROID_BUILD_EMBEDDED),true) # ============================================================ include $(CLEAR_VARS) -aidl_parcelables := -define stubs-to-aidl-parcelables - gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/$1.aidl - aidl_parcelables += $$(gen) - $$(gen): $(call java-lib-header-files,$1) $(HOST_OUT_EXECUTABLES)/sdkparcelables - @echo Extract SDK parcelables: $$@ - rm -f $$@ - $(HOST_OUT_EXECUTABLES)/sdkparcelables $$< $$@ -endef - -$(foreach stubs,android_stubs_current android_test_stubs_current android_system_stubs_current,\ - $(eval $(call stubs-to-aidl-parcelables,$(stubs)))) - -gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl -.KATI_RESTAT: $(gen) -$(gen): $(aidl_parcelables) - @echo Combining SDK parcelables: $@ - rm -f $@.tmp - cat $^ | sort -u > $@.tmp - $(call commit-change-for-toc,$@) - # This is used by ide.mk as the list of source files that are # always included. INTERNAL_SDK_SOURCE_DIRS := $(addprefix $(LOCAL_PATH)/,$(dirs_to_document)) diff --git a/api/current.txt b/api/current.txt index d44829ecb7a0..4c015b6b855f 100755 --- a/api/current.txt +++ b/api/current.txt @@ -8734,8 +8734,8 @@ package android.bluetooth.le { method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]); method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]); method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]); - method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid); - method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid, android.os.ParcelUuid); + method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid); + method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid); method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid); method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid); } @@ -20931,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; 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 dc5ff8f229c2..21d761fbac2f 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -923,6 +923,7 @@ package android.net.util { package android.os { public static class Build.VERSION { + field public static final String[] ACTIVE_CODENAMES; field public static final int FIRST_SDK_INT; field public static final int RESOURCES_SDK_INT; } @@ -1200,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 564e9186b868..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,8 +134,8 @@ message Atom { PhoneStateChanged phone_state_changed = 95; LowMemReported low_mem_reported = 81; ThermalThrottlingStateChanged thermal_throttling = 86; - NetworkDnsEventReported network_dns_event_reported = 116; - DataStallEvent data_stall_event = 121; + 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; BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127; @@ -165,7 +166,7 @@ message Atom { BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167; ProcessStartTime process_start_time = 169; BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171; - NetworkStackReported network_stack_reported = 182; + NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"]; } // Pulled events will start at field 10000. @@ -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/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp deleted file mode 100644 index 01c75873fdf9..000000000000 --- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define DEBUG false // STOPSHIP if true -#include "Log.h" - -#include <sstream> -#include "MemoryLeakTrackUtil.h" - -/* - * The code here originally resided in MediaPlayerService.cpp - */ - -// Figure out the abi based on defined macros. -#if defined(__arm__) -#define ABI_STRING "arm" -#elif defined(__aarch64__) -#define ABI_STRING "arm64" -#elif defined(__mips__) && !defined(__LP64__) -#define ABI_STRING "mips" -#elif defined(__mips__) && defined(__LP64__) -#define ABI_STRING "mips64" -#elif defined(__i386__) -#define ABI_STRING "x86" -#elif defined(__x86_64__) -#define ABI_STRING "x86_64" -#else -#error "Unsupported ABI" -#endif - -extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count); - -namespace android { -namespace os { -namespace statsd { - -extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, size_t* infoSize, - size_t* totalMemory, size_t* backtraceSize); - -extern "C" void free_malloc_leak_info(uint8_t* info); - -std::string dumpMemInfo(size_t limit) { - uint8_t* info; - size_t overallSize; - size_t infoSize; - size_t totalMemory; - size_t backtraceSize; - get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize); - - size_t count; - if (info == nullptr || overallSize == 0 || infoSize == 0 || - (count = overallSize / infoSize) == 0) { - VLOG("no malloc info, libc.debug.malloc.program property should be set"); - return std::string(); - } - - std::ostringstream oss; - oss << totalMemory << " bytes in " << count << " allocations\n"; - oss << " ABI: '" ABI_STRING "'" - << "\n\n"; - if (count > limit) count = limit; - - // The memory is sorted based on total size which is useful for finding - // worst memory offenders. For diffs, sometimes it is preferable to sort - // based on the backtrace. - for (size_t i = 0; i < count; i++) { - struct AllocEntry { - size_t size; // bit 31 is set if this is zygote allocated memory - size_t allocations; - uintptr_t backtrace[]; - }; - - const AllocEntry* const e = (AllocEntry*)(info + i * infoSize); - - oss << (e->size * e->allocations) << " bytes ( " << e->size << " bytes * " << e->allocations - << " allocations )\n"; - oss << backtrace_string(e->backtrace, backtraceSize) << "\n"; - } - oss << "\n"; - free_malloc_leak_info(info); - return oss.str(); -} - -} // namespace statsd -} // namespace os -} // namespace android
\ No newline at end of file diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f453289b4bc5..d9c82ea31537 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1003,9 +1003,8 @@ public final class ActivityThread extends ClientTransactionHandler { } public void updateHttpProxy() { - final ConnectivityManager cm = ConnectivityManager.from( + ActivityThread.updateHttpProxy( getApplication() != null ? getApplication() : getSystemContext()); - Proxy.setHttpProxySystemProperty(cm.getDefaultProxy()); } public void processInBackground() { @@ -6690,6 +6689,11 @@ public final class ActivityThread extends ClientTransactionHandler { return thread; } + public static void updateHttpProxy(@NonNull Context context) { + final ConnectivityManager cm = ConnectivityManager.from(context); + Proxy.setHttpProxySystemProperty(cm.getDefaultProxy()); + } + @UnsupportedAppUsage public final void installSystemProviders(List<ProviderInfo> providers) { if (providers != null) { 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/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 1e1280105964..34c7372202ee 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -56,7 +56,8 @@ import java.util.UUID; * returned by {@link BluetoothAdapter#getBondedDevices() * BluetoothAdapter.getBondedDevices()}. You can then open a * {@link BluetoothSocket} for communication with the remote device, using - * {@link #createRfcommSocketToServiceRecord(UUID)}. + * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using + * {@link #createL2capChannel(int)} over Bluetooth LE. * * <p class="note"><strong>Note:</strong> * Requires the {@link android.Manifest.permission#BLUETOOTH} permission. 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/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java index 4e886250b4fa..c06b837a9ee3 100644 --- a/core/java/android/bluetooth/BluetoothServerSocket.java +++ b/core/java/android/bluetooth/BluetoothServerSocket.java @@ -35,21 +35,28 @@ import java.io.IOException; * On the client side, use a single {@link BluetoothSocket} to both initiate * an outgoing connection and to manage the connection. * - * <p>The most common type of Bluetooth socket is RFCOMM, which is the type - * supported by the Android APIs. RFCOMM is a connection-oriented, streaming - * transport over Bluetooth. It is also known as the Serial Port Profile (SPP). + * <p>For Bluetooth BR/EDR, the most common type of socket is RFCOMM, which is the type supported by + * the Android APIs. RFCOMM is a connection-oriented, streaming transport over Bluetooth BR/EDR. It + * is also known as the Serial Port Profile (SPP). To create a listening + * {@link BluetoothServerSocket} that's ready for incoming Bluetooth BR/EDR connections, use {@link + * BluetoothAdapter#listenUsingRfcommWithServiceRecord + * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}. * - * <p>To create a listening {@link BluetoothServerSocket} that's ready for - * incoming connections, use - * {@link BluetoothAdapter#listenUsingRfcommWithServiceRecord - * BluetoothAdapter.listenUsingRfcommWithServiceRecord()}. Then call - * {@link #accept()} to listen for incoming connection requests. This call - * will block until a connection is established, at which point, it will return - * a {@link BluetoothSocket} to manage the connection. Once the {@link - * BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on - * the {@link BluetoothServerSocket} when it's no longer needed for accepting - * connections. Closing the {@link BluetoothServerSocket} will <em>not</em> - * close the returned {@link BluetoothSocket}. + * <p>For Bluetooth LE, the socket uses LE Connection-oriented Channel (CoC). LE CoC is a + * connection-oriented, streaming transport over Bluetooth LE and has a credit-based flow control. + * Correspondingly, use {@link BluetoothAdapter#listenUsingL2capChannel + * BluetoothAdapter.listenUsingL2capChannel()} to create a listening {@link BluetoothServerSocket} + * that's ready for incoming Bluetooth LE CoC connections. For LE CoC, you can use {@link #getPsm()} + * to get the protocol/service multiplexer (PSM) value that the peer needs to use to connect to your + * socket. + * + * <p> After the listening {@link BluetoothServerSocket} is created, call {@link #accept()} to + * listen for incoming connection requests. This call will block until a connection is established, + * at which point, it will return a {@link BluetoothSocket} to manage the connection. Once the + * {@link BluetoothSocket} is acquired, it's a good idea to call {@link #close()} on the {@link + * BluetoothServerSocket} when it's no longer needed for accepting + * connections. Closing the {@link BluetoothServerSocket} will <em>not</em> close the returned + * {@link BluetoothSocket}. * * <p>{@link BluetoothServerSocket} is thread * safe. In particular, {@link #close} will always immediately abort ongoing diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index c5d435b76139..66d1da8909cd 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -16,6 +16,7 @@ package android.bluetooth.le; +import android.annotation.NonNull; import android.annotation.Nullable; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -586,7 +587,8 @@ public final class ScanFilter implements Parcelable { /** * Set filter on service solicitation uuid. */ - public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid) { + public @NonNull Builder setServiceSolicitationUuid( + @Nullable ParcelUuid serviceSolicitationUuid) { mServiceSolicitationUuid = serviceSolicitationUuid; return this; } @@ -601,8 +603,9 @@ public final class ScanFilter implements Parcelable { * @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but * {@code serviceSolicitationUuidMask} is not {@code null}. */ - public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid, - ParcelUuid solicitationUuidMask) { + public @NonNull Builder setServiceSolicitationUuid( + @Nullable ParcelUuid serviceSolicitationUuid, + @Nullable ParcelUuid solicitationUuidMask) { if (mServiceSolicitationUuidMask != null && mServiceSolicitationUuid == null) { throw new IllegalArgumentException( "SolicitationUuid is null while SolicitationUuidMask is not null!"); 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/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/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d6774d47b49e..b5a2a16c7ff5 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -72,4 +72,8 @@ interface IIpSecService int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); + + int lockEncapSocketForNattKeepalive(int encapSocketResourceId, int requesterUid); + + void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid); } diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl index bab6ae8e7409..d586038ebb89 100644 --- a/core/java/android/net/ITestNetworkManager.aidl +++ b/core/java/android/net/ITestNetworkManager.aidl @@ -17,6 +17,7 @@ package android.net; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.TestNetworkInterface; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -31,7 +32,8 @@ interface ITestNetworkManager TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs); TestNetworkInterface createTapInterface(); - void setupTestNetwork(in String iface, in IBinder binder); + void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered, + in IBinder binder); void teardownTestNetwork(int netId); } 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/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java index e274005eb9d1..4ac4a69e4b1b 100644 --- a/core/java/android/net/TestNetworkManager.java +++ b/core/java/android/net/TestNetworkManager.java @@ -56,6 +56,26 @@ public class TestNetworkManager { /** * Sets up a capability-limited, testing-only network for a given interface * + * @param lp The LinkProperties for the TestNetworkService to use for this test network. Note + * that the interface name and link addresses will be overwritten, and the passed-in values + * discarded. + * @param isMetered Whether or not the network should be considered metered. + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + public void setupTestNetwork( + @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { + Preconditions.checkNotNull(lp, "Invalid LinkProperties"); + try { + mService.setupTestNetwork(lp.getInterfaceName(), lp, isMetered, binder); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets up a capability-limited, testing-only network for a given interface + * * @param iface the name of the interface to be used for the Network LinkProperties. * @param binder A binder object guarding the lifecycle of this test network. * @hide @@ -63,7 +83,7 @@ public class TestNetworkManager { @TestApi public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { try { - mService.setupTestNetwork(iface, binder); + mService.setupTestNetwork(iface, null, true, binder); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java index 5b674067192e..cf08b653d0f4 100644 --- a/core/java/android/net/UrlQuerySanitizer.java +++ b/core/java/android/net/UrlQuerySanitizer.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Locale; import java.util.Set; import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @@ -837,15 +839,11 @@ public class UrlQuerySanitizer { * @param string the escaped string * @return the unescaped string. */ + private static final Pattern plusOrPercent = Pattern.compile("[+%]"); public String unescape(String string) { - // Early exit if no escaped characters. - int firstEscape = string.indexOf('%'); - if ( firstEscape < 0) { - firstEscape = string.indexOf('+'); - if (firstEscape < 0) { - return string; - } - } + final Matcher matcher = plusOrPercent.matcher(string); + if (!matcher.find()) return string; + final int firstEscape = matcher.start(); int length = string.length(); @@ -855,8 +853,7 @@ public class UrlQuerySanitizer { char c = string.charAt(i); if (c == '+') { c = ' '; - } - else if ( c == '%' && i + 2 < length) { + } else if (c == '%' && i + 2 < length) { char c1 = string.charAt(i + 1); char c2 = string.charAt(i + 2); if (isHexDigit(c1) && isHexDigit(c2)) { 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/Build.java b/core/java/android/os/Build.java index 1c319fb4ea36..d3bed02a4b47 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -287,6 +287,7 @@ public class Build { /** * @hide */ + @TestApi @UnsupportedAppUsage public static final String[] ACTIVE_CODENAMES = "REL".equals(ALL_CODENAMES[0]) ? new String[0] : ALL_CODENAMES; diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 606c8f398563..1aaee18914a2 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -28,11 +28,11 @@ import android.util.Log; import dalvik.system.VMRuntime; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** @hide */ public class GraphicsEnvironment { @@ -49,7 +49,7 @@ public class GraphicsEnvironment { private static final boolean DEBUG = false; private static final String TAG = "GraphicsEnvironment"; private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; - private static final String GUP_WHITELIST_FILENAME = "whitelist.txt"; + private static final String GAME_DRIVER_WHITELIST_ALL = "*"; private ClassLoader mClassLoader; private String mLayerPath; @@ -98,15 +98,15 @@ public class GraphicsEnvironment { if (isDebuggable(context)) { - int enable = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); + final int enable = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0); if (enable != 0) { - String gpuDebugApp = Settings.Global.getString(context.getContentResolver(), - Settings.Global.GPU_DEBUG_APP); + final String gpuDebugApp = Settings.Global.getString(context.getContentResolver(), + Settings.Global.GPU_DEBUG_APP); - String packageName = context.getPackageName(); + final String packageName = context.getPackageName(); if ((gpuDebugApp != null && packageName != null) && (!gpuDebugApp.isEmpty() && !packageName.isEmpty()) @@ -136,37 +136,29 @@ public class GraphicsEnvironment { setLayerPaths(mClassLoader, layerPaths); } + private static List<String> getGlobalSettingsString(Bundle bundle, String globalSetting) { + List<String> valueList = null; + final String settingsValue = bundle.getString(globalSetting); + + if (settingsValue != null) { + valueList = new ArrayList<>(Arrays.asList(settingsValue.split(","))); + } else { + valueList = new ArrayList<>(); + } + + return valueList; + } + /** * Choose whether the current process should use the builtin or an updated driver. */ private static void chooseDriver(Context context, Bundle coreSettings) { - String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + final String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); if (driverPackageName == null || driverPackageName.isEmpty()) { return; } - // To minimize risk of driver updates crippling the device beyond user repair, never use an - // updated driver for privileged or non-updated system apps. Presumably pre-installed apps - // were tested thoroughly with the pre-installed driver. - ApplicationInfo ai = context.getApplicationInfo(); - if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { - if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); - return; - } - - String applicationPackageName = context.getPackageName(); - String devOptInApplicationName = coreSettings.getString( - Settings.Global.GUP_DEV_OPT_IN_APPS); - boolean devOptIn = applicationPackageName.equals(devOptInApplicationName); - boolean whitelisted = onWhitelist(context, driverPackageName, ai.packageName); - if (!devOptIn && !whitelisted) { - if (DEBUG) { - Log.w(TAG, applicationPackageName + " is not on the whitelist."); - } - return; - } - - ApplicationInfo driverInfo; + final ApplicationInfo driverInfo; try { driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY); @@ -184,7 +176,59 @@ public class GraphicsEnvironment { return; } - String abi = chooseAbi(driverInfo); + // To minimize risk of driver updates crippling the device beyond user repair, never use an + // updated driver for privileged or non-updated system apps. Presumably pre-installed apps + // were tested thoroughly with the pre-installed driver. + final ApplicationInfo ai = context.getApplicationInfo(); + if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { + if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); + return; + } + + // GAME_DRIVER_ALL_APPS + // 0: Default (Invalid values fallback to default as well) + // 1: All apps use Game Driver + // 2: All apps use system graphics driver + final int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); + if (gameDriverAllApps == 2) { + if (DEBUG) { + Log.w(TAG, "Game Driver is turned off on this device"); + } + return; + } + + if (gameDriverAllApps != 1) { + // GAME_DRIVER_OPT_OUT_APPS has higher priority than GAME_DRIVER_OPT_IN_APPS + if (getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_OUT_APPS) + .contains(ai.packageName)) { + if (DEBUG) { + Log.w(TAG, ai.packageName + " opts out from Game Driver."); + } + return; + } + final boolean isOptIn = + getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS) + .contains(ai.packageName); + final List<String> whitelist = getGlobalSettingsString(coreSettings, + Settings.Global.GAME_DRIVER_WHITELIST); + if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0 + && !whitelist.contains(ai.packageName)) { + if (DEBUG) { + Log.w(TAG, ai.packageName + " is not on the whitelist."); + } + return; + } + + // If the application is not opted-in and check whether it's on the blacklist, + // terminate early if it's on the blacklist and fallback to system driver. + if (!isOptIn + && getGlobalSettingsString(coreSettings, Settings.Global.GAME_DRIVER_BLACKLIST) + .contains(ai.packageName)) { + return; + } + } + + final String abi = chooseAbi(driverInfo); if (abi == null) { if (DEBUG) { // This is the normal case for the pre-installed empty driver package, don't spam @@ -195,16 +239,23 @@ public class GraphicsEnvironment { return; } - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(driverInfo.nativeLibraryDir) .append(File.pathSeparator); sb.append(driverInfo.sourceDir) .append("!/lib/") .append(abi); - String paths = sb.toString(); + final String paths = sb.toString(); - if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths); - setDriverPath(paths); + final String sphalLibraries = + coreSettings.getString(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES); + + if (DEBUG) { + Log.v(TAG, + "gfx driver package search path: " + paths + + ", required sphal libraries: " + sphalLibraries); + } + setDriverPathAndSphalLibraries(paths, sphalLibraries); } /** @@ -218,7 +269,7 @@ public class GraphicsEnvironment { * Should only be called after chooseDriver(). */ public static void earlyInitEGL() { - Thread eglInitThread = new Thread( + final Thread eglInitThread = new Thread( () -> { EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); }, @@ -227,7 +278,7 @@ public class GraphicsEnvironment { } private static String chooseAbi(ApplicationInfo ai) { - String isa = VMRuntime.getCurrentInstructionSet(); + final String isa = VMRuntime.getCurrentInstructionSet(); if (ai.primaryCpuAbi != null && isa.equals(VMRuntime.getInstructionSet(ai.primaryCpuAbi))) { return ai.primaryCpuAbi; @@ -239,32 +290,7 @@ public class GraphicsEnvironment { return null; } - private static boolean onWhitelist(Context context, String driverPackageName, - String applicationPackageName) { - try { - Context driverContext = context.createPackageContext(driverPackageName, - Context.CONTEXT_RESTRICTED); - AssetManager assets = driverContext.getAssets(); - InputStream stream = assets.open(GUP_WHITELIST_FILENAME); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - for (String packageName; (packageName = reader.readLine()) != null; ) { - if (packageName.equals(applicationPackageName)) { - return true; - } - } - } catch (PackageManager.NameNotFoundException e) { - if (DEBUG) { - Log.w(TAG, "driver package '" + driverPackageName + "' not installed"); - } - } catch (IOException e) { - if (DEBUG) { - Log.w(TAG, "Failed to load whitelist driver package, abort."); - } - } - return false; - } - private static native void setLayerPaths(ClassLoader classLoader, String layerPaths); private static native void setDebugLayers(String layers); - private static native void setDriverPath(String path); + private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries); } 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/CallLog.java b/core/java/android/provider/CallLog.java index ef28f07e817f..0827fd6e725e 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -967,6 +967,23 @@ public class CallLog { // spam the call log with its own entries, causing entries from Telephony to be // removed. final Uri result = resolver.insert(uri, values); + if (result != null) { + String lastPathSegment = result.getLastPathSegment(); + // When inserting into the call log, if ContentProvider#insert detect an appops + // denial a non-null "silent rejection" URI is returned which ends in 0. + // Example: content://call_log/calls/0 + // The 0 in the last part of the path indicates a fake call id of 0. + // A denial when logging calls from the platform is bad; there is no other + // logging to indicate that this has happened so we will check for that scenario + // here and log a warning so we have a hint as to what is going on. + if (lastPathSegment != null && lastPathSegment.equals("0")) { + Log.w(LOG_TAG, "Failed to insert into call log due to appops denial;" + + " resultUri=" + result); + } + } else { + Log.w(LOG_TAG, "Failed to insert into call log; null result uri."); + } + if (values.containsKey(PHONE_ACCOUNT_ID) && !TextUtils.isEmpty(values.getAsString(PHONE_ACCOUNT_ID)) && values.containsKey(PHONE_ACCOUNT_COMPONENT_NAME) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index bf33e0619304..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"; /** @@ -11446,16 +11424,55 @@ public final class Settings { public static final String GPU_DEBUG_APP = "gpu_debug_app"; /** - * Apps that are selected to use Game Update Package. + * Game Driver global preference for all Apps. + * 0 = Default + * 1 = All Apps use Game Driver + * 2 = All Apps use system graphics driver + * @hide + */ + public static final String GAME_DRIVER_ALL_APPS = "game_driver_all_apps"; + + /** + * List of Apps selected to use Game Driver. + * i.e. <pkg1>,<pkg2>,...,<pkgN> + * @hide + */ + public static final String GAME_DRIVER_OPT_IN_APPS = "game_driver_opt_in_apps"; + + /** + * List of Apps selected not to use Game Driver. + * i.e. <pkg1>,<pkg2>,...,<pkgN> + * @hide + */ + public static final String GAME_DRIVER_OPT_OUT_APPS = "game_driver_opt_out_apps"; + + /** + * Apps on the blacklist that are forbidden to use Game Driver. + * @hide + */ + public static final String GAME_DRIVER_BLACKLIST = "game_driver_blacklist"; + + /** + * List of blacklists, each blacklist is a blacklist for a specific version of Game Driver. + * @hide + */ + public static final String GAME_DRIVER_BLACKLISTS = "game_driver_blacklists"; + + /** + * Apps on the whitelist that are allowed to use Game Driver. + * The string is a list of application package names, seperated by comma. + * i.e. <apk1>,<apk2>,...,<apkN> * @hide */ - public static final String GUP_DEV_OPT_IN_APPS = "gup_dev_opt_in_apps"; + public static final String GAME_DRIVER_WHITELIST = "game_driver_whitelist"; /** - * Apps on the black list that are forbidden to useGame Update Package. + * List of libraries in sphal accessible by Game Driver + * The string is a list of library names, separated by colon. + * i.e. <lib1>:<lib2>:...:<libN> * @hide */ - public static final String GUP_BLACK_LIST = "gup_black_list"; + public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries"; /** * Ordered GPU debug layer list 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_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp index e22f581e14e2..076e99dd1fba 100644 --- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp +++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp @@ -22,6 +22,9 @@ #include <jni.h> #include "core_jni_helpers.h" +#include <android-base/logging.h> +#include <bionic_malloc.h> + #include <utils/Log.h> #include <utils/String8.h> @@ -30,11 +33,6 @@ #include <sys/types.h> #include <sys/stat.h> -extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, - size_t* infoSize, size_t* totalMemory, size_t* backtraceSize); - -extern "C" void free_malloc_leak_info(uint8_t* info); - #define DDMS_HEADER_SIGNATURE 0x812345dd #define DDMS_VERSION 2 @@ -78,9 +76,16 @@ static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) { ReadFile("/proc/self/maps", maps); header.mapSize = maps.size(); - uint8_t* allocBytes; - get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize, - &header.totalMemory, &header.backtraceSize); + android_mallopt_leak_info_t leak_info; + if (!android_mallopt(M_GET_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info))) { + PLOG(ERROR) << "*** Failed to get malloc leak info"; + return nullptr; + } + + header.allocSize = leak_info.overall_size; + header.allocInfoSize = leak_info.info_size; + header.totalMemory = leak_info.total_memory; + header.backtraceSize = leak_info.backtrace_size; ALOGD("*** mapSize: %zu allocSize: %zu allocInfoSize: %zu totalMemory: %zu", header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory); @@ -98,10 +103,10 @@ static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) { env->SetByteArrayRegion(array, sizeof(header), maps.size(), reinterpret_cast<const jbyte*>(maps.string())); env->SetByteArrayRegion(array, sizeof(header) + maps.size(), - header.allocSize, reinterpret_cast<jbyte*>(allocBytes)); + header.allocSize, reinterpret_cast<jbyte*>(leak_info.buffer)); } - free_malloc_leak_info(allocBytes); + android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info)); return array; } 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_Debug.cpp b/core/jni/android_os_Debug.cpp index 8be617f08ac3..62c4d76ed455 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -33,8 +33,10 @@ #include <iomanip> #include <string> +#include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> +#include <bionic_malloc.h> #include <debuggerd/client.h> #include <log/log.h> #include <utils/misc.h> @@ -960,9 +962,6 @@ static bool openFile(JNIEnv* env, jobject fileDescriptor, UniqueFile& fp) return true; } -/* pulled out of bionic */ -extern "C" void write_malloc_leak_info(FILE* fp); - /* * Dump the native heap, writing human-readable output to the specified * file descriptor. @@ -978,8 +977,11 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject, ALOGD("Native heap dump starting...\n"); // Formatting of the native heap dump is handled by malloc debug itself. // See https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md#backtrace-heap-dump-format - write_malloc_leak_info(fp.get()); - ALOGD("Native heap dump complete.\n"); + if (android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp.get(), sizeof(FILE*))) { + ALOGD("Native heap dump complete.\n"); + } else { + PLOG(ERROR) << "Failed to write native heap dump to file"; + } } /* diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index dfa5de6b65c6..b95d500212d4 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -23,9 +23,12 @@ namespace { -void setDriverPath(JNIEnv* env, jobject clazz, jstring path) { +void setDriverPathAndSphalLibraries_native(JNIEnv* env, jobject clazz, jstring path, + jstring sphalLibraries) { ScopedUtfChars pathChars(env, path); - android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str()); + ScopedUtfChars sphalLibrariesChars(env, sphalLibraries); + android::GraphicsEnv::getInstance().setDriverPathAndSphalLibraries(pathChars.c_str(), + sphalLibrariesChars.c_str()); } void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) { @@ -43,7 +46,7 @@ void setDebugLayers_native(JNIEnv* env, jobject clazz, jstring layers) { } const JNINativeMethod g_methods[] = { - { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) }, + { "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPathAndSphalLibraries_native) }, { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) }, { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) }, }; 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/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 7c9176aa9eb7..a44ec9a911be 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -384,11 +384,26 @@ message GlobalSettingsProto { // App allowed to load GPU debug layers. optional SettingProto debug_app = 1; optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; - // Apps opt in to load graphics driver from Game Update Package - // instead of native graphcis driver through developer options. - optional SettingProto gup_dev_opt_in_apps = 8; - // Apps on the black list that are forbidden to useGame Update Package. - optional SettingProto gup_black_list = 9; + // Game Driver - global preference for all Apps + // 0 = Default + // 1 = All Apps use Game Driver + // 2 = All Apps use system graphics driver + optional SettingProto game_driver_all_apps = 8; + // Game Driver - List of Apps selected to use Game Driver + // i.e. <pkg1>,<pkg2>,...,<pkgN> + optional SettingProto game_driver_opt_in_apps = 9; + // Game Driver - List of Apps selected not to use Game Driver + // i.e. <pkg1>,<pkg2>,...,<pkgN> + optional SettingProto game_driver_opt_out_apps = 10; + // Game Driver - List of Apps that are forbidden to use Game Driver + optional SettingProto game_driver_blacklist = 11; + // Game Driver - List of Apps that are allowed to use Game Driver + optional SettingProto game_driver_whitelist = 12; + // Game Driver - List of blacklists, each blacklist is a blacklist for + // a specific Game Driver version + optional SettingProto game_driver_blacklists = 14; + // Game Driver - List of libraries in sphal accessible by Game Driver + optional SettingProto game_driver_sphal_libraries = 16; } optional Gpu gpu = 59; 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/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 7b729284a063..76356ed572c7 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -444,8 +444,13 @@ public class SettingsBackupTest { Settings.Global.ENABLE_GPU_DEBUG_LAYERS, Settings.Global.GPU_DEBUG_APP, Settings.Global.GPU_DEBUG_LAYERS, - Settings.Global.GUP_DEV_OPT_IN_APPS, - Settings.Global.GUP_BLACK_LIST, + Settings.Global.GAME_DRIVER_ALL_APPS, + Settings.Global.GAME_DRIVER_OPT_IN_APPS, + Settings.Global.GAME_DRIVER_OPT_OUT_APPS, + Settings.Global.GAME_DRIVER_BLACKLISTS, + Settings.Global.GAME_DRIVER_BLACKLIST, + Settings.Global.GAME_DRIVER_WHITELIST, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS, diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 28099a16cda5..c17f076d2b71 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -33,12 +33,18 @@ 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"/> <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/> + <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> </privapp-permissions> <privapp-permissions package="com.android.defcontainer"> @@ -203,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/graphics/proto/Android.bp b/graphics/proto/Android.bp new file mode 100644 index 000000000000..1d06348fb02f --- /dev/null +++ b/graphics/proto/Android.bp @@ -0,0 +1,11 @@ +java_library_static { + name: "game-driver-protos", + host_supported: true, + proto: { + type: "lite", + }, + srcs: ["game_driver.proto"], + no_framework_libs: true, + jarjar_rules: "jarjar-rules.txt", + sdk_version: "28", +} diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/graphics/proto/game_driver.proto index 444ed92cc9bb..fd7ffccac24c 100644 --- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h +++ b/graphics/proto/game_driver.proto @@ -1,11 +1,11 @@ /* - * Copyright 2017, The Android Open Source Project + * 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 + * 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, @@ -13,21 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#pragma once -#include <iostream> +syntax = "proto2"; -namespace android { -namespace os { -namespace statsd { -/* - * Dump the heap memory of the calling process, sorted by total size - * (allocation size * number of allocations). - * - * limit is the number of unique allocations to return. - */ -extern std::string dumpMemInfo(size_t limit); +package android.gamedriver; + +option java_package = "android.gamedriver"; +option java_outer_classname = "GameDriverProto"; + +message Blacklist { + optional int64 version_code = 1; + repeated string package_names = 2; +} -} // namespace statsd -} // namespace os -} // namespace android
\ No newline at end of file +message Blacklists { + repeated Blacklist blacklists = 1; +} diff --git a/graphics/proto/jarjar-rules.txt b/graphics/proto/jarjar-rules.txt new file mode 100644 index 000000000000..4e4063706352 --- /dev/null +++ b/graphics/proto/jarjar-rules.txt @@ -0,0 +1 @@ +rule com.google.protobuf.** com.android.framework.protobuf.@1 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/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/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..ffd4d9d9acc6 100644 --- a/packages/CaptivePortalLogin/AndroidManifest.xml +++ b/packages/CaptivePortalLogin/AndroidManifest.xml @@ -26,6 +26,7 @@ <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" /> diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp index 5817118bc861..62de2ba45455 100644 --- a/packages/NetworkStack/Android.bp +++ b/packages/NetworkStack/Android.bp @@ -37,6 +37,7 @@ android_library { "src/**/*.java", ":framework-networkstack-shared-srcs", ":services-networkstack-shared-srcs", + ":statslog-networkstack-java-gen", ], static_libs: [ "androidx.annotation_annotation", @@ -55,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", @@ -78,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", @@ -104,3 +117,11 @@ android_app { certificate: "networkstack", manifest: "AndroidManifest.xml", } + +genrule { + name: "statslog-networkstack-java-gen", + tools: ["stats-log-api-gen"], + cmd: "$(location stats-log-api-gen) --java $(out) --module network_stack" + + " --javaPackage com.android.networkstack.metrics --javaClass NetworkStackStatsLog", + out: ["com/android/networkstack/metrics/NetworkStackStatsLog.java"], +} 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/res/values/config.xml b/packages/NetworkStack/res/values/config.xml index 704788d7d7e2..478ed6b06596 100644 --- a/packages/NetworkStack/res/values/config.xml +++ b/packages/NetworkStack/res/values/config.xml @@ -7,6 +7,9 @@ values are meant to be the default when no other configuration is specified. --> + <!-- DNS probe timeout for network validation. Enough for 3 DNS queries 5 seconds apart. --> + <integer name="default_captive_portal_dns_probe_timeout">12500</integer> + <!-- HTTP URL for network validation, to use for detecting captive portals. --> <string name="default_captive_portal_http_url" translatable="false">http://connectivitycheck.gstatic.com/generate_204</string> @@ -27,6 +30,7 @@ <!-- Configuration hooks for the above settings. Empty by default but may be overridden by RROs. --> + <integer name="config_captive_portal_dns_probe_timeout"></integer> <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook --> <string name="config_captive_portal_http_url" translatable="false"></string> <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook --> 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/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java index d21b5f7853bb..b8ab94ce3830 100644 --- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java +++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java @@ -647,4 +647,9 @@ public class DhcpServer extends IDhcpServer.Stub { } } } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java index 80d139cb6153..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,10 +558,20 @@ 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); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } public String getInterfaceName() { @@ -686,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); } /** @@ -1602,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/android/net/metrics/DataStallDetectionStats.java b/packages/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java index 225dc0f4bfdc..2523ecd4ea20 100644 --- a/packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java +++ b/packages/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.net.metrics; +package com.android.networkstack.metrics; import android.annotation.NonNull; import android.annotation.Nullable; diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/com/android/networkstack/metrics/DataStallStatsUtils.java index c96411e1e39f..93089017fd47 100644 --- a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java +++ b/packages/NetworkStack/src/com/android/networkstack/metrics/DataStallStatsUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.net.metrics; +package com.android.networkstack.metrics; import android.annotation.NonNull; import android.annotation.Nullable; @@ -41,7 +41,6 @@ public class DataStallStatsUtils { private static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) { if (result == null) return DataStallEventProto.INVALID; - // TODO: Add partial connectivity support. if (result.isSuccessful()) { return DataStallEventProto.VALID; } else if (result.isPortal()) { @@ -63,6 +62,12 @@ public class DataStallStatsUtils { Log.d(TAG, "write: " + stats + " with result: " + validationResult + ", dns: " + HexDump.toHexString(stats.mDns)); } - // TODO(b/124613085): Send to Statsd once the public StatsLog API is ready. + NetworkStackStatsLog.write(NetworkStackStatsLog.DATA_STALL_EVENT, + stats.mEvaluationType, + validationResult, + stats.mNetworkType, + stats.mWifiInfo, + stats.mCellularInfo, + stats.mDns); } } diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java index a0a90fde518f..a6d74842f631 100644 --- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java +++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java @@ -251,6 +251,11 @@ public class NetworkStackService extends Service { } } } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } private static class NetworkMonitorImpl extends INetworkMonitor.Stub { @@ -325,5 +330,10 @@ public class NetworkStackService extends Service { checkNetworkStackCallingPermission(); mNm.notifyNetworkCapabilitiesChanged(nc); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } } diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java index d88e3dc84848..bacec78e5699 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; @@ -59,6 +65,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.DnsResolver; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.LinkProperties; @@ -69,8 +76,6 @@ import android.net.TrafficStats; import android.net.Uri; import android.net.captiveportal.CaptivePortalProbeResult; import android.net.captiveportal.CaptivePortalProbeSpec; -import android.net.metrics.DataStallDetectionStats; -import android.net.metrics.DataStallStatsUtils; import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; import android.net.metrics.ValidationProbeEvent; @@ -106,6 +111,8 @@ import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.internal.util.TrafficStatsConstants; import com.android.networkstack.R; +import com.android.networkstack.metrics.DataStallDetectionStats; +import com.android.networkstack.metrics.DataStallStatsUtils; import java.io.IOException; import java.net.HttpURLConnection; @@ -122,6 +129,7 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; /** @@ -136,8 +144,13 @@ public class NetworkMonitor extends StateMachine { + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/60.0.3112.32 Safari/537.36"; + @VisibleForTesting + static final String CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT = + "captive_portal_dns_probe_timeout"; + private static final int SOCKET_TIMEOUT_MS = 10000; private static final int PROBE_TIMEOUT_MS = 3000; + enum EvaluationResult { VALIDATED(true), CAPTIVE_PORTAL(false); @@ -1168,10 +1181,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() { @@ -1181,8 +1194,34 @@ 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() { + return getIntSetting(mContext, R.integer.config_captive_portal_dns_probe_timeout, + CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT, + R.integer.default_captive_portal_dns_probe_timeout); + } + + /** + * Gets an integer setting from resources or device config + * + * configResource is used if set, followed by device config if set, followed by defaultResource. + * If none of these are set then an exception is thrown. + * + * TODO: move to a common location such as a ConfigUtils class. + * TODO(b/130324939): test that the resources can be overlayed by an RRO package. + */ + @VisibleForTesting + int getIntSetting(@NonNull final Context context, @StringRes int configResource, + @NonNull String symbol, @StringRes int defaultResource) { + final Resources res = context.getResources(); + try { + return res.getInteger(configResource); + } catch (Resources.NotFoundException e) { + return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY, + symbol, res.getInteger(defaultResource)); + } } /** @@ -1194,8 +1233,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() { @@ -1224,8 +1262,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)) { @@ -1446,6 +1484,45 @@ public class NetworkMonitor extends StateMachine { return sendHttpProbe(url, probeType, null); } + /** Do a DNS lookup for the given server, or throw UnknownHostException after timeoutMs */ + @VisibleForTesting + protected InetAddress[] sendDnsProbeWithTimeout(String host, int timeoutMs) + throws UnknownHostException { + final CountDownLatch latch = new CountDownLatch(1); + final AtomicReference<List<InetAddress>> resultRef = new AtomicReference<>(); + final DnsResolver.Callback<List<InetAddress>> callback = + new DnsResolver.Callback<List<InetAddress>>() { + public void onAnswer(List<InetAddress> answer, int rcode) { + if (rcode == 0) { + resultRef.set(answer); + } + latch.countDown(); + } + public void onError(@NonNull DnsResolver.DnsException e) { + validationLog("DNS error resolving " + host + ": " + e.getMessage()); + latch.countDown(); + } + }; + + final int oldTag = TrafficStats.getAndSetThreadStatsTag( + TrafficStatsConstants.TAG_SYSTEM_PROBE); + mDependencies.getDnsResolver().query(mNetwork, host, DnsResolver.FLAG_EMPTY, + r -> r.run() /* executor */, null /* cancellationSignal */, callback); + TrafficStats.setThreadStatsTag(oldTag); + + try { + latch.await(timeoutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + } + + List<InetAddress> result = resultRef.get(); + if (result == null || result.size() == 0) { + throw new UnknownHostException(host); + } + + return result.toArray(new InetAddress[0]); + } + /** Do a DNS resolution of the given server. */ private void sendDnsProbe(String host) { if (TextUtils.isEmpty(host)) { @@ -1457,7 +1534,7 @@ public class NetworkMonitor extends StateMachine { int result; String connectInfo; try { - InetAddress[] addresses = mNetwork.getAllByName(host); + InetAddress[] addresses = sendDnsProbeWithTimeout(host, getDnsProbeTimeout()); StringBuffer buffer = new StringBuffer(); for (InetAddress address : addresses) { buffer.append(',').append(address.getHostAddress()); @@ -1782,6 +1859,10 @@ public class NetworkMonitor extends StateMachine { return new OneAddressPerFamilyNetwork(network); } + public DnsResolver getDnsResolver() { + return DnsResolver.getInstance(); + } + public Random getRandom() { return new Random(); } diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java index 5650f2125737..6a6bf83bd3c8 100644 --- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java +++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java @@ -33,8 +33,8 @@ import android.net.IIpMemoryStore; import android.net.ipmemorystore.Blob; import android.net.ipmemorystore.IOnBlobRetrievedListener; import android.net.ipmemorystore.IOnL2KeyResponseListener; -import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; -import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener; +import android.net.ipmemorystore.IOnSameL3NetworkResponseListener; import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; import android.net.ipmemorystore.NetworkAttributesParcelable; @@ -297,16 +297,16 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { */ @Override public void isSameNetwork(@Nullable final String l2Key1, @Nullable final String l2Key2, - @Nullable final IOnSameNetworkResponseListener listener) { + @Nullable final IOnSameL3NetworkResponseListener listener) { if (null == listener) return; mExecutor.execute(() -> { try { if (null == l2Key1 || null == l2Key2) { - listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); + listener.onSameL3NetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } if (null == mDb) { - listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); + listener.onSameL3NetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } try { @@ -315,16 +315,16 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { final NetworkAttributes attr2 = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key2); if (null == attr1 || null == attr2) { - listener.onSameNetworkResponse(makeStatus(SUCCESS), + listener.onSameL3NetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, -1f /* never connected */).toParcelable()); return; } final float confidence = attr1.getNetworkGroupSamenessConfidence(attr2); - listener.onSameNetworkResponse(makeStatus(SUCCESS), + listener.onSameL3NetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, confidence).toParcelable()); } catch (Exception e) { - listener.onSameNetworkResponse(makeStatus(ERROR_GENERIC), null); + listener.onSameL3NetworkResponse(makeStatus(ERROR_GENERIC), null); } } catch (final RemoteException e) { // Client at the other end died @@ -343,7 +343,7 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { */ @Override public void retrieveNetworkAttributes(@Nullable final String l2Key, - @Nullable final IOnNetworkAttributesRetrieved listener) { + @Nullable final IOnNetworkAttributesRetrievedListener listener) { if (null == listener) return; mExecutor.execute(() -> { try { @@ -494,4 +494,9 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { listener.onComplete(makeStatus(ERROR_INTERNAL_INTERRUPTED)); return true; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java index 2775fde4c8b9..bea7052d8af2 100644 --- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java +++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java @@ -91,6 +91,11 @@ public final class RegularMaintenanceJobService extends JobService { } @Override + public int getInterfaceVersion() { + return this.VERSION; + } + + @Override public IBinder asBinder() { return null; } 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/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java index 7d5e9e3ba174..f0e2f1b8d459 100644 --- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java +++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java @@ -133,6 +133,11 @@ public class DhcpServerTest { public void onStatusAvailable(int statusCode) { assertEquals(STATUS_SUCCESS, statusCode); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; @Before 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 7d9eb9b55d07..0dc1cbf8a984 100644 --- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java @@ -33,6 +33,7 @@ import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -41,6 +42,7 @@ 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; @@ -55,6 +57,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.DnsResolver; import android.net.INetworkMonitorCallbacks; import android.net.InetAddresses; import android.net.LinkProperties; @@ -62,8 +65,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.captiveportal.CaptivePortalProbeResult; -import android.net.metrics.DataStallDetectionStats; -import android.net.metrics.DataStallStatsUtils; import android.net.metrics.IpConnectivityLog; import android.net.util.SharedLog; import android.net.wifi.WifiInfo; @@ -71,6 +72,7 @@ import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.ConditionVariable; import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; @@ -81,6 +83,10 @@ import android.util.ArrayMap; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.networkstack.R; +import com.android.networkstack.metrics.DataStallDetectionStats; +import com.android.networkstack.metrics.DataStallStatsUtils; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -95,8 +101,12 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Random; +import java.util.concurrent.Executor; import javax.net.ssl.SSLHandshakeException; @@ -110,6 +120,7 @@ public class NetworkMonitorTest { private @Mock IpConnectivityLog mLogger; private @Mock SharedLog mValidationLogger; private @Mock NetworkInfo mNetworkInfo; + private @Mock DnsResolver mDnsResolver; private @Mock ConnectivityManager mCm; private @Mock TelephonyManager mTelephony; private @Mock WifiManager mWifi; @@ -155,10 +166,36 @@ 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; + } + + List<InetAddress> answerList = new ArrayList<>(); + for (String answer : answers) { + answerList.add(InetAddresses.parseNumericAddress(answer)); + } + InetAddress[] answerArray = answerList.toArray(new InetAddress[0]); + + doReturn(answerArray).when(mNetwork).getAllByName(any()); + + 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()); + } + @Before public void setUp() throws IOException { MockitoAnnotations.initMocks(this); when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mNetwork); + when(mDependencies.getDnsResolver()).thenReturn(mDnsResolver); when(mDependencies.getRandom()).thenReturn(mRandom); when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt())) .thenReturn(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT); @@ -203,9 +240,8 @@ public class NetworkMonitorTest { }).when(mNetwork).openConnection(any()); when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>()); when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>()); - doReturn(new InetAddress[] { - InetAddresses.parseNumericAddress("192.168.0.0") - }).when(mNetwork).getAllByName(any()); + + setDnsAnswers(new String[]{"2001:db8::1", "192.0.2.2"}); when(mContext.registerReceiver(any(BroadcastReceiver.class), any())).then((invocation) -> { mRegisteredReceivers.add(invocation.getArgument(0)); @@ -312,6 +348,44 @@ public class NetworkMonitorTest { } @Test + public void testGetIntSetting() throws Exception { + WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor(); + + // No config resource, no device config. Expect to get default resource. + doThrow(new Resources.NotFoundException()) + .when(mResources).getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)); + doAnswer(invocation -> { + int defaultValue = invocation.getArgument(2); + return defaultValue; + }).when(mDependencies).getDeviceConfigPropertyInt(any(), + eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT), + anyInt()); + when(mResources.getInteger(eq(R.integer.default_captive_portal_dns_probe_timeout))) + .thenReturn(42); + assertEquals(42, wnm.getIntSetting(mContext, + R.integer.config_captive_portal_dns_probe_timeout, + NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT, + R.integer.default_captive_portal_dns_probe_timeout)); + + // Set device config. Expect to get device config. + when(mDependencies.getDeviceConfigPropertyInt(any(), + eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT), anyInt())) + .thenReturn(1234); + assertEquals(1234, wnm.getIntSetting(mContext, + R.integer.config_captive_portal_dns_probe_timeout, + NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT, + R.integer.default_captive_portal_dns_probe_timeout)); + + // Set config resource. Expect to get config resource. + when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout))) + .thenReturn(5678); + assertEquals(5678, wnm.getIntSetting(mContext, + R.integer.config_captive_portal_dns_probe_timeout, + NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT, + R.integer.default_captive_portal_dns_probe_timeout)); + } + + @Test public void testIsCaptivePortal_HttpProbeIsPortal() throws IOException { setSslException(mHttpsConnection); setPortal302(mHttpConnection); @@ -641,6 +715,45 @@ public class NetworkMonitorTest { runPartialConnectivityNetworkTest(); } + private void assertIpAddressArrayEquals(String[] expected, InetAddress[] actual) { + String[] actualStrings = new String[actual.length]; + for (int i = 0; i < actual.length; i++) { + actualStrings[i] = actual[i].getHostAddress(); + } + assertArrayEquals("Array of IP addresses differs", expected, actualStrings); + } + + @Test + public void testSendDnsProbeWithTimeout() throws Exception { + WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor(); + final int shortTimeoutMs = 200; + + String[] expected = new String[]{"2001:db8::"}; + setDnsAnswers(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); + assertIpAddressArrayEquals(expected, actual); + + expected = new String[0]; + setDnsAnswers(expected); + try { + wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs); + fail("No DNS results, expected UnknownHostException"); + } catch (UnknownHostException e) { + } + + setDnsAnswers(null); + try { + wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs); + fail("DNS query timed out, expected UnknownHostException"); + } catch (UnknownHostException e) { + } + } + private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) { for (int i = 0; i < count; i++) { wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount( diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java index 94cc58919459..87346e5d6a28 100644 --- a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java +++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java @@ -31,8 +31,8 @@ import android.content.Context; import android.net.ipmemorystore.Blob; import android.net.ipmemorystore.IOnBlobRetrievedListener; import android.net.ipmemorystore.IOnL2KeyResponseListener; -import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; -import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener; +import android.net.ipmemorystore.IOnSameL3NetworkResponseListener; import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; import android.net.ipmemorystore.NetworkAttributesParcelable; @@ -136,6 +136,11 @@ public class IpMemoryStoreServiceTest { public IBinder asBinder() { return null; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; } @@ -156,6 +161,11 @@ public class IpMemoryStoreServiceTest { public IBinder asBinder() { return null; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; } @@ -163,9 +173,9 @@ public class IpMemoryStoreServiceTest { private interface OnNetworkAttributesRetrievedListener { void onNetworkAttributesRetrieved(Status status, String l2Key, NetworkAttributes attr); } - private IOnNetworkAttributesRetrieved onNetworkAttributesRetrieved( + private IOnNetworkAttributesRetrievedListener onNetworkAttributesRetrieved( final OnNetworkAttributesRetrievedListener functor) { - return new IOnNetworkAttributesRetrieved() { + return new IOnNetworkAttributesRetrievedListener() { @Override public void onNetworkAttributesRetrieved(final StatusParcelable status, final String l2Key, final NetworkAttributesParcelable attributes) @@ -178,21 +188,26 @@ public class IpMemoryStoreServiceTest { public IBinder asBinder() { return null; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; } /** Helper method to make an IOnSameNetworkResponseListener */ - private interface OnSameNetworkResponseListener { - void onSameNetworkResponse(Status status, SameL3NetworkResponse answer); + private interface OnSameL3NetworkResponseListener { + void onSameL3NetworkResponse(Status status, SameL3NetworkResponse answer); } - private IOnSameNetworkResponseListener onSameResponse( - final OnSameNetworkResponseListener functor) { - return new IOnSameNetworkResponseListener() { + private IOnSameL3NetworkResponseListener onSameResponse( + final OnSameL3NetworkResponseListener functor) { + return new IOnSameL3NetworkResponseListener() { @Override - public void onSameNetworkResponse(final StatusParcelable status, + public void onSameL3NetworkResponse(final StatusParcelable status, final SameL3NetworkResponseParcelable sameL3Network) throws RemoteException { - functor.onSameNetworkResponse(new Status(status), + functor.onSameL3NetworkResponse(new Status(status), null == sameL3Network ? null : new SameL3NetworkResponse(sameL3Network)); } @@ -200,6 +215,11 @@ public class IpMemoryStoreServiceTest { public IBinder asBinder() { return null; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; } @@ -219,6 +239,11 @@ public class IpMemoryStoreServiceTest { public IBinder asBinder() { return null; } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }; } diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 2c4abaeb9949..d5b121768a66 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1131,7 +1131,4 @@ <!-- The notice header of Third-party licenses. not translatable --> <string name="notice_header" translatable="false"></string> - - <!-- UI debug setting: opt in to use updated graphics driver? [CHAR LIMIT=100] --> - <string name="gup_dev_opt_in_app_summary">Opt in app to use Game Update Package in developement</string> </resources> 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/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 759b51c853da..c60e352e9960 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -648,11 +648,26 @@ class SettingsProtoDumpUtil { Settings.Global.GPU_DEBUG_LAYERS, GlobalSettingsProto.Gpu.DEBUG_LAYERS); dumpSetting(s, p, - Settings.Global.GUP_DEV_OPT_IN_APPS, - GlobalSettingsProto.Gpu.GUP_DEV_OPT_IN_APPS); + Settings.Global.GAME_DRIVER_ALL_APPS, + GlobalSettingsProto.Gpu.GAME_DRIVER_ALL_APPS); dumpSetting(s, p, - Settings.Global.GUP_BLACK_LIST, - GlobalSettingsProto.Gpu.GUP_BLACK_LIST); + Settings.Global.GAME_DRIVER_OPT_IN_APPS, + GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_IN_APPS); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_OPT_OUT_APPS, + GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_OUT_APPS); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_BLACKLIST, + GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLIST); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_WHITELIST, + GlobalSettingsProto.Gpu.GAME_DRIVER_WHITELIST); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_BLACKLISTS, + GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS); + dumpSetting(s, p, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, + GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); 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/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index d79d833f2233..6902a706e91f 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -6492,6 +6492,11 @@ message MetricsEvent { // OS: Q ACTION_EMERGENCY_DIALER_FROM_POWER_MENU = 1569; + // OPEN: Settings > Developer Options > Game Driver Preference + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_GAME_DRIVER_DASHBOARD = 1613; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. 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 c1aff757d474..63fd2fda1ce6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY; import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID; +import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; @@ -634,7 +635,8 @@ public class ConnectivityService extends IConnectivityManager.Stub * the first network for a given type changes, or if the default network * changes. */ - private class LegacyTypeTracker { + @VisibleForTesting + static class LegacyTypeTracker { private static final boolean DBG = true; private static final boolean VDBG = false; @@ -660,10 +662,12 @@ public class ConnectivityService extends IConnectivityManager.Stub * - dump is thread-safe with respect to concurrent add and remove calls. */ private final ArrayList<NetworkAgentInfo> mTypeLists[]; + @NonNull + private final ConnectivityService mService; - public LegacyTypeTracker() { - mTypeLists = (ArrayList<NetworkAgentInfo>[]) - new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; + LegacyTypeTracker(@NonNull ConnectivityService service) { + mService = service; + mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1]; } public void addSupportedType(int type) { @@ -712,10 +716,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Send a broadcast if this is the first network of its type or if it's the default. - final boolean isDefaultNetwork = isDefaultNetwork(nai); + final boolean isDefaultNetwork = mService.isDefaultNetwork(nai); if ((list.size() == 1) || isDefaultNetwork) { maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork); - sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); + mService.sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); } } @@ -733,19 +737,18 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - final DetailedState state = DetailedState.DISCONNECTED; - if (wasFirstNetwork || wasDefault) { - maybeLogBroadcast(nai, state, type, wasDefault); - sendLegacyNetworkBroadcast(nai, state, type); + maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault); + mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type); } if (!list.isEmpty() && wasFirstNetwork) { if (DBG) log("Other network available for type " + type + ", sending connected broadcast"); final NetworkAgentInfo replacement = list.get(0); - maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement)); - sendLegacyNetworkBroadcast(replacement, state, type); + maybeLogBroadcast(replacement, DetailedState.CONNECTED, type, + mService.isDefaultNetwork(replacement)); + mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type); } } @@ -760,7 +763,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // send out another legacy broadcast - currently only used for suspend/unsuspend // toggle public void update(NetworkAgentInfo nai) { - final boolean isDefault = isDefaultNetwork(nai); + final boolean isDefault = mService.isDefaultNetwork(nai); final DetailedState state = nai.networkInfo.getDetailedState(); for (int type = 0; type < mTypeLists.length; type++) { final ArrayList<NetworkAgentInfo> list = mTypeLists[type]; @@ -768,7 +771,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean isFirst = contains && (nai == list.get(0)); if (isFirst || contains && isDefault) { maybeLogBroadcast(nai, state, type, isDefault); - sendLegacyNetworkBroadcast(nai, state, type); + mService.sendLegacyNetworkBroadcast(nai, state, type); } } } @@ -804,7 +807,7 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(); } } - private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(); + private final LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker(this); /** * Helper class which parses out priority arguments and dumps sections according to their @@ -2815,6 +2818,11 @@ public class ConnectivityService extends IConnectivityManager.Stub EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNai.network.netId)); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } private boolean networkRequiresValidation(NetworkAgentInfo nai) { @@ -2853,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 @@ -3023,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(); @@ -3062,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) { @@ -3074,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. @@ -3412,7 +3445,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().setAcceptPartialConnectivity(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } } } @@ -3448,7 +3481,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().launchCaptivePortalApp(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } }); } @@ -4076,7 +4109,7 @@ public class ConnectivityService extends IConnectivityManager.Stub try { nai.networkMonitor().forceReevaluation(uid); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + e.rethrowAsRuntimeException(); } } @@ -5371,7 +5404,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private boolean isDefaultNetwork(NetworkAgentInfo nai) { + @VisibleForTesting + protected boolean isDefaultNetwork(NetworkAgentInfo nai) { return nai == getDefaultNetwork(); } @@ -5455,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; @@ -5512,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); @@ -6473,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; } @@ -6518,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); @@ -6671,7 +6691,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { + @VisibleForTesting + protected void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { // The NetworkInfo we actually send out has no bearing on the real // state of affairs. For example, if the default connection is mobile, // and a request for HIPRI has just gone away, we need to pretend that @@ -6838,6 +6859,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceKeepalivePermission(); mKeepaliveTracker.startNattKeepalive( getNetworkAgentInfoForNetwork(network), null /* fd */, + INVALID_RESOURCE_ID /* Unused */, intervalSeconds, cb, srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2055b64483d9..c1f52552eaf7 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -28,8 +28,10 @@ import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -42,6 +44,7 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; +import android.net.NetworkStack; import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; @@ -74,6 +77,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -175,6 +180,14 @@ public class IpSecService extends IIpSecService.Stub { } /** + * Sentinel value placeholder for a real binder in RefcountedResources. + * + * <p>Used for cases where there the allocating party is a system service, and thus is expected + * to track the resource lifecycles instead of IpSecService. + */ + private static final Binder DUMMY_BINDER = new Binder(); + + /** * RefcountedResource manages references and dependencies in an exclusively acyclic graph. * * <p>RefcountedResource implements both explicit and implicit resource management. Creating a @@ -188,24 +201,42 @@ public class IpSecService extends IIpSecService.Stub { */ @VisibleForTesting public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient { - private final T mResource; - private final List<RefcountedResource> mChildren; + + @NonNull private final T mResource; + @NonNull private final List<RefcountedResource> mChildren; int mRefCount = 1; // starts at 1 for user's reference. - IBinder mBinder; - RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { + /* + * This field can take one of three states: + * 1. null, when the object has been released by the user (or the user's binder dies) + * 2. DUMMY_BINDER, when the refcounted resource is allocated from another system service + * and the other system service manages the lifecycle of the resource instead of + * IpSecService. + * 3. an actual binder, to ensure IpSecService can cleanup after users that forget to close + * their resources. + */ + @Nullable IBinder mBinder; + + RefcountedResource(@NonNull T resource, @NonNull RefcountedResource... children) { + this(resource, DUMMY_BINDER, children); + } + + RefcountedResource( + @NonNull T resource, + @NonNull IBinder binder, + @NonNull RefcountedResource... children) { synchronized (IpSecService.this) { this.mResource = resource; - this.mChildren = new ArrayList<>(children.length); this.mBinder = binder; - + this.mChildren = Collections.unmodifiableList(Arrays.asList(children)); for (RefcountedResource child : children) { - mChildren.add(child); child.mRefCount++; } try { - mBinder.linkToDeath(this, 0); + if (mBinder != DUMMY_BINDER) { + mBinder.linkToDeath(this, 0); + } } catch (RemoteException e) { binderDied(); e.rethrowFromSystemServer(); @@ -252,11 +283,12 @@ public class IpSecService extends IIpSecService.Stub { return; } - mBinder.unlinkToDeath(this, 0); + if (mBinder != DUMMY_BINDER) { + mBinder.unlinkToDeath(this, 0); + } mBinder = null; mResource.invalidate(); - releaseReference(); } @@ -381,6 +413,8 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName()); final RefcountedResourceArray<TunnelInterfaceRecord> mTunnelInterfaceRecords = new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName()); + final RefcountedResourceArray<NattKeepaliveRecord> mNattKeepaliveRecords = + new RefcountedResourceArray<>(NattKeepaliveRecord.class.getSimpleName()); /** * Trackers for quotas for each of the OwnedResource types. @@ -394,6 +428,8 @@ public class IpSecService extends IIpSecService.Stub { final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); + final ResourceTracker mNattKeepaliveQuotaTracker = + new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); // Max 1 NATT keepalive per encap socket final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES); void removeSpiRecord(int resourceId) { @@ -412,6 +448,10 @@ public class IpSecService extends IIpSecService.Stub { mEncapSocketRecords.remove(resourceId); } + void removeNattKeepaliveRecord(int resourceId) { + mNattKeepaliveRecords.remove(resourceId); + } + @Override public String toString() { return new StringBuilder() @@ -421,6 +461,8 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformQuotaTracker) .append(", mSocketQuotaTracker=") .append(mSocketQuotaTracker) + .append(", mNattKeepaliveQuotaTracker=") + .append(mNattKeepaliveQuotaTracker) .append(", mTunnelQuotaTracker=") .append(mTunnelQuotaTracker) .append(", mSpiRecords=") @@ -429,6 +471,8 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformRecords) .append(", mEncapSocketRecords=") .append(mEncapSocketRecords) + .append(", mNattKeepaliveRecords=") + .append(mNattKeepaliveRecords) .append(", mTunnelInterfaceRecords=") .append(mTunnelInterfaceRecords) .append("}") @@ -573,6 +617,11 @@ public class IpSecService extends IIpSecService.Stub { mArray.remove(key); } + @VisibleForTesting + int size() { + return mArray.size(); + } + @Override public String toString() { return mArray.toString(); @@ -984,6 +1033,50 @@ public class IpSecService extends IIpSecService.Stub { } /** + * Tracks a NATT-keepalive instance + * + * <p>This class ensures that while a NATT-keepalive is active, the UDP encap socket that it is + * supporting will stay open until the NATT-keepalive is finished. NATT-keepalive offload + * lifecycles will be managed by ConnectivityService, which will validate that the UDP Encap + * socket is owned by the requester, and take a reference to it via this NattKeepaliveRecord + * + * <p>It shall be the responsibility of the caller to ensure that instances of an EncapSocket do + * not spawn multiple instances of NATT keepalives (and thereby register duplicate records) + */ + private final class NattKeepaliveRecord extends OwnedResourceRecord { + NattKeepaliveRecord(int resourceId) { + super(resourceId); + } + + @Override + @GuardedBy("IpSecService.this") + public void freeUnderlyingResources() { + Log.d(TAG, "Natt Keepalive released: " + mResourceId); + + getResourceTracker().give(); + } + + @Override + protected ResourceTracker getResourceTracker() { + return getUserRecord().mNattKeepaliveQuotaTracker; + } + + @Override + public void invalidate() { + getUserRecord().removeNattKeepaliveRecord(mResourceId); + } + + @Override + public String toString() { + return new StringBuilder() + .append("{super=") + .append(super.toString()) + .append("}") + .toString(); + } + } + + /** * Constructs a new IpSecService instance * * @param context Binder context for this service @@ -1818,6 +1911,57 @@ public class IpSecService extends IIpSecService.Stub { } } + private void verifyNetworkStackCaller() { + if (mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Requires permission NETWORK_STACK or MAINLINE_NETWORK_STACK"); + } + } + + /** + * Validates that a provided UID owns the encapSocket, and creates a NATT keepalive record + * + * <p>For system server use only. Caller must have NETWORK_STACK permission + * + * @param encapSocketResourceId resource identifier of the encap socket record + * @param ownerUid the UID of the caller. Used to verify ownership. + * @return + */ + public synchronized int lockEncapSocketForNattKeepalive( + int encapSocketResourceId, int ownerUid) { + verifyNetworkStackCaller(); + + // Verify ownership. Will throw IllegalArgumentException if the UID specified does not + // own the specified UDP encapsulation socket + UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); + RefcountedResource<EncapSocketRecord> refcountedSocketRecord = + userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(encapSocketResourceId); + + // Build NattKeepaliveRecord + final int resourceId = mNextResourceId++; + userRecord.mNattKeepaliveRecords.put( + resourceId, + new RefcountedResource<NattKeepaliveRecord>( + new NattKeepaliveRecord(resourceId), refcountedSocketRecord)); + + return resourceId; + } + + /** + * Release a previously allocated NattKeepalive that has been registered with the system server + */ + @Override + public synchronized void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid) + throws RemoteException { + verifyNetworkStackCaller(); + + UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); + releaseResource(userRecord.mNattKeepaliveRecords, nattKeepaliveResourceId); + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); 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/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 40bf7bccff72..d19d2ddd7c3c 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -19,6 +19,7 @@ package com.android.server; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; import android.net.INetd; @@ -53,6 +54,7 @@ import java.net.Inet6Address; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.util.ArrayList; import java.util.concurrent.atomic.AtomicInteger; /** @hide */ @@ -226,6 +228,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { @NonNull Looper looper, @NonNull Context context, @NonNull String iface, + @Nullable LinkProperties lp, + boolean isMetered, int callingUid, @NonNull IBinder binder) throws RemoteException, SocketException { @@ -245,9 +249,19 @@ class TestNetworkService extends ITestNetworkManager.Stub { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.setNetworkSpecifier(new StringNetworkSpecifier(iface)); + if (!isMetered) { + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); + } // Build LinkProperties - LinkProperties lp = new LinkProperties(); + if (lp == null) { + lp = new LinkProperties(); + } else { + lp = new LinkProperties(lp); + // Use LinkAddress(es) from the interface itself to minimize how much the caller + // is trusted. + lp.setLinkAddresses(new ArrayList<>()); + } lp.setInterfaceName(iface); // Find the currently assigned addresses, and add them to LinkProperties @@ -284,7 +298,11 @@ class TestNetworkService extends ITestNetworkManager.Stub { * <p>This method provides a Network that is useful only for testing. */ @Override - public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { + public void setupTestNetwork( + @NonNull String iface, + @Nullable LinkProperties lp, + boolean isMetered, + @NonNull IBinder binder) { enforceTestNetworkPermissions(mContext); checkNotNull(iface, "missing Iface"); @@ -315,6 +333,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { mHandler.getLooper(), mContext, iface, + lp, + isMetered, callingUid, binder); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index e18f3740a969..5ebd17360961 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -318,7 +318,6 @@ import android.location.LocationManager; import android.media.audiofx.AudioEffect; import android.metrics.LogMaker; import android.net.Proxy; -import android.net.ProxyInfo; import android.net.Uri; import android.os.BatteryStats; import android.os.Binder; @@ -2252,21 +2251,25 @@ public class ActivityManagerService extends IActivityManager.Stub } } break; case UPDATE_HTTP_PROXY_MSG: { + // Update the HTTP proxy for each application thread. synchronized (ActivityManagerService.this) { for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { ProcessRecord r = mLruProcesses.get(i); // Don't dispatch to isolated processes as they can't access - // ConnectivityManager and don't have network privileges anyway. - if (r.thread != null && !r.isolated) { + // ConnectivityManager and don't have network privileges anyway. Exclude + // system server and update it separately outside the AMS lock, to avoid + // deadlock with Connectivity Service. + if (r.pid != MY_PID && r.thread != null && !r.isolated) { try { r.thread.updateHttpProxy(); } catch (RemoteException ex) { - Slog.w(TAG, "Failed to update http proxy for: " + - r.info.processName); + Slog.w(TAG, "Failed to update http proxy for: " + + r.info.processName); } } } } + ActivityThread.updateHttpProxy(mContext); } break; case PROC_START_TIMEOUT_MSG: { ProcessRecord app = (ProcessRecord)msg.obj; @@ -2607,7 +2610,7 @@ public class ActivityManagerService extends IActivityManager.Stub } break; } } - }; + } static final int COLLECT_PSS_BG_MSG = 1; diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 63300a1c05cd..9ff47e0dc0b4 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -55,8 +55,13 @@ final class CoreSettingsObserver extends ContentObserver { // add other system settings here... sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class); - sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_IN_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACK_LIST, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALL_APPS, int.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class); // add other global settings here... } 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/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 77a18e2b3ddc..bde430cc297f 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -17,6 +17,7 @@ package com.android.server.connectivity; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.NattSocketKeepalive.NATT_PORT; import static android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER; import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER; @@ -37,6 +38,7 @@ import static android.net.SocketKeepalive.SUCCESS; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.net.IIpSecService; import android.net.ISocketKeepaliveCallback; import android.net.KeepalivePacketData; import android.net.NattKeepalivePacketData; @@ -52,6 +54,7 @@ import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.system.ErrnoException; import android.system.Os; import android.util.Log; @@ -89,11 +92,14 @@ public class KeepaliveTracker { private final TcpKeepaliveController mTcpController; @NonNull private final Context mContext; + @NonNull + private final IIpSecService mIpSec; public KeepaliveTracker(Context context, Handler handler) { mConnectivityServiceHandler = handler; mTcpController = new TcpKeepaliveController(handler); mContext = context; + mIpSec = IIpSecService.Stub.asInterface(ServiceManager.getService(Context.IPSEC_SERVICE)); } /** @@ -112,6 +118,10 @@ public class KeepaliveTracker { private final int mType; private final FileDescriptor mFd; + private final int mEncapSocketResourceId; + // Stores the NATT keepalive resource ID returned by IpSecService. + private int mNattIpsecResourceId = INVALID_RESOURCE_ID; + public static final int TYPE_NATT = 1; public static final int TYPE_TCP = 2; @@ -140,7 +150,8 @@ public class KeepaliveTracker { @NonNull KeepalivePacketData packet, int interval, int type, - @Nullable FileDescriptor fd) throws InvalidSocketException { + @Nullable FileDescriptor fd, + int encapSocketResourceId) throws InvalidSocketException { mCallback = callback; mPid = Binder.getCallingPid(); mUid = Binder.getCallingUid(); @@ -151,6 +162,9 @@ public class KeepaliveTracker { mInterval = interval; mType = type; + mEncapSocketResourceId = encapSocketResourceId; + mNattIpsecResourceId = INVALID_RESOURCE_ID; + // For SocketKeepalive, a dup of fd is kept in mFd so the source port from which the // keepalives are sent cannot be reused by another app even if the fd gets closed by // the user. A null is acceptable here for backward compatibility of PacketKeepalive @@ -158,7 +172,7 @@ public class KeepaliveTracker { try { if (fd != null) { mFd = Os.dup(fd); - } else { + } else { Log.d(TAG, toString() + " calls with null fd"); if (!mPrivileged) { throw new SecurityException( @@ -206,6 +220,8 @@ public class KeepaliveTracker { + IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort) + " interval=" + mInterval + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged + + " nattIpsecRId=" + mNattIpsecResourceId + + " encapSocketRId=" + mEncapSocketResourceId + " packetData=" + HexDump.toHexString(mPacket.getPacket()) + " ]"; } @@ -262,6 +278,51 @@ public class KeepaliveTracker { return SUCCESS; } + private int checkAndLockNattKeepaliveResource() { + // Check that apps should be either privileged or fill in an ipsec encapsulated socket + // resource id. + if (mEncapSocketResourceId == INVALID_RESOURCE_ID) { + if (mPrivileged) { + return SUCCESS; + } else { + // Invalid access. + return ERROR_INVALID_SOCKET; + } + } + + // Check if the ipsec encapsulated socket resource id is registered. + final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(mNai); + if (networkKeepalives == null) { + return ERROR_INVALID_NETWORK; + } + for (KeepaliveInfo ki : networkKeepalives.values()) { + if (ki.mEncapSocketResourceId == mEncapSocketResourceId + && ki.mNattIpsecResourceId != INVALID_RESOURCE_ID) { + Log.d(TAG, "Registered resource found on keepalive " + mSlot + + " when verify NATT socket with uid=" + mUid + " rid=" + + mEncapSocketResourceId); + return ERROR_INVALID_SOCKET; + } + } + + // Ensure that the socket is created by IpSecService, and lock the resource that is + // preserved by IpSecService. If succeed, a resource id is stored to keep tracking + // the resource preserved by IpSecServce and must be released when stopping keepalive. + try { + mNattIpsecResourceId = + mIpSec.lockEncapSocketForNattKeepalive(mEncapSocketResourceId, mUid); + return SUCCESS; + } catch (IllegalArgumentException e) { + // The UID specified does not own the specified UDP encapsulation socket. + Log.d(TAG, "Failed to verify NATT socket with uid=" + mUid + " rid=" + + mEncapSocketResourceId + ": " + e); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling lockEncapSocketForNattKeepalive with " + + this.toString(), e); + } + return ERROR_INVALID_SOCKET; + } + private int isValid() { synchronized (mNai) { int error = checkInterval(); @@ -275,6 +336,13 @@ public class KeepaliveTracker { void start(int slot) { mSlot = slot; int error = isValid(); + + // Check and lock ipsec resource needed by natt kepalive. This should be only called + // once per keepalive. + if (error == SUCCESS && mType == TYPE_NATT) { + error = checkAndLockNattKeepaliveResource(); + } + if (error == SUCCESS) { Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name()); switch (mType) { @@ -350,6 +418,20 @@ public class KeepaliveTracker { } } + // Release the resource held by keepalive in IpSecService. + if (mNattIpsecResourceId != INVALID_RESOURCE_ID) { + if (mType != TYPE_NATT) { + Log.wtf(TAG, "natt ipsec resource held by incorrect keepalive " + + this.toString()); + } + try { + mIpSec.releaseNattKeepalive(mNattIpsecResourceId, mUid); + } catch (RemoteException e) { + Log.wtf(TAG, "error calling releaseNattKeepalive with " + this.toString(), e); + } + mNattIpsecResourceId = INVALID_RESOURCE_ID; + } + if (reason == SUCCESS) { try { mCallback.onStopped(); @@ -538,6 +620,7 @@ public class KeepaliveTracker { **/ public void startNattKeepalive(@Nullable NetworkAgentInfo nai, @Nullable FileDescriptor fd, + int encapSocketResourceId, int intervalSeconds, @NonNull ISocketKeepaliveCallback cb, @NonNull String srcAddrString, @@ -569,7 +652,7 @@ public class KeepaliveTracker { KeepaliveInfo ki = null; try { ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_NATT, fd); + KeepaliveInfo.TYPE_NATT, fd, encapSocketResourceId); } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { Log.e(TAG, "Fail to construct keepalive", e); notifyErrorCallback(cb, ERROR_INVALID_SOCKET); @@ -609,7 +692,7 @@ public class KeepaliveTracker { KeepaliveInfo ki = null; try { ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds, - KeepaliveInfo.TYPE_TCP, fd); + KeepaliveInfo.TYPE_TCP, fd, INVALID_RESOURCE_ID /* Unused */); } catch (InvalidSocketException | IllegalArgumentException | SecurityException e) { Log.e(TAG, "Fail to construct keepalive e=" + e); notifyErrorCallback(cb, ERROR_INVALID_SOCKET); @@ -628,17 +711,12 @@ public class KeepaliveTracker { **/ public void startNattKeepalive(@Nullable NetworkAgentInfo nai, @Nullable FileDescriptor fd, - int resourceId, + int encapSocketResourceId, int intervalSeconds, @NonNull ISocketKeepaliveCallback cb, @NonNull String srcAddrString, @NonNull String dstAddrString, int dstPort) { - // Ensure that the socket is created by IpSecService. - if (!isNattKeepaliveSocketValid(fd, resourceId)) { - notifyErrorCallback(cb, ERROR_INVALID_SOCKET); - } - // Get src port to adopt old API. int srcPort = 0; try { @@ -649,23 +727,8 @@ public class KeepaliveTracker { } // Forward request to old API. - startNattKeepalive(nai, fd, intervalSeconds, cb, srcAddrString, srcPort, - dstAddrString, dstPort); - } - - /** - * Verify if the IPsec NAT-T file descriptor and resource Id hold for IPsec keepalive is valid. - **/ - public static boolean isNattKeepaliveSocketValid(@Nullable FileDescriptor fd, int resourceId) { - // TODO: 1. confirm whether the fd is called from system api or created by IpSecService. - // 2. If the fd is created from the system api, check that it's bounded. And - // call dup to keep the fd open. - // 3. If the fd is created from IpSecService, check if the resource ID is valid. And - // hold the resource needed in IpSecService. - if (null == fd) { - return false; - } - return true; + startNattKeepalive(nai, fd, encapSocketResourceId, intervalSeconds, cb, srcAddrString, + srcPort, dstAddrString, dstPort); } public void dump(IndentingPrintWriter pw) { 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/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java new file mode 100644 index 000000000000..647727f795da --- /dev/null +++ b/services/core/java/com/android/server/gpu/GpuService.java @@ -0,0 +1,274 @@ +/* + * 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 com.android.server.gpu; + +import static android.content.Intent.ACTION_PACKAGE_ADDED; +import static android.content.Intent.ACTION_PACKAGE_CHANGED; +import static android.content.Intent.ACTION_PACKAGE_REMOVED; + +import android.annotation.NonNull; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.database.ContentObserver; +import android.gamedriver.GameDriverProto.Blacklist; +import android.gamedriver.GameDriverProto.Blacklists; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Base64; +import android.util.Slog; + +import com.android.framework.protobuf.InvalidProtocolBufferException; +import com.android.internal.annotations.GuardedBy; +import com.android.server.SystemService; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +/** + * Service to manage GPU related features. + * + * <p>GPU service is a core service that monitors, coordinates all GPU related features, + * as well as collect metrics about the GPU and GPU driver.</p> + */ +public class GpuService extends SystemService { + public static final String TAG = "GpuService"; + public static final boolean DEBUG = false; + + private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0"; + private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt"; + private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; + private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP; + + private final Context mContext; + private final String mDriverPackageName; + private final PackageManager mPackageManager; + private final Object mLock = new Object(); + private ContentResolver mContentResolver; + private long mGameDriverVersionCode; + private SettingsObserver mSettingsObserver; + @GuardedBy("mLock") + private Blacklists mBlacklists; + + public GpuService(Context context) { + super(context); + + mContext = context; + mDriverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + mGameDriverVersionCode = -1; + mPackageManager = context.getPackageManager(); + if (mDriverPackageName != null && !mDriverPackageName.isEmpty()) { + final IntentFilter packageFilter = new IntentFilter(); + packageFilter.addAction(ACTION_PACKAGE_ADDED); + packageFilter.addAction(ACTION_PACKAGE_CHANGED); + packageFilter.addAction(ACTION_PACKAGE_REMOVED); + packageFilter.addDataScheme("package"); + getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, + packageFilter, null, null); + } + } + + @Override + public void onStart() { + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_BOOT_COMPLETED) { + mContentResolver = mContext.getContentResolver(); + mSettingsObserver = new SettingsObserver(); + if (mDriverPackageName == null || mDriverPackageName.isEmpty()) { + return; + } + fetchGameDriverPackageProperties(); + processBlacklists(); + setBlacklist(); + } + } + + private final class SettingsObserver extends ContentObserver { + private final Uri mGameDriverBlackUri = + Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_BLACKLISTS); + + SettingsObserver() { + super(new Handler()); + mContentResolver.registerContentObserver(mGameDriverBlackUri, false, this, + UserHandle.USER_ALL); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (uri == null) { + return; + } + + if (mGameDriverBlackUri.equals(uri)) { + processBlacklists(); + setBlacklist(); + } + } + } + + private final class PackageReceiver extends BroadcastReceiver { + @Override + public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { + final Uri data = intent.getData(); + if (data == null && DEBUG) { + Slog.e(TAG, "Cannot handle package broadcast with null data"); + return; + } + final String packageName = data.getSchemeSpecificPart(); + if (!packageName.equals(mDriverPackageName)) { + return; + } + + final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + + switch (intent.getAction()) { + case ACTION_PACKAGE_ADDED: + case ACTION_PACKAGE_CHANGED: + case ACTION_PACKAGE_REMOVED: + fetchGameDriverPackageProperties(); + setBlacklist(); + break; + default: + // do nothing + break; + } + } + } + + private static void assetToSettingsGlobal(Context context, Context driverContext, + String fileName, String settingsGlobal, CharSequence delimiter) { + try { + final BufferedReader reader = new BufferedReader( + new InputStreamReader(driverContext.getAssets().open(fileName))); + final ArrayList<String> assetStrings = new ArrayList<>(); + for (String assetString; (assetString = reader.readLine()) != null; ) { + assetStrings.add(assetString); + } + Settings.Global.putString(context.getContentResolver(), + settingsGlobal, + String.join(delimiter, assetStrings)); + } catch (IOException e) { + if (DEBUG) { + Slog.w(TAG, "Failed to load " + fileName + ", abort."); + } + } + } + + private void fetchGameDriverPackageProperties() { + final ApplicationInfo driverInfo; + try { + driverInfo = mPackageManager.getApplicationInfo(mDriverPackageName, + PackageManager.MATCH_SYSTEM_ONLY); + } catch (PackageManager.NameNotFoundException e) { + if (DEBUG) { + Slog.e(TAG, "driver package '" + mDriverPackageName + "' not installed"); + } + return; + } + + // O drivers are restricted to the sphal linker namespace, so don't try to use + // packages unless they declare they're compatible with that restriction. + if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) { + if (DEBUG) { + Slog.w(TAG, "Driver package is not known to be compatible with O"); + } + return; + } + + // Reset the whitelist. + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_WHITELIST, ""); + // Reset the sphal libraries + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ""); + mGameDriverVersionCode = driverInfo.longVersionCode; + + try { + final Context driverContext = mContext.createPackageContext(mDriverPackageName, + Context.CONTEXT_RESTRICTED); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME, + Settings.Global.GAME_DRIVER_WHITELIST, ","); + + assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_SPHAL_LIBRARIES_FILENAME, + Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ":"); + + } catch (PackageManager.NameNotFoundException e) { + if (DEBUG) { + Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed"); + } + } + } + + private void processBlacklists() { + // TODO(b/121350991) Switch to DeviceConfig with property listener. + String base64String = + Settings.Global.getString(mContentResolver, Settings.Global.GAME_DRIVER_BLACKLISTS); + if (base64String == null || base64String.isEmpty()) { + return; + } + + synchronized (mLock) { + // Reset all blacklists + mBlacklists = null; + try { + mBlacklists = Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS)); + } catch (IllegalArgumentException e) { + if (DEBUG) { + Slog.w(TAG, "Can't parse blacklist, skip and continue..."); + } + } catch (InvalidProtocolBufferException e) { + if (DEBUG) { + Slog.w(TAG, "Can't parse blacklist, skip and continue..."); + } + } + } + } + + private void setBlacklist() { + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_BLACKLIST, ""); + synchronized (mLock) { + if (mBlacklists == null) { + return; + } + List<Blacklist> blacklists = mBlacklists.getBlacklistsList(); + for (Blacklist blacklist : blacklists) { + if (blacklist.getVersionCode() == mGameDriverVersionCode) { + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_BLACKLIST, + String.join(",", blacklist.getPackageNamesList())); + return; + } + } + } + } +} diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 4baf70b37655..62ea95b21865 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -34,10 +34,10 @@ per-file UserManagerService.java = omakoto@google.com, yamasani@google.com per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com # security -per-file KeySetHandle.java = cbrubaker@google.com -per-file KeySetManagerService.java = cbrubaker@google.com -per-file PackageKeySetData.java = cbrubaker@google.com -per-file PackageSignatures.java = cbrubaker@google.com +per-file KeySetHandle.java = cbrubaker@google.com, nnk@google.com +per-file KeySetManagerService.java = cbrubaker@google.com, nnk@google.com +per-file PackageKeySetData.java = cbrubaker@google.com, nnk@google.com +per-file PackageSignatures.java = cbrubaker@google.com, nnk@google.com per-file SELinuxMMAC.java = cbrubaker@google.com, jeffv@google.com, jgalenson@google.com, nnk@google.com # shortcuts 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/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7be7ab2bfb23..f0292aaded18 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -87,6 +87,7 @@ import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; import com.android.server.emergency.EmergencyAffordanceService; import com.android.server.fingerprint.FingerprintService; +import com.android.server.gpu.GpuService; import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; import com.android.server.job.JobSchedulerService; @@ -747,6 +748,11 @@ public final class SystemServer { traceBeginAndSlog("StartBugreportManagerService"); mSystemServiceManager.startService(BugreportManagerService.class); traceEnd(); + + // Serivce for GPU and GPU driver. + traceBeginAndSlog("GpuService"); + mSystemServiceManager.startService(GpuService.class); + traceEnd(); } /** diff --git a/services/net/Android.bp b/services/net/Android.bp index 8f48f5b3d292..ab11fe4df283 100644 --- a/services/net/Android.bp +++ b/services/net/Android.bp @@ -3,8 +3,6 @@ aidl_interface { name: "ipmemorystore-aidl-interfaces", local_include_dir: "java", srcs: [ - // TODO: Define and use a filegroup for these files, since they're also used in - // networkstack-aidl-interfaces. This does not appear to work at the moment. "java/android/net/IIpMemoryStore.aidl", "java/android/net/IIpMemoryStoreCallbacks.aidl", "java/android/net/ipmemorystore/**/*.aidl", @@ -17,22 +15,25 @@ aidl_interface { enabled: false, }, }, - api_dir: "aidl/networkstack", + api_dir: "aidl/ipmemorystore", + versions: [ + "1", + "2", + ], } aidl_interface { name: "networkstack-aidl-interfaces", local_include_dir: "java", - include_dirs: ["frameworks/base/core/java"], // For framework parcelables. + include_dirs: ["frameworks/base/core/java"], // For framework parcelables. srcs: [ "java/android/net/DhcpResultsParcelable.aidl", - "java/android/net/IIpMemoryStore.aidl", - "java/android/net/IIpMemoryStoreCallbacks.aidl", "java/android/net/INetworkMonitor.aidl", "java/android/net/INetworkMonitorCallbacks.aidl", "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", @@ -41,7 +42,6 @@ aidl_interface { "java/android/net/dhcp/IDhcpServerCallbacks.aidl", "java/android/net/ip/IIpClient.aidl", "java/android/net/ip/IIpClientCallbacks.aidl", - "java/android/net/ipmemorystore/**/*.aidl", ], backend: { ndk: { @@ -52,6 +52,12 @@ aidl_interface { }, }, api_dir: "aidl/networkstack", + imports: ["ipmemorystore-aidl-interfaces"], + versions: [ + "1", + "2", + "3", + ], } java_library_static { @@ -59,9 +65,10 @@ java_library_static { srcs: ["java/**/*.java"], static_libs: [ "dnsresolver_aidl_interface-java", + "ipmemorystore-client", "netd_aidl_interface-java", "networkstack-aidl-interfaces-java", - ] + ], } java_library_static { @@ -74,7 +81,7 @@ java_library_static { ], static_libs: [ "ipmemorystore-aidl-interfaces-java", - ] + ], } filegroup { diff --git a/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl new file mode 100644 index 000000000000..a8cbab26190f --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl new file mode 100644 index 000000000000..cf02c26c2fe3 --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl new file mode 100644 index 000000000000..291dbef817e6 --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl @@ -0,0 +1,4 @@ +package android.net.ipmemorystore; +parcelable Blob { + byte[] data; +} diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl new file mode 100644 index 000000000000..52f40d49abd5 --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl new file mode 100644 index 000000000000..785351435d73 --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl new file mode 100644 index 000000000000..3dd2ae6e9bab --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl new file mode 100644 index 000000000000..46d4ecb9ed7c --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl new file mode 100644 index 000000000000..54e654b80c9e --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl new file mode 100644 index 000000000000..9531ea3963fb --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl new file mode 100644 index 000000000000..414272b49f1d --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/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/1/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl new file mode 100644 index 000000000000..92c6779b5dc0 --- /dev/null +++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl @@ -0,0 +1,4 @@ +package android.net.ipmemorystore; +parcelable StatusParcelable { + int resultCode; +} 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/1/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl new file mode 100644 index 000000000000..92b5345ee221 --- /dev/null +++ b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl @@ -0,0 +1,8 @@ +package android.net; +parcelable DhcpResultsParcelable { + android.net.StaticIpConfiguration baseConfiguration; + int leaseDuration; + int mtu; + String serverAddress; + String vendorInfo; +} diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl new file mode 100644 index 000000000000..b19f522880ec --- /dev/null +++ b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl @@ -0,0 +1,17 @@ +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; +} diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl new file mode 100644 index 000000000000..ee9871ddcd15 --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl new file mode 100644 index 000000000000..7da11e476c0e --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl new file mode 100644 index 000000000000..f6ca6f7a78e2 --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl new file mode 100644 index 000000000000..c80a78785b3b --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl new file mode 100644 index 000000000000..2de790bb7754 --- /dev/null +++ b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl @@ -0,0 +1,5 @@ +package android.net; +parcelable PrivateDnsConfigParcel { + String hostname; + String[] ips; +} diff --git a/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl new file mode 100644 index 000000000000..3a6c30496fd8 --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl new file mode 100644 index 000000000000..e121c064f7ac --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl new file mode 100644 index 000000000000..67193ae904bc --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl new file mode 100644 index 000000000000..914315855496 --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl new file mode 100644 index 000000000000..dcc4489d52a6 --- /dev/null +++ b/services/net/aidl/networkstack/1/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/1/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl new file mode 100644 index 000000000000..95a15742a684 --- /dev/null +++ b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl @@ -0,0 +1,14 @@ +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); +} diff --git a/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl new file mode 100644 index 000000000000..d6bc8089a0be --- /dev/null +++ b/services/net/aidl/networkstack/1/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/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/IIpMemoryStore.aidl b/services/net/java/android/net/IIpMemoryStore.aidl index 6f88dec8dee9..63feae65756f 100644 --- a/services/net/java/android/net/IIpMemoryStore.aidl +++ b/services/net/java/android/net/IIpMemoryStore.aidl @@ -20,8 +20,8 @@ import android.net.ipmemorystore.Blob; import android.net.ipmemorystore.NetworkAttributesParcelable; import android.net.ipmemorystore.IOnBlobRetrievedListener; import android.net.ipmemorystore.IOnL2KeyResponseListener; -import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; -import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener; +import android.net.ipmemorystore.IOnSameL3NetworkResponseListener; import android.net.ipmemorystore.IOnStatusListener; /** {@hide} */ @@ -84,7 +84,7 @@ oneway interface IIpMemoryStore { * @param listener The listener that will be invoked to return the answer. * @return (through the listener) A SameL3NetworkResponse containing the answer and confidence. */ - void isSameNetwork(String l2Key1, String l2Key2, IOnSameNetworkResponseListener listener); + void isSameNetwork(String l2Key1, String l2Key2, IOnSameL3NetworkResponseListener listener); /** * Retrieve the network attributes for a key. @@ -95,7 +95,7 @@ oneway interface IIpMemoryStore { * @return (through the listener) The network attributes and the L2 key associated with * the query. */ - void retrieveNetworkAttributes(String l2Key, IOnNetworkAttributesRetrieved listener); + void retrieveNetworkAttributes(String l2Key, IOnNetworkAttributesRetrievedListener listener); /** * Retrieve previously stored private data. 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 9248299e178d..4a115e6ec55b 100644 --- a/services/net/java/android/net/IpMemoryStore.java +++ b/services/net/java/android/net/IpMemoryStore.java @@ -41,6 +41,11 @@ public class IpMemoryStore extends IpMemoryStoreClient { public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) { mService.complete(memoryStore); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } }); } diff --git a/services/net/java/android/net/IpMemoryStoreClient.java b/services/net/java/android/net/IpMemoryStoreClient.java index 2f4fdbd8a4a7..379c017b2990 100644 --- a/services/net/java/android/net/IpMemoryStoreClient.java +++ b/services/net/java/android/net/IpMemoryStoreClient.java @@ -20,14 +20,13 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ipmemorystore.Blob; -import android.net.ipmemorystore.IOnBlobRetrievedListener; -import android.net.ipmemorystore.IOnL2KeyResponseListener; -import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; -import android.net.ipmemorystore.IOnSameNetworkResponseListener; -import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; +import android.net.ipmemorystore.OnBlobRetrievedListener; +import android.net.ipmemorystore.OnL2KeyResponseListener; +import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener; +import android.net.ipmemorystore.OnSameL3NetworkResponseListener; +import android.net.ipmemorystore.OnStatusListener; import android.net.ipmemorystore.Status; -import android.net.ipmemorystore.StatusParcelable; import android.os.RemoteException; import android.util.Log; @@ -50,12 +49,6 @@ public abstract class IpMemoryStoreClient { @NonNull protected abstract IIpMemoryStore getService() throws InterruptedException, ExecutionException; - protected StatusParcelable internalErrorStatus() { - final StatusParcelable error = new StatusParcelable(); - error.resultCode = Status.ERROR_UNKNOWN; - return error; - } - /** * Store network attributes for a given L2 key. * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to @@ -74,12 +67,13 @@ public abstract class IpMemoryStoreClient { */ public void storeNetworkAttributes(@NonNull final String l2Key, @NonNull final NetworkAttributes attributes, - @Nullable final IOnStatusListener listener) { + @Nullable final OnStatusListener listener) { try { try { - getService().storeNetworkAttributes(l2Key, attributes.toParcelable(), listener); + getService().storeNetworkAttributes(l2Key, attributes.toParcelable(), + OnStatusListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onComplete(internalErrorStatus()); + listener.onComplete(new Status(Status.ERROR_UNKNOWN)); } } catch (RemoteException e) { Log.e(TAG, "Error storing network attributes", e); @@ -99,12 +93,13 @@ public abstract class IpMemoryStoreClient { */ public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId, @NonNull final String name, @NonNull final Blob data, - @Nullable final IOnStatusListener listener) { + @Nullable final OnStatusListener listener) { try { try { - getService().storeBlob(l2Key, clientId, name, data, listener); + getService().storeBlob(l2Key, clientId, name, data, + OnStatusListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onComplete(internalErrorStatus()); + listener.onComplete(new Status(Status.ERROR_UNKNOWN)); } } catch (RemoteException e) { Log.e(TAG, "Error storing blob", e); @@ -126,12 +121,13 @@ public abstract class IpMemoryStoreClient { * Through the listener, returns the L2 key if one matched, or null. */ public void findL2Key(@NonNull final NetworkAttributes attributes, - @NonNull final IOnL2KeyResponseListener listener) { + @NonNull final OnL2KeyResponseListener listener) { try { try { - getService().findL2Key(attributes.toParcelable(), listener); + getService().findL2Key(attributes.toParcelable(), + OnL2KeyResponseListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onL2KeyResponse(internalErrorStatus(), null); + listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null); } } catch (RemoteException e) { Log.e(TAG, "Error finding L2 Key", e); @@ -148,12 +144,13 @@ public abstract class IpMemoryStoreClient { * Through the listener, a SameL3NetworkResponse containing the answer and confidence. */ public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2, - @NonNull final IOnSameNetworkResponseListener listener) { + @NonNull final OnSameL3NetworkResponseListener listener) { try { try { - getService().isSameNetwork(l2Key1, l2Key2, listener); + getService().isSameNetwork(l2Key1, l2Key2, + OnSameL3NetworkResponseListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onSameNetworkResponse(internalErrorStatus(), null); + listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null); } } catch (RemoteException e) { Log.e(TAG, "Error checking for network sameness", e); @@ -170,12 +167,13 @@ public abstract class IpMemoryStoreClient { * the query. */ public void retrieveNetworkAttributes(@NonNull final String l2Key, - @NonNull final IOnNetworkAttributesRetrieved listener) { + @NonNull final OnNetworkAttributesRetrievedListener listener) { try { try { - getService().retrieveNetworkAttributes(l2Key, listener); + getService().retrieveNetworkAttributes(l2Key, + OnNetworkAttributesRetrievedListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onNetworkAttributesRetrieved(internalErrorStatus(), null, null); + listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN), null, null); } } catch (RemoteException e) { Log.e(TAG, "Error retrieving network attributes", e); @@ -194,12 +192,13 @@ public abstract class IpMemoryStoreClient { * and the name of the data associated with the query. */ public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId, - @NonNull final String name, @NonNull final IOnBlobRetrievedListener listener) { + @NonNull final String name, @NonNull final OnBlobRetrievedListener listener) { try { try { - getService().retrieveBlob(l2Key, clientId, name, listener); + getService().retrieveBlob(l2Key, clientId, name, + OnBlobRetrievedListener.toAIDL(listener)); } catch (InterruptedException | ExecutionException m) { - listener.onBlobRetrieved(internalErrorStatus(), null, null, null); + listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN), null, null, null); } } catch (RemoteException e) { Log.e(TAG, "Error retrieving blob", e); 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/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java index 90624e0518f8..714ade12435b 100644 --- a/services/net/java/android/net/ip/IpClientUtil.java +++ b/services/net/java/android/net/ip/IpClientUtil.java @@ -175,6 +175,11 @@ public class IpClientUtil { public void setNeighborDiscoveryOffload(boolean enable) { mCb.setNeighborDiscoveryOffload(enable); } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } /** diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java index fc1128b80499..66884c60b0bc 100644 --- a/services/net/java/android/net/ip/IpServer.java +++ b/services/net/java/android/net/ip/IpServer.java @@ -277,6 +277,11 @@ public class IpServer extends StateMachine { } public abstract void callback(int statusCode); + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } } private class DhcpServerCallbacksImpl extends DhcpServerCallbacks { diff --git a/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl b/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl index fb4ca3b97895..870e217eb5b7 100644 --- a/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl @@ -20,7 +20,7 @@ import android.net.ipmemorystore.NetworkAttributesParcelable; import android.net.ipmemorystore.StatusParcelable; /** {@hide} */ -oneway interface IOnNetworkAttributesRetrieved { +oneway interface IOnNetworkAttributesRetrievedListener { /** * Network attributes were fetched for the specified L2 key. While the L2 key will never * be null, the attributes may be if no data is stored about this L2 key. diff --git a/services/net/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl b/services/net/java/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl index 294bd3bd4012..b8ccfb99fddd 100644 --- a/services/net/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl +++ b/services/net/java/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl @@ -20,10 +20,10 @@ import android.net.ipmemorystore.SameL3NetworkResponseParcelable; import android.net.ipmemorystore.StatusParcelable; /** {@hide} */ -oneway interface IOnSameNetworkResponseListener { +oneway interface IOnSameL3NetworkResponseListener { /** * The memory store has come up with the answer to a query that was sent. */ - void onSameNetworkResponse(in StatusParcelable status, + void onSameL3NetworkResponse(in StatusParcelable status, in SameL3NetworkResponseParcelable response); } diff --git a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java new file mode 100644 index 000000000000..a17483a84e78 --- /dev/null +++ b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java @@ -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.ipmemorystore; + +import android.annotation.NonNull; + +/** + * A listener for the IpMemoryStore to return a blob. + * @hide + */ +public interface OnBlobRetrievedListener { + /** + * The memory store has come up with the answer to a query that was sent. + */ + void onBlobRetrieved(Status status, String l2Key, String name, Blob blob); + + /** Converts this OnBlobRetrievedListener to a parcelable object */ + @NonNull + static IOnBlobRetrievedListener toAIDL(@NonNull final OnBlobRetrievedListener listener) { + return new IOnBlobRetrievedListener.Stub() { + @Override + public void onBlobRetrieved(final StatusParcelable statusParcelable, final String l2Key, + final String name, final Blob blob) { + // NonNull, but still don't crash the system server if null + if (null != listener) { + listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob); + } + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + }; + } +} diff --git a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java new file mode 100644 index 000000000000..e608aecbf498 --- /dev/null +++ b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java @@ -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.ipmemorystore; + +import android.annotation.NonNull; + +/** + * A listener for the IpMemoryStore to return a L2 key. + * @hide + */ +public interface OnL2KeyResponseListener { + /** + * The operation has completed with the specified status. + */ + void onL2KeyResponse(Status status, String l2Key); + + /** Converts this OnL2KeyResponseListener to a parcelable object */ + @NonNull + static IOnL2KeyResponseListener toAIDL(@NonNull final OnL2KeyResponseListener listener) { + return new IOnL2KeyResponseListener.Stub() { + @Override + public void onL2KeyResponse(final StatusParcelable statusParcelable, + final String l2Key) { + // NonNull, but still don't crash the system server if null + if (null != listener) { + listener.onL2KeyResponse(new Status(statusParcelable), l2Key); + } + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + }; + } +} diff --git a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java new file mode 100644 index 000000000000..ca6f3029d496 --- /dev/null +++ b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java @@ -0,0 +1,54 @@ +/* + * 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.ipmemorystore; + +import android.annotation.NonNull; + +/** + * A listener for the IpMemoryStore to return network attributes. + * @hide + */ +public interface OnNetworkAttributesRetrievedListener { + /** + * The memory store has come up with the answer to a query that was sent. + */ + void onNetworkAttributesRetrieved(Status status, String l2Key, NetworkAttributes attributes); + + /** Converts this OnNetworkAttributesRetrievedListener to a parcelable object */ + @NonNull + static IOnNetworkAttributesRetrievedListener toAIDL( + @NonNull final OnNetworkAttributesRetrievedListener listener) { + return new IOnNetworkAttributesRetrievedListener.Stub() { + @Override + public void onNetworkAttributesRetrieved(final StatusParcelable statusParcelable, + final String l2Key, + final NetworkAttributesParcelable networkAttributesParcelable) { + // NonNull, but still don't crash the system server if null + if (null != listener) { + listener.onNetworkAttributesRetrieved( + new Status(statusParcelable), l2Key, + new NetworkAttributes(networkAttributesParcelable)); + } + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + }; + } +} diff --git a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java new file mode 100644 index 000000000000..67f8da81c3f2 --- /dev/null +++ b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java @@ -0,0 +1,53 @@ +/* + * 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.ipmemorystore; + +import android.annotation.NonNull; + +/** + * A listener for the IpMemoryStore to return a response about network sameness. + * @hide + */ +public interface OnSameL3NetworkResponseListener { + /** + * The memory store has come up with the answer to a query that was sent. + */ + void onSameL3NetworkResponse(Status status, SameL3NetworkResponse response); + + /** Converts this OnSameL3NetworkResponseListener to a parcelable object */ + @NonNull + static IOnSameL3NetworkResponseListener toAIDL( + @NonNull final OnSameL3NetworkResponseListener listener) { + return new IOnSameL3NetworkResponseListener.Stub() { + @Override + public void onSameL3NetworkResponse(final StatusParcelable statusParcelable, + final SameL3NetworkResponseParcelable sameL3NetworkResponseParcelable) { + // NonNull, but still don't crash the system server if null + if (null != listener) { + listener.onSameL3NetworkResponse( + new Status(statusParcelable), + new SameL3NetworkResponse(sameL3NetworkResponseParcelable)); + } + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + }; + } +} diff --git a/services/net/java/android/net/ipmemorystore/OnStatusListener.java b/services/net/java/android/net/ipmemorystore/OnStatusListener.java new file mode 100644 index 000000000000..4262efde8843 --- /dev/null +++ b/services/net/java/android/net/ipmemorystore/OnStatusListener.java @@ -0,0 +1,49 @@ +/* + * 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.ipmemorystore; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * A listener for the IpMemoryStore to return a status to a client. + * @hide + */ +public interface OnStatusListener { + /** + * The operation has completed with the specified status. + */ + void onComplete(Status status); + + /** Converts this OnStatusListener to a parcelable object */ + @NonNull + static IOnStatusListener toAIDL(@Nullable final OnStatusListener listener) { + return new IOnStatusListener.Stub() { + @Override + public void onComplete(final StatusParcelable statusParcelable) { + if (null != listener) { + listener.onComplete(new Status(statusParcelable)); + } + } + + @Override + public int getInterfaceVersion() { + return this.VERSION; + } + }; + } +} 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/startop/iorap/TEST_MAPPING b/startop/iorap/DISABLED_TEST_MAPPING index 8c9d4dfb0894..8c9d4dfb0894 100644 --- a/startop/iorap/TEST_MAPPING +++ b/startop/iorap/DISABLED_TEST_MAPPING 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 51cff8f8edf8..c449dbf02c2e 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1199,6 +1199,82 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string"; /** + * 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 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). + * B1 = 1: display of registered PLMN name required when registered PLMN is either HPLMN or a + * PLMN in the service provider PLMN list(see EF_SPDI). + * B2 = 0: display of the service provider name is required when registered PLMN is neither + * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI). + * B2 = 1: display of the service provider name is not required when registered PLMN is neither + * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI). + * + * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.12 EF_SPN. + * @hide + */ + public static final String KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT = + "spn_display_condition_override_int"; + + /** + * Override the SPDI - an array of PLMN(MCC + MNC) strings. + * + * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.66 EF_SPDI. + * @hide + */ + public static final String KEY_SPDI_OVERRIDE_STRING_ARRAY = "spdi_override_string_array"; + + /** + * Override the EHPLMNs - an array of PLMN(MCC + MNC) strings. + * + * To allow provision for multiple HPLMN codes, PLMN codes that are present within this list + * shall replace the HPLMN code derived from the IMSI for PLMN selection purposes. + * + * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.84 EF_EHPLMN + * Reference: 3GPP TS 23.122 v15.6.0 Section 1.2 Equivalent HPLMN list + * @hide + */ + public static final String KEY_EHPLMN_OVERRIDE_STRING_ARRAY = "ehplmn_override_string_array"; + + /** + * Override the PNN - a string array of comma-separated alpha long and short names: + * "alpha_long1,alpha_short1". + * + * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.58 EF_PNN. + * @hide + */ + public static final String KEY_PNN_OVERRIDE_STRING_ARRAY = "pnn_override_string_array"; + + /** + * A string array of OPL records, each with comma-delimited data fields as follows: + * "plmn1,lactac_start,lactac_end,index". + * + * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.59 EF_OPL. + * @hide + */ + public static final String KEY_OPL_OVERRIDE_STRING_ARRAY = "opl_override_opl_string_array"; + + /** + * 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 + */ + public static final String KEY_ALLOW_ERI_BOOL = "allow_cdma_eri_bool"; + + /** + * If true, use the carrier display name(SPN and PLMN) from the carrier display name resolver. + * + * @hide + */ + public static final String KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL = + "enable_carrier_display_name_resolver_bool"; + + /** * String to override sim country iso. * Sim country iso is based on sim MCC which is coarse and doesn't work with dual IMSI SIM where * a SIM can have multiple MCC from different countries. @@ -1312,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 */ @@ -2800,6 +2894,13 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false); sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false); sDefaults.putString(KEY_CARRIER_NAME_STRING, ""); + sDefaults.putInt(KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT, -1); + sDefaults.putStringArray(KEY_SPDI_OVERRIDE_STRING_ARRAY, null); + sDefaults.putStringArray(KEY_PNN_OVERRIDE_STRING_ARRAY, null); + sDefaults.putStringArray(KEY_OPL_OVERRIDE_STRING_ARRAY, null); + sDefaults.putStringArray(KEY_EHPLMN_OVERRIDE_STRING_ARRAY, null); + sDefaults.putBoolean(KEY_ALLOW_ERI_BOOL, false); + sDefaults.putBoolean(KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false); sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, ""); sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false); @@ -2946,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); @@ -3056,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/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java index 2cb369d28029..3dd931898c18 100644 --- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java @@ -95,6 +95,21 @@ public final class DataSpecificRegistrationInfo implements Parcelable { this.mIsUsingCarrierAggregation = isUsingCarrierAggregation; } + /** + * Constructor from another data specific registration info + * + * @param dsri another data specific registration info + * @hide + */ + DataSpecificRegistrationInfo(DataSpecificRegistrationInfo dsri) { + maxDataCalls = dsri.maxDataCalls; + isDcNrRestricted = dsri.isDcNrRestricted; + isNrAvailable = dsri.isNrAvailable; + isEnDcAvailable = dsri.isEnDcAvailable; + mLteVopsSupportInfo = dsri.mLteVopsSupportInfo; + mIsUsingCarrierAggregation = dsri.mIsUsingCarrierAggregation; + } + private DataSpecificRegistrationInfo(Parcel source) { maxDataCalls = source.readInt(); isDcNrRestricted = source.readBoolean(); diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java index 7b9f6d5eb8a1..2fae949cacb3 100644 --- a/telephony/java/android/telephony/NetworkRegistrationInfo.java +++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java @@ -280,6 +280,39 @@ public final class NetworkRegistrationInfo implements Parcelable { } /** + * Constructor from another network registration info + * + * @param nri Another network registration info + * @hide + */ + public NetworkRegistrationInfo(NetworkRegistrationInfo nri) { + mDomain = nri.mDomain; + mTransportType = nri.mTransportType; + mRegistrationState = nri.mRegistrationState; + mRoamingType = nri.mRoamingType; + mAccessNetworkTechnology = nri.mAccessNetworkTechnology; + mRejectCause = nri.mRejectCause; + mEmergencyOnly = nri.mEmergencyOnly; + mAvailableServices = new ArrayList<>(nri.mAvailableServices); + if (nri.mCellIdentity != null) { + Parcel p = Parcel.obtain(); + nri.mCellIdentity.writeToParcel(p, 0); + p.setDataPosition(0); + // TODO: Instead of doing this, we should create a formal way for cloning cell identity. + // Cell identity is not an immutable object so we have to deep copy it. + mCellIdentity = CellIdentity.CREATOR.createFromParcel(p); + } + + if (nri.mVoiceSpecificInfo != null) { + mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(nri.mVoiceSpecificInfo); + } + if (nri.mDataSpecificInfo != null) { + mDataSpecificInfo = new DataSpecificRegistrationInfo(nri.mDataSpecificInfo); + } + mNrState = nri.mNrState; + } + + /** * @return The transport type. */ public @TransportType int getTransportType() { return mTransportType; } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index f4a6984001cb..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 @@ -418,8 +421,10 @@ public class ServiceState implements Parcelable { Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length); mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost; mNetworkRegistrationInfos = s.mNetworkRegistrationInfos == null ? null : - new ArrayList<>(s.mNetworkRegistrationInfos); + 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() { @@ -1113,16 +1130,16 @@ public class ServiceState implements Parcelable { /** @hide */ @TestApi public void setVoiceRoamingType(@RoamingType int type) { - NetworkRegistrationInfo regState = getNetworkRegistrationInfo( + NetworkRegistrationInfo regInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (regState == null) { - regState = new NetworkRegistrationInfo.Builder() + if (regInfo == null) { + regInfo = new NetworkRegistrationInfo.Builder() .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .build(); - addNetworkRegistrationInfo(regState); } - regState.setRoamingType(type); + regInfo.setRoamingType(type); + addNetworkRegistrationInfo(regInfo); } /** @hide */ @@ -1134,16 +1151,16 @@ public class ServiceState implements Parcelable { /** @hide */ @TestApi public void setDataRoamingType(@RoamingType int type) { - NetworkRegistrationInfo regState = getNetworkRegistrationInfo( + NetworkRegistrationInfo regInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (regState == null) { - regState = new NetworkRegistrationInfo.Builder() + if (regInfo == null) { + regInfo = new NetworkRegistrationInfo.Builder() .setDomain(NetworkRegistrationInfo.DOMAIN_PS) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .build(); - addNetworkRegistrationInfo(regState); } - regState.setRoamingType(type); + regInfo.setRoamingType(type); + addNetworkRegistrationInfo(regInfo); } /** @@ -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 */ @@ -1305,16 +1324,16 @@ public class ServiceState implements Parcelable { Rlog.e(LOG_TAG, "ServiceState.setRilVoiceRadioTechnology() called. It's encouraged to " + "use addNetworkRegistrationInfo() instead *******"); // Sync to network registration state - NetworkRegistrationInfo regState = getNetworkRegistrationInfo( + NetworkRegistrationInfo regInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (regState == null) { - regState = new NetworkRegistrationInfo.Builder() + if (regInfo == null) { + regInfo = new NetworkRegistrationInfo.Builder() .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .build(); - addNetworkRegistrationInfo(regState); } - regState.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt)); + regInfo.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt)); + addNetworkRegistrationInfo(regInfo); } @@ -1326,17 +1345,17 @@ public class ServiceState implements Parcelable { // Sync to network registration state. Always write down the WWAN transport. For AP-assisted // mode device, use addNetworkRegistrationInfo() to set the correct transport if RAT // is IWLAN. - NetworkRegistrationInfo regState = getNetworkRegistrationInfo( + NetworkRegistrationInfo regInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (regState == null) { - regState = new NetworkRegistrationInfo.Builder() + if (regInfo == null) { + regInfo = new NetworkRegistrationInfo.Builder() .setDomain(NetworkRegistrationInfo.DOMAIN_PS) .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .build(); - addNetworkRegistrationInfo(regState); } - regState.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt)); + regInfo.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt)); + addNetworkRegistrationInfo(regInfo); } /** @hide */ @@ -1378,10 +1397,10 @@ public class ServiceState implements Parcelable { * @hide */ public @NRState int getNrState() { - final NetworkRegistrationInfo regState = getNetworkRegistrationInfo( + final NetworkRegistrationInfo regInfo = getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); - if (regState == null) return NetworkRegistrationInfo.NR_STATE_NONE; - return regState.getNrState(); + if (regInfo == null) return NetworkRegistrationInfo.NR_STATE_NONE; + return regInfo.getNrState(); } /** @@ -1775,7 +1794,11 @@ public class ServiceState implements Parcelable { @SystemApi public List<NetworkRegistrationInfo> getNetworkRegistrationInfoList() { synchronized (mNetworkRegistrationInfos) { - return new ArrayList<>(mNetworkRegistrationInfos); + List<NetworkRegistrationInfo> newList = new ArrayList<>(); + for (NetworkRegistrationInfo nri : mNetworkRegistrationInfos) { + newList.add(new NetworkRegistrationInfo(nri)); + } + return newList; } } @@ -1795,7 +1818,7 @@ public class ServiceState implements Parcelable { synchronized (mNetworkRegistrationInfos) { for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) { if (networkRegistrationInfo.getTransportType() == transportType) { - list.add(networkRegistrationInfo); + list.add(new NetworkRegistrationInfo(networkRegistrationInfo)); } } } @@ -1819,7 +1842,7 @@ public class ServiceState implements Parcelable { synchronized (mNetworkRegistrationInfos) { for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) { if (networkRegistrationInfo.getDomain() == domain) { - list.add(networkRegistrationInfo); + list.add(new NetworkRegistrationInfo(networkRegistrationInfo)); } } } @@ -1844,7 +1867,7 @@ public class ServiceState implements Parcelable { for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) { if (networkRegistrationInfo.getTransportType() == transportType && networkRegistrationInfo.getDomain() == domain) { - return networkRegistrationInfo; + return new NetworkRegistrationInfo(networkRegistrationInfo); } } } @@ -1856,20 +1879,20 @@ public class ServiceState implements Parcelable { * @hide */ @TestApi - public void addNetworkRegistrationInfo(NetworkRegistrationInfo regState) { - if (regState == null) return; + public void addNetworkRegistrationInfo(NetworkRegistrationInfo nri) { + if (nri == null) return; synchronized (mNetworkRegistrationInfos) { for (int i = 0; i < mNetworkRegistrationInfos.size(); i++) { NetworkRegistrationInfo curRegState = mNetworkRegistrationInfos.get(i); - if (curRegState.getTransportType() == regState.getTransportType() - && curRegState.getDomain() == regState.getDomain()) { + if (curRegState.getTransportType() == nri.getTransportType() + && curRegState.getDomain() == nri.getDomain()) { mNetworkRegistrationInfos.remove(i); break; } } - mNetworkRegistrationInfos.add(regState); + mNetworkRegistrationInfos.add(new NetworkRegistrationInfo(nri)); } } @@ -1906,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 586c815ae7b5..43acfdddf819 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -294,6 +294,19 @@ public class SubscriptionManager { public static final String SUBSCRIPTION_TYPE = "subscription_type"; /** + * TelephonyProvider column name white_listed_apn_data. + * It's a bitmask of APN types that will be allowed on this subscription even if it's metered + * and mobile data is turned off by the user. + * <P>Type: INTEGER (int)</P> For example, if TYPE_MMS is is true, Telephony will allow MMS + * data connection to setup even if MMS is metered and mobile_data is turned off on that + * subscription. + * + * Default value is 0. + */ + /** @hide */ + public static final String WHITE_LISTED_APN_DATA = "white_listed_apn_data"; + + /** * This constant is to designate a subscription as a Local-SIM Subscription. * <p> A Local-SIM can be a physical SIM inserted into a sim-slot in the device, or eSIM on the * device. @@ -2052,7 +2065,6 @@ public class SubscriptionManager { } else { logd("putPhoneIdAndSubIdExtra: no valid subs"); intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); - intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); } } @@ -2063,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); } /** @@ -3087,6 +3096,31 @@ public class SubscriptionManager { return subId; } + /** + * Set whether a subscription always allows MMS connection. If true, MMS network + * request will be accepted by telephony even if user turns "mobile data" off + * on this subscription. + * + * @param subId which subscription it's setting to. + * @param alwaysAllow whether Mms data is always allowed. + * @return whether operation is successful. + * + * @hide + */ + public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) { + try { + ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); + if (iSub != null) { + return iSub.setAlwaysAllowMmsData(subId, alwaysAllow); + } + } catch (RemoteException ex) { + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } + } + return false; + } + private interface CallISubMethodHelper { int callMethod(ISub iSub) throws RemoteException; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index e1425b975525..510e7c9f864f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -64,6 +64,7 @@ import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.VisualVoicemailService.VisualVoicemailTask; +import android.telephony.data.ApnSetting; import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories; import android.telephony.ims.aidl.IImsConfig; @@ -2276,12 +2277,15 @@ public class TelephonyManager { } /** - * Returns the ISO country code equivalent of the MCC (Mobile Country Code) of the current + * Returns the ISO-3166 country code equivalent of the MCC (Mobile Country Code) of the current * registered operator or the cell nearby, if available. - * . + * <p> + * The ISO-3166 country code is provided in lowercase 2 character format. * <p> * Note: Result may be unreliable on CDMA networks (use {@link #getPhoneType()} to determine * if on a CDMA network). + * <p> + * @return the lowercase 2 character ISO-3166 country code, or empty string if not available. */ public String getNetworkCountryIso() { return getNetworkCountryIsoForPhone(getPhoneId()); @@ -3140,7 +3144,10 @@ public class TelephonyManager { } /** - * Returns the ISO country code equivalent for the SIM provider's country code. + * Returns the ISO-3166 country code equivalent for the SIM provider's country code. + * <p> + * The ISO-3166 country code is provided in lowercase 2 character format. + * @return the lowercase 2 character ISO-3166 country code, or empty string is not available. */ public String getSimCountryIso() { return getSimCountryIsoForPhone(getPhoneId()); @@ -3274,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> @@ -10888,4 +10895,58 @@ public class TelephonyManager { } return new Pair<Integer, Integer>(-1, -1); } + + /** + * Return whether data is enabled for certain APN type. This will tell if framework will accept + * corresponding network requests on a subId. + * + * {@link #isDataEnabled()} is directly associated with users' Mobile data toggle on / off. If + * {@link #isDataEnabled()} returns false, it means in general all meter-ed data are disabled. + * + * This per APN type API gives a better idea whether data is allowed on a specific APN type. + * It will return true if: + * + * 1) User data is turned on, or + * 2) APN is un-metered for this subscription, or + * 3) APN type is whitelisted. E.g. MMS is whitelisted if + * {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on. + * + * @return whether data is enabled for a apn type. + * + * @hide + */ + public boolean isDataEnabledForApn(@ApnSetting.ApnType int apnType) { + String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.isDataEnabledForApn(apnType, getSubId(), pkgForDebug); + } + } catch (RemoteException ex) { + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } + } + return false; + } + + /** + * Whether an APN type is metered or not. It will be evaluated with the subId associated + * with the TelephonyManager instance. + * + * @hide + */ + public boolean isApnMetered(@ApnSetting.ApnType int apnType) { + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.isApnMetered(apnType, getSubId()); + } + } catch (RemoteException ex) { + if (!isSystemProcess()) { + ex.rethrowAsRuntimeException(); + } + } + return true; + } } 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/VoiceSpecificRegistrationInfo.java b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java index 18a533a46273..d43181e68c28 100644 --- a/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java +++ b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java @@ -65,6 +65,19 @@ public class VoiceSpecificRegistrationInfo implements Parcelable{ this.defaultRoamingIndicator = defaultRoamingIndicator; } + /** + * Constructor from another voice specific registration info + * + * @param vsri another voice specific registration info + * @hide + */ + VoiceSpecificRegistrationInfo(VoiceSpecificRegistrationInfo vsri) { + cssSupported = vsri.cssSupported; + roamingIndicator = vsri.roamingIndicator; + systemIsInPrl = vsri.systemIsInPrl; + defaultRoamingIndicator = vsri.defaultRoamingIndicator; + } + private VoiceSpecificRegistrationInfo(Parcel source) { this.cssSupported = source.readBoolean(); this.roamingIndicator = source.readInt(); diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java index dba220718818..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); @@ -635,7 +650,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu != second.getEmergencyServiceCategoryBitmask()) { return false; } - if (first.getEmergencyUrns().equals(second.getEmergencyUrns())) { + if (!first.getEmergencyUrns().equals(second.getEmergencyUrns())) { return false; } if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) { 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/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 6e8d038eda4f..bb5c251b69e1 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -94,6 +94,7 @@ public class DctConstants { public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48; public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49; public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 50; + public static final int EVENT_APN_WHITE_LIST_CHANGE = BASE + 51; /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index 118f5e26e6e7..f248893ec638 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -283,4 +283,6 @@ interface ISub { int getSimStateForSlotIndex(int slotIndex); boolean isActiveSubId(int subId, String callingPackage); + + boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index d173cc9c44e5..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> @@ -1958,4 +1958,8 @@ interface ITelephony { int getRadioHalVersion(); boolean isModemEnabledForSlot(int slotIndex, String callingPackage); + + boolean isDataEnabledForApn(int apnType, int subId, String callingPackage); + + boolean isApnMetered(int apnType, int subId); } 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/Android.bp b/tests/net/Android.bp index 9098f90fd777..1fbb6580c389 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -6,6 +6,7 @@ java_defaults { static_libs: [ "FrameworksNetCommonTests", "frameworks-base-testutils", + "frameworks-net-testutils", "framework-protos", "androidx.test.rules", "mockito-target-minus-junit4", @@ -63,7 +64,7 @@ java_defaults { android_test { name: "FrameworksNetTests", defaults: ["FrameworksNetTests-jni-defaults"], - srcs: ["java/**/*.java"], + srcs: ["java/**/*.java", "java/**/*.kt"], platform_apis: true, test_suites: ["device-tests"], certificate: "platform", diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp index 0a1ac75aac80..07525a6ea49c 100644 --- a/tests/net/common/Android.bp +++ b/tests/net/common/Android.bp @@ -18,10 +18,12 @@ // They must be fast and stable, and exercise public or test APIs. java_library { name: "FrameworksNetCommonTests", - srcs: ["java/**/*.java"], + srcs: ["java/**/*.java", "java/**/*.kt"], static_libs: [ "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/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index d462441b22fa..d462441b22fa 100644 --- a/tests/net/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 417729150be8..709f5f69aa2b 100644 --- a/tests/net/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -868,12 +868,12 @@ public class LinkPropertiesTest { source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96")); - TestUtils.assertParcelingIsLossless(source, LinkProperties.CREATOR); + TestUtils.assertParcelingIsLossless(source); } @Test public void testParcelUninitialized() throws Exception { LinkProperties empty = new LinkProperties(); - TestUtils.assertParcelingIsLossless(empty, LinkProperties.CREATOR); + TestUtils.assertParcelingIsLossless(empty); } } diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index ad76388b3c9b..6bc7c1bb30f8 100644 --- a/tests/net/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/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java index 0bee7cd29d29..bef66b27df62 100644 --- a/tests/net/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/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index 2edbd403b5b5..2edbd403b5b5 100644 --- a/tests/net/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java diff --git a/tests/net/java/android/net/StaticIpConfigurationTest.java b/tests/net/common/java/android/net/StaticIpConfigurationTest.java index 8449ca76d580..5096be221cbf 100644 --- a/tests/net/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/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java index 75752c33da5c..3ed8a86b2fb5 100644 --- a/tests/net/java/android/net/apf/ApfCapabilitiesTest.java +++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java @@ -19,11 +19,10 @@ package android.net.apf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import android.net.shared.ParcelableTestUtil; - 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.Test; @@ -37,7 +36,7 @@ public class ApfCapabilitiesTest { final ApfCapabilities caps = new ApfCapabilities(123, 456, 789); ParcelableTestUtil.assertFieldCountEquals(3, ApfCapabilities.class); - TestUtils.assertParcelingIsLossless(caps, ApfCapabilities.CREATOR); + TestUtils.assertParcelingIsLossless(caps); } @Test 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 new file mode 100644 index 000000000000..e9d5e6db1c7e --- /dev/null +++ b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt @@ -0,0 +1,65 @@ +package android.net.metrics + +import android.net.metrics.DhcpErrorEvent.errorCodeWithOption +import android.net.metrics.DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.internal.util.TestUtils.parcelingRoundTrip +import java.lang.reflect.Modifier +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +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 due to it's protected) +private const val DHCP_SUBNET_MASK = 1 + +@RunWith(AndroidJUnit4::class) +@SmallTest +class DhcpErrorEventTest { + + @Test + fun testConstructor() { + val event = DhcpErrorEvent(TEST_ERROR_CODE) + assertEquals(TEST_ERROR_CODE, event.errorCode) + } + + @Test + fun testParcelUnparcel() { + val event = DhcpErrorEvent(TEST_ERROR_CODE) + val parceled = parcelingRoundTrip(event) + assertEquals(TEST_ERROR_CODE, parceled.errorCode) + } + + @Test + fun testErrorCodeWithOption() { + val errorCode = errorCodeWithOption(DHCP_INVALID_OPTION_LENGTH, DHCP_SUBNET_MASK); + assertTrue((DHCP_INVALID_OPTION_LENGTH and errorCode) == DHCP_INVALID_OPTION_LENGTH); + assertTrue((DHCP_SUBNET_MASK and errorCode) == DHCP_SUBNET_MASK); + } + + @Test + fun testToString() { + val names = listOf("L2_ERROR", "L3_ERROR", "L4_ERROR", "DHCP_ERROR", "MISC_ERROR") + val errorFields = DhcpErrorEvent::class.java.declaredFields.filter { + it.type == Int::class.javaPrimitiveType + && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) + && it.name !in names + } + + errorFields.forEach { + val intValue = it.getInt(null) + val stringValue = DhcpErrorEvent(intValue).toString() + assertTrue("Invalid string for error 0x%08X (field %s): %s".format(intValue, it.name, + stringValue), + stringValue.contains(it.name)) + } + } + + @Test + fun testToString_InvalidErrorCode() { + assertNotNull(DhcpErrorEvent(TEST_ERROR_CODE).toString()) + } +}
\ No newline at end of file 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/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index e0b722761c34..583d3fd536aa 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -79,7 +79,7 @@ public final class TcpKeepalivePacketDataTest { assertEquals(testInfo.tos, resultData.ipTos); assertEquals(testInfo.ttl, resultData.ipTtl); - TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR); + TestUtils.assertParcelingIsLossless(resultData); final byte[] packet = resultData.getPacket(); // IP version and IHL diff --git a/tests/net/java/android/net/shared/InitialConfigurationTest.java b/tests/net/java/android/net/shared/InitialConfigurationTest.java index 27bc13d75440..2fb8b19abcd4 100644 --- a/tests/net/java/android/net/shared/InitialConfigurationTest.java +++ b/tests/net/java/android/net/shared/InitialConfigurationTest.java @@ -17,7 +17,8 @@ package android.net.shared; import static android.net.InetAddresses.parseNumericAddress; -import static android.net.shared.ParcelableTestUtil.assertFieldCountEquals; + +import static com.android.internal.util.ParcelableTestUtil.assertFieldCountEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java index 21a4988950db..f9dbdc7fbf3e 100644 --- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java +++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java @@ -19,7 +19,8 @@ package android.net.shared; import static android.net.InetAddresses.parseNumericAddress; import static android.net.shared.IpConfigurationParcelableUtil.fromStableParcelable; import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable; -import static android.net.shared.ParcelableTestUtil.assertFieldCountEquals; + +import static com.android.internal.util.ParcelableTestUtil.assertFieldCountEquals; import static org.junit.Assert.assertEquals; @@ -54,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 @@ -100,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/android/net/shared/ProvisioningConfigurationTest.java b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java index 6fad89ec50b2..382afe0279be 100644 --- a/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java +++ b/tests/net/java/android/net/shared/ProvisioningConfigurationTest.java @@ -17,9 +17,10 @@ package android.net.shared; import static android.net.InetAddresses.parseNumericAddress; -import static android.net.shared.ParcelableTestUtil.assertFieldCountEquals; import static android.net.shared.ProvisioningConfiguration.fromStableParcelable; +import static com.android.internal.util.ParcelableTestUtil.assertFieldCountEquals; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index e3c6c4113cc5..37af461b1305 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; @@ -4228,6 +4266,25 @@ public class ConnectivityServiceTest { callback.expectStarted(); ka.stop(); callback.expectStopped(); + + // Check that the same NATT socket cannot be used by 2 keepalives. + try (SocketKeepalive ka2 = mCm.createSocketKeepalive( + myNet, testSocket, myIPv4, dstIPv4, executor, callback)) { + // Check that second keepalive cannot be started if the first one is running. + ka.start(validKaInterval); + callback.expectStarted(); + ka2.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); + ka.stop(); + callback.expectStopped(); + + // Check that second keepalive can be started/stopped normally if the first one is + // stopped. + ka2.start(validKaInterval); + callback.expectStarted(); + ka2.stop(); + callback.expectStopped(); + } } // Check that deleting the IP address stops the keepalive. @@ -4291,6 +4348,10 @@ public class ConnectivityServiceTest { testSocket.close(); testSocket2.close(); } + + // Check that the closed socket cannot be used to start keepalive. + ka.start(validKaInterval); + callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET); } // Check that there is no port leaked after all keepalives and sockets are closed. @@ -4868,7 +4929,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); @@ -4952,6 +5016,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(); @@ -5825,12 +5891,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); @@ -6022,7 +6093,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); @@ -6146,7 +6217,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6173,7 +6243,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6187,7 +6256,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); @@ -6203,7 +6271,6 @@ public class ConnectivityServiceTest { } @Test - @Ignore public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); @@ -6253,7 +6320,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/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 4a35015044ff..6b5a2203ce74 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -118,6 +118,7 @@ public class IpSecServiceTest { INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; + int mUid = Os.getuid(); @Before public void setUp() throws Exception { @@ -665,4 +666,99 @@ public class IpSecServiceTest { mIpSecService.releaseNetId(releasedNetId); assertEquals(releasedNetId, mIpSecService.reserveNetId()); } + + @Test + public void testLockEncapSocketForNattKeepalive() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(udpEncapResp.resourceId, mUid); + + // Validate response, and record was added + assertNotEquals(IpSecManager.INVALID_RESOURCE_ID, nattKeepaliveResourceId); + assertEquals(1, userRecord.mNattKeepaliveRecords.size()); + + // Validate keepalive can be released and removed. + mIpSecService.releaseNattKeepalive(nattKeepaliveResourceId, mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); + } + + @Test + public void testLockEncapSocketForNattKeepaliveInvalidUid() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + try { + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive( + udpEncapResp.resourceId, mUid + 1); + fail("Expected SecurityException for invalid user"); + } catch (SecurityException expected) { + } + + // Validate keepalive was not added to lists + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + } + + @Test + public void testLockEncapSocketForNattKeepaliveInvalidResourceId() throws Exception { + // Verify no NATT keepalive records upon startup + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + + try { + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(12345, mUid); + fail("Expected IllegalArgumentException for invalid resource ID"); + } catch (IllegalArgumentException expected) { + } + + // Validate keepalive was not added to lists + assertEquals(0, userRecord.mNattKeepaliveRecords.size()); + } + + @Test + public void testEncapSocketReleasedBeforeKeepaliveReleased() throws Exception { + IpSecUdpEncapResponse udpEncapResp = + mIpSecService.openUdpEncapsulationSocket(0, new Binder()); + assertNotNull(udpEncapResp); + assertEquals(IpSecManager.Status.OK, udpEncapResp.status); + + // Get encap socket record, verify initial starting refcount. + IpSecService.UserRecord userRecord = mIpSecService.mUserResourceTracker.getUserRecord(mUid); + IpSecService.RefcountedResource encapSocketRefcountedRecord = + userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( + udpEncapResp.resourceId); + assertEquals(1, encapSocketRefcountedRecord.mRefCount); + + // Verify that the reference was added + int nattKeepaliveResourceId = + mIpSecService.lockEncapSocketForNattKeepalive(udpEncapResp.resourceId, mUid); + assertNotEquals(IpSecManager.INVALID_RESOURCE_ID, nattKeepaliveResourceId); + assertEquals(2, encapSocketRefcountedRecord.mRefCount); + + // Close UDP encap socket, but expect the refcountedRecord to still have a reference. + mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); + assertEquals(1, encapSocketRefcountedRecord.mRefCount); + + // Verify UDP encap socket cleaned up once reference is removed. Expect -1 if cleanup + // was properly completed. + mIpSecService.releaseNattKeepalive(nattKeepaliveResourceId, mUid); + assertEquals(-1, encapSocketRefcountedRecord.mRefCount); + } } diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt new file mode 100644 index 000000000000..f045369459c9 --- /dev/null +++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt @@ -0,0 +1,114 @@ +/* + * 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 com.android.server + +import android.net.ConnectivityManager.TYPE_ETHERNET +import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_WIFI +import android.net.ConnectivityManager.TYPE_WIMAX +import android.net.NetworkInfo.DetailedState.CONNECTED +import android.net.NetworkInfo.DetailedState.DISCONNECTED +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.server.ConnectivityService.LegacyTypeTracker +import com.android.server.connectivity.NetworkAgentInfo +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertSame +import org.junit.Assert.assertTrue +import org.junit.Assert.fail +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.verify + +const val UNSUPPORTED_TYPE = TYPE_WIMAX + +@RunWith(AndroidJUnit4::class) +@SmallTest +class LegacyTypeTrackerTest { + private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET) + + private val mMockService = mock(ConnectivityService::class.java).apply { + doReturn(false).`when`(this).isDefaultNetwork(any()) + } + private val mTracker = LegacyTypeTracker(mMockService).apply { + supportedTypes.forEach { + addSupportedType(it) + } + } + + @Test + fun testSupportedTypes() { + try { + mTracker.addSupportedType(supportedTypes[0]) + fail("Expected IllegalStateException") + } catch (expected: IllegalStateException) {} + supportedTypes.forEach { + assertTrue(mTracker.isTypeSupported(it)) + } + assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE)) + } + + @Test + fun testAddNetwork() { + val mobileNai = mock(NetworkAgentInfo::class.java) + val wifiNai = mock(NetworkAgentInfo::class.java) + mTracker.add(TYPE_MOBILE, mobileNai) + mTracker.add(TYPE_WIFI, wifiNai) + assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + // Make sure adding a second NAI does not change the results. + val secondMobileNai = mock(NetworkAgentInfo::class.java) + mTracker.add(TYPE_MOBILE, secondMobileNai) + assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + // Make sure removing a network that wasn't added for this type is a no-op. + mTracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */) + assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai) + assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + // Remove the top network for mobile and make sure the second one becomes the network + // of record for this type. + mTracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */) + assertSame(mTracker.getNetworkForType(TYPE_MOBILE), secondMobileNai) + assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai) + // Make sure adding a network for an unsupported type does not register it. + mTracker.add(UNSUPPORTED_TYPE, mobileNai) + assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE)) + } + + @Test + fun testBroadcastOnDisconnect() { + val mobileNai1 = mock(NetworkAgentInfo::class.java) + val mobileNai2 = mock(NetworkAgentInfo::class.java) + doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1) + mTracker.add(TYPE_MOBILE, mobileNai1) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE) + reset(mMockService) + doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2) + mTracker.add(TYPE_MOBILE, mobileNai2) + verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt()) + mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE) + verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE) + } +} 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 fb84611cb662..a83faf34776d 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.net.ipmemorystore; +package com.android.server.connectivity.ipmemorystore; import static org.junit.Assert.assertEquals; diff --git a/tests/net/util/Android.bp b/tests/net/util/Android.bp new file mode 100644 index 000000000000..d8c502d46871 --- /dev/null +++ b/tests/net/util/Android.bp @@ -0,0 +1,30 @@ +// +// 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. +// + +// Common utilities for network tests. +java_library { + name: "frameworks-net-testutils", + srcs: ["java/**/*.java"], + // test_current to be also appropriate for CTS tests + sdk_version: "test_current", + static_libs: [ + "androidx.annotation_annotation", + "junit", + ], + libs: [ + "android.test.base.stubs", + ], +}
\ No newline at end of file diff --git a/tests/net/java/android/net/shared/ParcelableTestUtil.java b/tests/net/util/java/com/android/internal/util/ParcelableTestUtil.java index 088ea3c1d1ed..87537b93887b 100644 --- a/tests/net/java/android/net/shared/ParcelableTestUtil.java +++ b/tests/net/util/java/com/android/internal/util/ParcelableTestUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.net.shared; +package com.android.internal.util; import static org.junit.Assert.assertEquals; diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/util/java/com/android/internal/util/TestUtils.java index 57cc1723835c..a99cd4716f9a 100644 --- a/tests/net/java/com/android/internal/util/TestUtils.java +++ b/tests/net/util/java/com/android/internal/util/TestUtils.java @@ -19,7 +19,6 @@ package com.android.internal.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import android.annotation.NonNull; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; @@ -27,6 +26,8 @@ import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; + import java.util.concurrent.Executor; public final class TestUtils { @@ -36,7 +37,7 @@ public final class TestUtils { * Block until the given Handler thread becomes idle, or until timeoutMs has passed. */ public static void waitForIdleHandler(HandlerThread handlerThread, long timeoutMs) { - waitForIdleHandler(handlerThread.getThreadHandler(), timeoutMs); + waitForIdleLooper(handlerThread.getLooper(), timeoutMs); } /** @@ -68,9 +69,17 @@ public final class TestUtils { } } - // TODO : fetch the creator through reflection or something instead of passing it - public static <T extends Parcelable, C extends Parcelable.Creator<T>> - void assertParcelingIsLossless(T source, C creator) { + /** + * Return a new instance of {@code T} after being parceled then unparceled. + */ + public static <T extends Parcelable> T parcelingRoundTrip(T source) { + final Parcelable.Creator<T> creator; + try { + creator = (Parcelable.Creator<T>) source.getClass().getField("CREATOR").get(null); + } catch (IllegalAccessException | NoSuchFieldException e) { + fail("Missing CREATOR field: " + e.getMessage()); + return null; + } Parcel p = Parcel.obtain(); source.writeToParcel(p, /* flags */ 0); p.setDataPosition(0); @@ -78,7 +87,14 @@ public final class TestUtils { p = Parcel.obtain(); p.unmarshall(marshalled, 0, marshalled.length); p.setDataPosition(0); - T dest = creator.createFromParcel(p); - assertEquals(source, dest); + return creator.createFromParcel(p); + } + + /** + * Assert that after being parceled then unparceled, {@code source} is equal to the original + * object. + */ + public static <T extends Parcelable> void assertParcelingIsLossless(T source) { + assertEquals(source, parcelingRoundTrip(source)); } } diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 99420de47fca..609e3660375e 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -497,9 +497,9 @@ Maybe<int> ParseSdkVersion(const StringPiece& str) { } // Try parsing the code name. - std::pair<StringPiece, int> entry = GetDevelopmentSdkCodeNameAndVersion(); - if (entry.first == trimmed_str) { - return entry.second; + Maybe<int> entry = GetDevelopmentSdkCodeNameVersion(trimmed_str); + if (entry) { + return entry.value(); } return {}; } diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index 8ebde752bc4b..b4b6ff1daaaa 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -18,15 +18,17 @@ #include <algorithm> #include <string> -#include <unordered_map> +#include <unordered_set> #include <vector> using android::StringPiece; namespace aapt { -static const char* sDevelopmentSdkCodeName = "P"; -static ApiVersion sDevelopmentSdkLevel = 28; +static ApiVersion sDevelopmentSdkLevel = 10000; +static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>({ + "Q", "R" +}); static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { {0x021c, 1}, @@ -54,6 +56,7 @@ static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = { {0x0530, SDK_NOUGAT_MR1}, {0x0568, SDK_O}, {0x056d, SDK_O_MR1}, + {0x0586, SDK_P}, }; static bool less_entry_id(const std::pair<uint16_t, ApiVersion>& p, uint16_t entryId) { @@ -71,8 +74,9 @@ ApiVersion FindAttributeSdkLevel(const ResourceId& id) { return iter->second; } -std::pair<StringPiece, ApiVersion> GetDevelopmentSdkCodeNameAndVersion() { - return std::make_pair(StringPiece(sDevelopmentSdkCodeName), sDevelopmentSdkLevel); +Maybe<ApiVersion> GetDevelopmentSdkCodeNameVersion(const StringPiece& code_name) { + return (sDevelopmentSdkCodeNames.find(code_name) == sDevelopmentSdkCodeNames.end()) + ? Maybe<ApiVersion>() : sDevelopmentSdkLevel; } } // namespace aapt diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index 9fa29f25c29c..adb034a95328 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -57,7 +57,7 @@ enum : ApiVersion { }; ApiVersion FindAttributeSdkLevel(const ResourceId& id); -std::pair<android::StringPiece, ApiVersion> GetDevelopmentSdkCodeNameAndVersion(); +Maybe<ApiVersion> GetDevelopmentSdkCodeNameVersion(const android::StringPiece& code_name); } // namespace aapt diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp index 4c23bd3d6e3e..2ef8b999a192 100644 --- a/tools/aapt2/configuration/ConfigurationParser_test.cpp +++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp @@ -705,35 +705,24 @@ TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_InvalidVersion) { } TEST_F(ConfigurationParserTest, AndroidSdkGroupAction_NonNumeric) { - static constexpr const char* xml = R"xml( + auto doc = test::BuildXmlDom(R"xml( <android-sdk - label="P" + label="Q" minSdkVersion="25" - targetSdkVersion="%s" - maxSdkVersion="%s"> - </android-sdk>)xml"; - - const auto& dev_sdk = GetDevelopmentSdkCodeNameAndVersion(); - const char* codename = dev_sdk.first.data(); - const ApiVersion& version = dev_sdk.second; - - auto doc = test::BuildXmlDom(StringPrintf(xml, codename, codename)); + targetSdkVersion="Q" + maxSdkVersion="Q"> + </android-sdk>)xml"); PostProcessingConfiguration config; - bool ok = AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_); - ASSERT_TRUE(ok); - + ASSERT_TRUE(AndroidSdkTagHandler(&config, NodeCast<Element>(doc.get()->root.get()), &diag_)); ASSERT_EQ(1ul, config.android_sdks.size()); - ASSERT_EQ(1u, config.android_sdks.count("P")); - - auto& out = config.android_sdks["P"]; + ASSERT_EQ(1u, config.android_sdks.count("Q")); AndroidSdk sdk; sdk.min_sdk_version = 25; - sdk.target_sdk_version = version; - sdk.max_sdk_version = version; - - ASSERT_EQ(sdk, out); + sdk.target_sdk_version = 10000; + sdk.max_sdk_version = 10000; + ASSERT_EQ(sdk, config.android_sdks["Q"]); } TEST_F(ConfigurationParserTest, GlTextureGroupAction) { 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/locked_region_code_injection/src/lockedregioncodeinjection/Main.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java index edb9a49f4106..828cce72dda9 100644 --- a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java +++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java @@ -13,6 +13,9 @@ */ package lockedregioncodeinjection; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -24,8 +27,6 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; public class Main { public static void main(String[] args) throws IOException { @@ -74,6 +75,7 @@ public class Main { while (srcEntries.hasMoreElements()) { ZipEntry entry = srcEntries.nextElement(); ZipEntry newEntry = new ZipEntry(entry.getName()); + newEntry.setTime(entry.getTime()); zos.putNextEntry(newEntry); BufferedInputStream bis = new BufferedInputStream(zipSrc.getInputStream(entry)); diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp index 49eee0708a45..dc18b8d14dc7 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -219,6 +219,14 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, errorCount++; continue; } + + // Doubles are not supported yet. + if (javaType == JAVA_TYPE_DOUBLE) { + print_error(field, "Doubles are not supported in atoms. Please change field %s to float\n", + field->name().c_str()); + errorCount++; + continue; + } } // Check that if there's an attribution chain, it's at position 1. diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h index e0ea207793f9..8e4cb9f44029 100644 --- a/tools/stats_log_api_gen/Collation.h +++ b/tools/stats_log_api_gen/Collation.h @@ -48,6 +48,7 @@ typedef enum { JAVA_TYPE_DOUBLE = 6, JAVA_TYPE_STRING = 7, JAVA_TYPE_ENUM = 8, + JAVA_TYPE_KEY_VALUE_PAIR = 9, JAVA_TYPE_OBJECT = -1, JAVA_TYPE_BYTE_ARRAY = -2, @@ -118,4 +119,4 @@ int collate_atom(const Descriptor *atom, AtomDecl *atomDecl, vector<java_type_t> } // namespace android -#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H
\ No newline at end of file +#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp index 2d9b9885c5ba..43b79cc4d784 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -27,6 +27,11 @@ int maxPushedAtomId = 2; const string DEFAULT_MODULE_NAME = "DEFAULT"; const string DEFAULT_CPP_NAMESPACE = "android,util"; const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h"; +const string DEFAULT_JAVA_PACKAGE = "android.util"; +const string DEFAULT_JAVA_CLASS = "StatsLogInternal"; + +const int JAVA_MODULE_REQUIRES_FLOAT = 0x01; +const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02; using android::os::statsd::Atom; @@ -807,11 +812,350 @@ static void write_java_method( } } +static void write_java_helpers_for_module( + FILE * out, + const AtomDecl &attributionDecl, + const int requiredHelpers) { + fprintf(out, " private static void copyInt(byte[] buff, int pos, int val) {\n"); + fprintf(out, " buff[pos] = (byte) (val);\n"); + fprintf(out, " buff[pos + 1] = (byte) (val >> 8);\n"); + fprintf(out, " buff[pos + 2] = (byte) (val >> 16);\n"); + fprintf(out, " buff[pos + 3] = (byte) (val >> 24);\n"); + fprintf(out, " return;\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + + fprintf(out, " private static void copyLong(byte[] buff, int pos, long val) {\n"); + fprintf(out, " buff[pos] = (byte) (val);\n"); + fprintf(out, " buff[pos + 1] = (byte) (val >> 8);\n"); + fprintf(out, " buff[pos + 2] = (byte) (val >> 16);\n"); + fprintf(out, " buff[pos + 3] = (byte) (val >> 24);\n"); + fprintf(out, " buff[pos + 4] = (byte) (val >> 32);\n"); + fprintf(out, " buff[pos + 5] = (byte) (val >> 40);\n"); + fprintf(out, " buff[pos + 6] = (byte) (val >> 48);\n"); + fprintf(out, " buff[pos + 7] = (byte) (val >> 56);\n"); + fprintf(out, " return;\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + + if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) { + fprintf(out, " private static void copyFloat(byte[] buff, int pos, float val) {\n"); + fprintf(out, " copyInt(buff, pos, Float.floatToIntBits(val));\n"); + fprintf(out, " return;\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + } + + if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) { + fprintf(out, " private static void writeAttributionChain(byte[] buff, int pos"); + for (auto chainField : attributionDecl.fields) { + fprintf(out, ", %s[] %s", + java_type_name(chainField.javaType), chainField.name.c_str()); + } + fprintf(out, ") {\n"); + + const char* uidName = attributionDecl.fields.front().name.c_str(); + const char* tagName = attributionDecl.fields.back().name.c_str(); + + // Write the first list begin. + fprintf(out, " buff[pos] = LIST_TYPE;\n"); + fprintf(out, " buff[pos + 1] = (byte) (%s.length);\n", tagName); + fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n"); + + // Iterate through the attribution chain and write the nodes. + fprintf(out, " for (int i = 0; i < %s.length; i++) {\n", tagName); + // Write the list begin. + fprintf(out, " buff[pos] = LIST_TYPE;\n"); + fprintf(out, " buff[pos + 1] = %lu;\n", attributionDecl.fields.size()); + fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n"); + + // Write the uid. + fprintf(out, " buff[pos] = INT_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, %s[i]);\n", uidName); + fprintf(out, " pos += INT_TYPE_SIZE;\n"); + + // Write the tag. + fprintf(out, " String %sStr = (%s[i] == null) ? \"\" : %s[i];\n", + tagName, tagName, tagName); + fprintf(out, " byte[] %sByte = %sStr.getBytes(UTF_8);\n", tagName, tagName); + fprintf(out, " buff[pos] = STRING_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, %sByte.length);\n", tagName); + fprintf(out, " System.arraycopy(" + "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n", + tagName, tagName); + fprintf(out, " pos += STRING_TYPE_OVERHEAD + %sByte.length;\n", tagName); + fprintf(out, " }\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + } +} + + +static int write_java_non_chained_method_for_module( + FILE* out, + const map<vector<java_type_t>, set<string>>& signatures_to_modules, + const string& moduleName + ) { + for (auto signature_to_modules_it = signatures_to_modules.begin(); + signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) { + // Skip if this signature is not needed for the module. + if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) { + continue; + } + + // Print method signature. + vector<java_type_t> signature = signature_to_modules_it->first; + fprintf(out, " public static void write_non_chained(int code"); + int argIndex = 1; + for (vector<java_type_t>::const_iterator arg = signature.begin(); + arg != signature.end(); arg++) { + if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { + // Non chained signatures should not have attribution chains. + return 1; + } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { + // Module logging does not yet support key value pair. + return 1; + } else { + fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); + } + argIndex++; + } + fprintf(out, ") {\n"); + + fprintf(out, " write(code"); + argIndex = 1; + for (vector<java_type_t>::const_iterator arg = signature.begin(); + arg != signature.end(); arg++) { + // First two args are uid and tag of attribution chain. + if (argIndex == 1) { + fprintf(out, ", new int[] {arg%d}", argIndex); + } else if (argIndex == 2) { + fprintf(out, ", new java.lang.String[] {arg%d}", argIndex); + } else { + fprintf(out, ", arg%d", argIndex); + } + argIndex++; + } + fprintf(out, ");\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + } + return 0; +} + +static int write_java_method_for_module( + FILE* out, + const map<vector<java_type_t>, set<string>>& signatures_to_modules, + const AtomDecl &attributionDecl, + const string& moduleName, + int* requiredHelpers + ) { + + for (auto signature_to_modules_it = signatures_to_modules.begin(); + signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) { + // Skip if this signature is not needed for the module. + if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) { + continue; + } + + // Print method signature. + vector<java_type_t> signature = signature_to_modules_it->first; + fprintf(out, " public static void write(int code"); + int argIndex = 1; + for (vector<java_type_t>::const_iterator arg = signature.begin(); + arg != signature.end(); arg++) { + if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { + for (auto chainField : attributionDecl.fields) { + fprintf(out, ", %s[] %s", + java_type_name(chainField.javaType), chainField.name.c_str()); + } + } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { + // Module logging does not yet support key value pair. + return 1; + } else { + fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); + } + argIndex++; + } + fprintf(out, ") {\n"); + + // Calculate the size of the buffer. + fprintf(out, " // Initial overhead of the list, timestamp, and atom tag.\n"); + fprintf(out, " int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + INT_TYPE_SIZE;\n"); + argIndex = 1; + for (vector<java_type_t>::const_iterator arg = signature.begin(); + arg != signature.end(); arg++) { + switch (*arg) { + case JAVA_TYPE_BOOLEAN: + case JAVA_TYPE_INT: + case JAVA_TYPE_FLOAT: + case JAVA_TYPE_ENUM: + fprintf(out, " needed += INT_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_LONG: + // Longs take 9 bytes, 1 for the type and 8 for the value. + fprintf(out, " needed += LONG_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_STRING: + // Strings take 5 metadata bytes + length of byte encoded string. + fprintf(out, " if (arg%d == null) {\n", argIndex); + fprintf(out, " arg%d = \"\";\n", argIndex); + fprintf(out, " }\n"); + fprintf(out, " byte[] arg%dBytes= arg%d.getBytes(UTF_8);\n", + argIndex, argIndex); + fprintf(out, " needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n", + argIndex); + break; + case JAVA_TYPE_BYTE_ARRAY: + // Byte arrays take 5 metadata bytes + length of byte array. + fprintf(out, " if (arg%d == null) {\n", argIndex); + fprintf(out, " arg%d = new byte[0];\n", argIndex); + fprintf(out, " }\n"); + fprintf(out, " needed += STRING_TYPE_OVERHEAD + arg%d.length;\n", argIndex); + break; + case JAVA_TYPE_ATTRIBUTION_CHAIN: + { + const char* uidName = attributionDecl.fields.front().name.c_str(); + const char* tagName = attributionDecl.fields.back().name.c_str(); + // Null checks on the params. + fprintf(out, " if (%s == null) {\n", uidName); + fprintf(out, " %s = new %s[0];\n", uidName, + java_type_name(attributionDecl.fields.front().javaType)); + fprintf(out, " }\n"); + fprintf(out, " if (%s == null) {\n", tagName); + fprintf(out, " %s = new %s[0];\n", tagName, + java_type_name(attributionDecl.fields.back().javaType)); + fprintf(out, " }\n"); + + // First check that the lengths of the uid and tag arrays are the same. + fprintf(out, " if (%s.length != %s.length) {\n", uidName, tagName); + fprintf(out, " return;\n"); + fprintf(out, " }\n"); + fprintf(out, " int attrSize = LIST_TYPE_OVERHEAD;\n"); + fprintf(out, " for (int i = 0; i < %s.length; i++) {\n", tagName); + fprintf(out, " String str%d = (%s[i] == null) ? \"\" : %s[i];\n", + argIndex, tagName, tagName); + fprintf(out, " int str%dlen = str%d.getBytes(UTF_8).length;\n", + argIndex, argIndex); + fprintf(out, + " attrSize += " + "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + str%dlen;\n", + argIndex); + fprintf(out, " }\n"); + fprintf(out, " needed += attrSize;\n"); + break; + } + default: + // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR. + return 1; + } + argIndex++; + } + + // Now we have the size that is needed. Check for overflow and return if needed. + fprintf(out, " if (needed > MAX_EVENT_PAYLOAD) {\n"); + fprintf(out, " return;\n"); + fprintf(out, " }\n"); + + // Create new buffer, and associated data types. + fprintf(out, " byte[] buff = new byte[needed];\n"); + fprintf(out, " int pos = 0;\n"); + + // Initialize the buffer with list data type. + fprintf(out, " buff[pos] = LIST_TYPE;\n"); + fprintf(out, " buff[pos + 1] = %lu;\n", signature.size() + 2); + fprintf(out, " pos += LIST_TYPE_OVERHEAD;\n"); + + // Write timestamp. + fprintf(out, " long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n"); + fprintf(out, " buff[pos] = LONG_TYPE;\n"); + fprintf(out, " copyLong(buff, pos + 1, elapsedRealtime);\n"); + fprintf(out, " pos += LONG_TYPE_SIZE;\n"); + + // Write atom code. + fprintf(out, " buff[pos] = INT_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, code);\n"); + fprintf(out, " pos += INT_TYPE_SIZE;\n"); + + // Write the args. + argIndex = 1; + for (vector<java_type_t>::const_iterator arg = signature.begin(); + arg != signature.end(); arg++) { + switch (*arg) { + case JAVA_TYPE_BOOLEAN: + fprintf(out, " buff[pos] = INT_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, arg%d? 1 : 0);\n", argIndex); + fprintf(out, " pos += INT_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_INT: + case JAVA_TYPE_ENUM: + fprintf(out, " buff[pos] = INT_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, arg%d);\n", argIndex); + fprintf(out, " pos += INT_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_FLOAT: + *requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT; + fprintf(out, " buff[pos] = FLOAT_TYPE;\n"); + fprintf(out, " copyFloat(buff, pos + 1, arg%d);\n", argIndex); + fprintf(out, " pos += FLOAT_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_LONG: + fprintf(out, " buff[pos] = LONG_TYPE;\n"); + fprintf(out, " copyLong(buff, pos + 1, arg%d);\n", argIndex); + fprintf(out, " pos += LONG_TYPE_SIZE;\n"); + break; + case JAVA_TYPE_STRING: + fprintf(out, " buff[pos] = STRING_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, arg%dBytes.length);\n", argIndex); + fprintf(out, " System.arraycopy(" + "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%dBytes.length);\n", + argIndex, argIndex); + fprintf(out, " pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n", + argIndex); + break; + case JAVA_TYPE_BYTE_ARRAY: + fprintf(out, " buff[pos] = STRING_TYPE;\n"); + fprintf(out, " copyInt(buff, pos + 1, arg%d.length);\n", argIndex); + fprintf(out, " System.arraycopy(" + "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n", + argIndex, argIndex); + fprintf(out, " pos += STRING_TYPE_OVERHEAD + arg%d.length;\n", argIndex); + break; + case JAVA_TYPE_ATTRIBUTION_CHAIN: + { + *requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION; + const char* uidName = attributionDecl.fields.front().name.c_str(); + const char* tagName = attributionDecl.fields.back().name.c_str(); + + fprintf(out, " writeAttributionChain(buff, pos, %s, %s);\n", + uidName, tagName); + fprintf(out, " pos += attrSize;\n"); + break; + } + default: + // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR. + return 1; + } + argIndex++; + } + + fprintf(out, " StatsLog.writeRaw(buff, pos);\n"); + fprintf(out, " }\n"); + fprintf(out, "\n"); + } + return 0; +} + static void write_java_work_source_method(FILE* out, - const map<vector<java_type_t>, set<string>>& signatures_to_modules) { + const map<vector<java_type_t>, set<string>>& signatures_to_modules, + const string& moduleName) { fprintf(out, "\n // WorkSource methods.\n"); for (auto signature_to_modules_it = signatures_to_modules.begin(); signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) { + // Skip if this signature is not needed for the module. + if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) { + continue; + } vector<java_type_t> signature = signature_to_modules_it->first; // Determine if there is Attribution in this signature. int attributionArg = -1; @@ -834,7 +1178,9 @@ static void write_java_work_source_method(FILE* out, } // Method header (signature) - fprintf(out, " /** @hide */\n"); + if (moduleName == DEFAULT_MODULE_NAME) { + fprintf(out, " /** @hide */\n"); + } fprintf(out, " public static void write(int code"); int argIndex = 1; for (vector<java_type_t>::const_iterator arg = signature.begin(); @@ -859,7 +1205,7 @@ static void write_java_work_source_method(FILE* out, } } fprintf(out, ");\n"); - fprintf(out, " }\n"); // close flor-loop + fprintf(out, " }\n"); // close for-loop // write() component. fprintf(out, " ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n"); @@ -880,23 +1226,7 @@ static void write_java_work_source_method(FILE* out, } } -static int -write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) -{ - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - fprintf(out, "package android.util;\n"); - fprintf(out, "\n"); - fprintf(out, "import android.os.WorkSource;\n"); - fprintf(out, "import java.util.ArrayList;\n"); - fprintf(out, "\n"); - fprintf(out, "\n"); - fprintf(out, "/**\n"); - fprintf(out, " * API For logging statistics events.\n"); - fprintf(out, " * @hide\n"); - fprintf(out, " */\n"); - fprintf(out, "public class StatsLogInternal {\n"); +static void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) { fprintf(out, " // Constants for atom codes.\n"); std::map<int, set<AtomDecl>::const_iterator> atom_code_to_non_chained_decl_map; @@ -905,6 +1235,10 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD // Print constants for the atom codes. for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end(); atom++) { + // Skip if the atom is not needed for the module. + if (!atom_needed_for_module(*atom, moduleName)) { + continue; + } string constant = make_constant_name(atom->name); fprintf(out, "\n"); fprintf(out, " /**\n"); @@ -914,16 +1248,23 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { write_java_usage(out, "write_non_chained", constant, *non_chained_decl->second); } - fprintf(out, " * @hide\n"); + if (moduleName == DEFAULT_MODULE_NAME) { + fprintf(out, " * @hide\n"); + } fprintf(out, " */\n"); fprintf(out, " public static final int %s = %d;\n", constant.c_str(), atom->code); } fprintf(out, "\n"); +} - // Print constants for the enum values. +static void write_java_enum_values(FILE* out, const Atoms& atoms, const string& moduleName) { fprintf(out, " // Constants for enum values.\n\n"); for (set<AtomDecl>::const_iterator atom = atoms.decls.begin(); atom != atoms.decls.end(); atom++) { + // Skip if the atom is not needed for the module. + if (!atom_needed_for_module(*atom, moduleName)) { + continue; + } for (vector<AtomField>::const_iterator field = atom->fields.begin(); field != atom->fields.end(); field++) { if (field->javaType == JAVA_TYPE_ENUM) { @@ -931,7 +1272,9 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD field->name.c_str()); for (map<int, string>::const_iterator value = field->enumValues.begin(); value != field->enumValues.end(); value++) { - fprintf(out, " /** @hide */\n"); + if (moduleName == DEFAULT_MODULE_NAME) { + fprintf(out, " /** @hide */\n"); + } fprintf(out, " public static final int %s__%s__%s = %d;\n", make_constant_name(atom->message).c_str(), make_constant_name(field->name).c_str(), @@ -942,19 +1285,107 @@ write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionD } } } +} + +static int +write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) +{ + // Print prelude + fprintf(out, "// This file is autogenerated\n"); + fprintf(out, "\n"); + fprintf(out, "package android.util;\n"); + fprintf(out, "\n"); + fprintf(out, "import android.os.WorkSource;\n"); + fprintf(out, "import android.util.SparseArray;\n"); + fprintf(out, "import java.util.ArrayList;\n"); + fprintf(out, "\n"); + fprintf(out, "\n"); + fprintf(out, "/**\n"); + fprintf(out, " * API For logging statistics events.\n"); + fprintf(out, " * @hide\n"); + fprintf(out, " */\n"); + fprintf(out, "public class StatsLogInternal {\n"); + write_java_atom_codes(out, atoms, DEFAULT_MODULE_NAME); + + write_java_enum_values(out, atoms, DEFAULT_MODULE_NAME); // Print write methods fprintf(out, " // Write methods\n"); write_java_method(out, "write", atoms.signatures_to_modules, attributionDecl); write_java_method(out, "write_non_chained", atoms.non_chained_signatures_to_modules, attributionDecl); - write_java_work_source_method(out, atoms.signatures_to_modules); + write_java_work_source_method(out, atoms.signatures_to_modules, DEFAULT_MODULE_NAME); fprintf(out, "}\n"); return 0; } +// TODO: Merge this with write_stats_log_java so that we can get rid of StatsLogInternal JNI. +static int +write_stats_log_java_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl, + const string& moduleName, const string& javaClass, const string& javaPackage) +{ + // Print prelude + fprintf(out, "// This file is autogenerated\n"); + fprintf(out, "\n"); + fprintf(out, "package %s;\n", javaPackage.c_str()); + fprintf(out, "\n"); + fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n"); + fprintf(out, "\n"); + fprintf(out, "import android.util.StatsLog;\n"); + fprintf(out, "import android.os.SystemClock;\n"); + fprintf(out, "\n"); + fprintf(out, "import java.util.ArrayList;\n"); + fprintf(out, "\n"); + fprintf(out, "\n"); + fprintf(out, "/**\n"); + fprintf(out, " * Utility class for logging statistics events.\n"); + fprintf(out, " */\n"); + fprintf(out, "public class %s {\n", javaClass.c_str()); + + // TODO: ideally these match with the native values (and automatically change if they change). + fprintf(out, " private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n"); + fprintf(out, + " private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;\n"); + // Value types. Must match with EventLog.java and log.h. + fprintf(out, " private static final byte INT_TYPE = 0;\n"); + fprintf(out, " private static final byte LONG_TYPE = 1;\n"); + fprintf(out, " private static final byte STRING_TYPE = 2;\n"); + fprintf(out, " private static final byte LIST_TYPE = 3;\n"); + fprintf(out, " private static final byte FLOAT_TYPE = 4;\n"); + + // Size of each value type. + // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for the value. + fprintf(out, " private static final int INT_TYPE_SIZE = 5;\n"); + fprintf(out, " private static final int FLOAT_TYPE_SIZE = 5;\n"); + // Longs take 9 bytes, 1 for the type and 8 for the value. + fprintf(out, " private static final int LONG_TYPE_SIZE = 9;\n"); + // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the length. + fprintf(out, " private static final int STRING_TYPE_OVERHEAD = 5;\n"); + fprintf(out, " private static final int LIST_TYPE_OVERHEAD = 2;\n"); + + write_java_atom_codes(out, atoms, moduleName); + + write_java_enum_values(out, atoms, moduleName); + + int errors = 0; + int requiredHelpers = 0; + // Print write methods + fprintf(out, " // Write methods\n"); + errors += write_java_method_for_module(out, atoms.signatures_to_modules, attributionDecl, + moduleName, &requiredHelpers); + errors += write_java_non_chained_method_for_module(out, atoms.non_chained_signatures_to_modules, + moduleName); + + fprintf(out, " // Helper methods for copying primitives\n"); + write_java_helpers_for_module(out, attributionDecl, requiredHelpers); + + fprintf(out, "}\n"); + + return errors; +} + static const char* jni_type_name(java_type_t type) { @@ -1346,7 +1777,11 @@ print_usage() fprintf(stderr, " --namespace COMMA,SEP,NAMESPACE required for cpp/header with module\n"); fprintf(stderr, " comma separated namespace of the files\n"); fprintf(stderr, " --importHeader NAME required for cpp/jni to say which header to import\n"); -} + fprintf(stderr, " --javaPackage PACKAGE the package for the java file.\n"); + fprintf(stderr, " required for java with module\n"); + fprintf(stderr, " --javaClass CLASS the class name of the java class.\n"); + fprintf(stderr, " Optional for Java with module.\n"); + fprintf(stderr, " Default is \"StatsLogInternal\"\n");} /** * Do the argument parsing and execute the tasks. @@ -1362,6 +1797,8 @@ run(int argc, char const*const* argv) string moduleName = DEFAULT_MODULE_NAME; string cppNamespace = DEFAULT_CPP_NAMESPACE; string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT; + string javaPackage = DEFAULT_JAVA_PACKAGE; + string javaClass = DEFAULT_JAVA_CLASS; int index = 1; while (index < argc) { @@ -1417,6 +1854,20 @@ run(int argc, char const*const* argv) return 1; } cppHeaderImport = argv[index]; + } else if (0 == strcmp("--javaPackage", argv[index])) { + index++; + if (index >= argc) { + print_usage(); + return 1; + } + javaPackage = argv[index]; + } else if (0 == strcmp("--javaClass", argv[index])) { + index++; + if (index >= argc) { + print_usage(); + return 1; + } + javaClass = argv[index]; } index++; } @@ -1486,8 +1937,18 @@ run(int argc, char const*const* argv) fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str()); return 1; } - errorCount = android::stats_log_api_gen::write_stats_log_java( - out, atoms, attributionDecl); + // If this is for a specific module, the java package must also be provided. + if (moduleName != DEFAULT_MODULE_NAME && javaPackage== DEFAULT_JAVA_PACKAGE) { + fprintf(stderr, "Must supply --javaPackage if supplying a specific module\n"); + return 1; + } + if (moduleName == DEFAULT_MODULE_NAME) { + errorCount = android::stats_log_api_gen::write_stats_log_java( + out, atoms, attributionDecl); + } else { + errorCount = android::stats_log_api_gen::write_stats_log_java_for_module( + out, atoms, attributionDecl, moduleName, javaClass, javaPackage); + } fclose(out); } @@ -1503,7 +1964,7 @@ run(int argc, char const*const* argv) fclose(out); } - return 0; + return errorCount; } } 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' |