Merge "Added riddlehsu@, louischang@, and erosky@ to WM OWNERS file"
diff --git a/Android.bp b/Android.bp
index ec8636d..57f6513 100644
--- a/Android.bp
+++ b/Android.bp
@@ -687,6 +687,7 @@
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 c58f7af..9bda2dc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,27 +32,6 @@
# ============================================================
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 b7df380..2417d8e 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -8734,8 +8734,8 @@
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);
}
@@ -29116,7 +29116,6 @@
method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
- method @NonNull public java.util.List<java.lang.String> getSupportedOffHostSecureElements();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
method @Deprecated public boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
@@ -29209,10 +29208,10 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
method public boolean removeAidsForService(android.content.ComponentName, String);
- method public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
method public boolean supportsAidPrefixRegistration();
- method public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
+ method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
method public boolean unsetPreferredService(android.app.Activity);
field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final String CATEGORY_OTHER = "other";
diff --git a/api/system-current.txt b/api/system-current.txt
index 71dcdac..ce379f5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4609,17 +4609,6 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, @Nullable String, boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
- field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
- field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
- field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
- field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
- field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
- field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
- field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
- field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
- field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
- field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
- field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
field public static final String CARRIER_APP_NAMES = "carrier_app_names";
field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
@@ -7777,6 +7766,10 @@
method public int getUid();
}
+ public final class StatsLog {
+ method public static void writeRaw(@NonNull byte[], int);
+ }
+
}
package android.view {
diff --git a/api/test-current.txt b/api/test-current.txt
index dc5ff8f..21d761f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -923,6 +923,7 @@
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 @@
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 564e918..1ac6ea8 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -134,7 +134,7 @@
LowMemReported low_mem_reported = 81;
ThermalThrottlingStateChanged thermal_throttling = 86;
NetworkDnsEventReported network_dns_event_reported = 116;
- DataStallEvent data_stall_event = 121;
+ 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 +165,7 @@
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.
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
deleted file mode 100644
index 01c7587..0000000
--- 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/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
deleted file mode 100644
index 444ed92..0000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1,33 +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.
- */
-#pragma once
-
-#include <iostream>
-
-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);
-
-} // 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 a6f19f4..d9c82ea 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1003,9 +1003,8 @@
}
public void updateHttpProxy() {
- final ConnectivityManager cm = ConnectivityManager.from(
+ ActivityThread.updateHttpProxy(
getApplication() != null ? getApplication() : getSystemContext());
- Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
}
public void processInBackground() {
@@ -5594,7 +5593,7 @@
}
}
- GraphicsEnvironment.getInstance().setup(context);
+ GraphicsEnvironment.getInstance().setup(context, mCoreSettings);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -6690,6 +6689,11 @@
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 70fa5fa..f6b7eef 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -555,7 +555,7 @@
new CachedServiceFetcher<RcsManager>() {
@Override
public RcsManager createService(ContextImpl ctx) {
- return new RcsManager();
+ return new RcsManager(ctx.getOuterContext());
}
});
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 1c9a43a..9c21e8f 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,7 +1,9 @@
-artikz@google.com
+alsutton@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
+nathch@google.com
+rthakohov@google.com
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 1e12801..34c7372 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -56,7 +56,8 @@
* 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/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 4e88625..c06b837 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -35,21 +35,28 @@
* 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 c5d435b..66d1da8 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 @@
/**
* 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 @@
* @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 d710d57..ca43d40 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -80,7 +80,6 @@
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Base64;
-import android.util.ByteStringUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.PackageUtils;
@@ -99,6 +98,7 @@
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -5999,7 +5999,8 @@
}
// first see if the hash represents a single-signer in our signing history
- byte[] sha256Bytes = ByteStringUtils.fromHexToByteArray(sha256String);
+ byte[] sha256Bytes = sha256String == null
+ ? null : HexEncoding.decode(sha256String, false /* allowSingleChar */);
if (hasSha256Certificate(sha256Bytes, flags)) {
return true;
}
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index a33f3fc..65bc75b 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -64,6 +64,8 @@
@UnsupportedAppUsage
public int mtu;
+ public String serverHostName;
+
public DhcpResults() {
super();
}
@@ -97,6 +99,7 @@
vendorInfo = source.vendorInfo;
leaseDuration = source.leaseDuration;
mtu = source.mtu;
+ serverHostName = source.serverHostName;
}
}
@@ -129,6 +132,7 @@
vendorInfo = null;
leaseDuration = 0;
mtu = 0;
+ serverHostName = null;
}
@Override
@@ -139,6 +143,7 @@
str.append(" Vendor info ").append(vendorInfo);
str.append(" lease ").append(leaseDuration).append(" seconds");
if (mtu != 0) str.append(" MTU ").append(mtu);
+ str.append(" Servername ").append(serverHostName);
return str.toString();
}
@@ -154,6 +159,7 @@
return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
&& Objects.equals(serverAddress, target.serverAddress)
&& Objects.equals(vendorInfo, target.vendorInfo)
+ && Objects.equals(serverHostName, target.serverHostName)
&& leaseDuration == target.leaseDuration
&& mtu == target.mtu;
}
@@ -179,6 +185,7 @@
dest.writeInt(mtu);
InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
dest.writeString(vendorInfo);
+ dest.writeString(serverHostName);
}
@Override
@@ -193,6 +200,7 @@
dhcpResults.mtu = in.readInt();
dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
dhcpResults.vendorInfo = in.readString();
+ dhcpResults.serverHostName = in.readString();
return dhcpResults;
}
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index d6774d4..b5a2a16 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -72,4 +72,8 @@
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 bab6ae8..d586038 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 @@
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 d4c3edc..889e9bc 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -941,7 +941,8 @@
throw new IllegalArgumentException(sse);
} else if (sse.errorCode == OsConstants.EAGAIN) {
throw new IllegalStateException(sse);
- } else if (sse.errorCode == OsConstants.EOPNOTSUPP) {
+ } else if (sse.errorCode == OsConstants.EOPNOTSUPP
+ || sse.errorCode == OsConstants.EPROTONOSUPPORT) {
throw new UnsupportedOperationException(sse);
}
}
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
index e274005..4ac4a69 100644
--- a/core/java/android/net/TestNetworkManager.java
+++ b/core/java/android/net/TestNetworkManager.java
@@ -56,6 +56,26 @@
/**
* 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 @@
@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 5b67406..cf08b65 100644
--- a/core/java/android/net/UrlQuerySanitizer.java
+++ b/core/java/android/net/UrlQuerySanitizer.java
@@ -22,6 +22,8 @@
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 @@
* @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 @@
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 30d3b84..cd8ce8d 100644
--- a/core/java/android/net/metrics/ApfProgramEvent.java
+++ b/core/java/android/net/metrics/ApfProgramEvent.java
@@ -176,7 +176,7 @@
out.writeInt(filteredRas);
out.writeInt(currentRas);
out.writeInt(programLength);
- out.writeInt(flags);
+ out.writeInt(this.flags);
}
/** @hide */
@@ -192,6 +192,18 @@
programLength, actualLifetime, lifetimeString, namesOf(flags));
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfProgramEvent.class))) return false;
+ final ApfProgramEvent other = (ApfProgramEvent) obj;
+ return lifetime == other.lifetime
+ && actualLifetime == other.actualLifetime
+ && filteredRas == other.filteredRas
+ && currentRas == other.currentRas
+ && programLength == other.programLength
+ && flags == other.flags;
+ }
+
/** @hide */
public static final Parcelable.Creator<ApfProgramEvent> CREATOR
= new Parcelable.Creator<ApfProgramEvent>() {
diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java
index ddc788d..2e78469 100644
--- a/core/java/android/net/metrics/ApfStats.java
+++ b/core/java/android/net/metrics/ApfStats.java
@@ -275,6 +275,22 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ApfStats.class))) return false;
+ final ApfStats other = (ApfStats) obj;
+ return durationMs == other.durationMs
+ && receivedRas == other.receivedRas
+ && matchingRas == other.matchingRas
+ && droppedRas == other.droppedRas
+ && zeroLifetimeRas == other.zeroLifetimeRas
+ && parseErrors == other.parseErrors
+ && programUpdates == other.programUpdates
+ && programUpdatesAll == other.programUpdatesAll
+ && programUpdatesAllowingMulticast == other.programUpdatesAllowingMulticast
+ && maxProgramSize == other.maxProgramSize;
+ }
+
/** @hide */
public static final Parcelable.Creator<ApfStats> CREATOR = new Parcelable.Creator<ApfStats>() {
public ApfStats createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 93063cb..fa6bff3 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -22,6 +22,7 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
* An event recorded when a DhcpClient state machine transitions to a new state.
@@ -101,6 +102,14 @@
return String.format("DhcpClientEvent(%s, %dms)", msg, durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(DhcpClientEvent.class))) return false;
+ final DhcpClientEvent other = (DhcpClientEvent) obj;
+ return TextUtils.equals(msg, other.msg)
+ && durationMs == other.durationMs;
+ }
+
/** @hide */
public static final Parcelable.Creator<DhcpClientEvent> CREATOR
= new Parcelable.Creator<DhcpClientEvent>() {
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index 013e353..77908e6 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -101,6 +101,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpManagerEvent.class))) return false;
+ final IpManagerEvent other = (IpManagerEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{IpManagerEvent.class},
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index c736297..f9ee39b 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -93,6 +93,13 @@
return String.format("IpReachabilityEvent(%s:%02x)", eventName, lo);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(IpReachabilityEvent.class))) return false;
+ final IpReachabilityEvent other = (IpReachabilityEvent) obj;
+ return eventType == other.eventType;
+ }
+
final static class Decoder {
static final SparseArray<String> constants =
MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class},
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 5128115..ec0f82a 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -121,6 +121,14 @@
Decoder.constants.get(eventType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(NetworkEvent.class))) return false;
+ final NetworkEvent other = (NetworkEvent) obj;
+ return eventType == other.eventType
+ && durationMs == other.durationMs;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"});
diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java
index d16a104..6ccca7d 100644
--- a/core/java/android/net/metrics/RaEvent.java
+++ b/core/java/android/net/metrics/RaEvent.java
@@ -97,6 +97,18 @@
.toString();
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(RaEvent.class))) return false;
+ final RaEvent other = (RaEvent) obj;
+ return routerLifetime == other.routerLifetime
+ && prefixValidLifetime == other.prefixValidLifetime
+ && prefixPreferredLifetime == other.prefixPreferredLifetime
+ && routeInfoLifetime == other.routeInfoLifetime
+ && rdnssLifetime == other.rdnssLifetime
+ && dnsslLifetime == other.dnsslLifetime;
+ }
+
/** @hide */
public static final Parcelable.Creator<RaEvent> CREATOR = new Parcelable.Creator<RaEvent>() {
public RaEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index ebca7e6..6784420 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -170,6 +170,15 @@
getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj.getClass().equals(ValidationProbeEvent.class))) return false;
+ final ValidationProbeEvent other = (ValidationProbeEvent) obj;
+ return durationMs == other.durationMs
+ && probeType == other.probeType
+ && returnCode == other.returnCode;
+ }
+
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{ValidationProbeEvent.class},
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b90a60e..eb347e7 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -526,6 +526,7 @@
* @return List<String> containing secure elements on the device which supports
* off host card emulation. eSE for Embedded secure element,
* SIM for UICC and so on.
+ * @hide
*/
public @NonNull List<String> getSupportedOffHostSecureElements() {
List<String> offHostSE = new ArrayList<String>();
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 911ec84..ab0a0ef 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -432,7 +432,15 @@
mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
}
- @UnsupportedAppUsage
+ /**
+ * Sets the off host Secure Element.
+ * @param offHost Secure Element to set. Only accept strings with prefix SIM or prefix eSE.
+ * Ref: GSMA TS.26 - NFC Handset Requirements
+ * TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be SIM[smartcard slot]
+ * (e.g. SIM/SIM1, SIM2… SIMn).
+ * TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be eSE[number]
+ * (e.g. eSE/eSE1, eSE2, etc.).
+ */
public void setOffHostSecureElement(String offHost) {
mOffHostName = offHost;
}
@@ -441,7 +449,6 @@
* Resets the off host Secure Element to statically defined
* by the service in the manifest file.
*/
- @UnsupportedAppUsage
public void unsetOffHostSecureElement() {
mOffHostName = mStaticOffHostName;
}
@@ -581,10 +588,9 @@
pw.println(" On Host Service");
} else {
pw.println(" Off-host Service");
- pw.println(" " + "Current off-host SE" + mOffHostName
- + " static off-host: " + mOffHostName);
+ pw.println(" " + "Current off-host SE:" + mOffHostName
+ + " static off-host SE:" + mStaticOffHostName);
}
- pw.println(" Static off-host Secure Element:");
pw.println(" Static AID groups:");
for (AidGroup group : mStaticAidGroups.values()) {
pw.println(" Category: " + group.category);
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index f23dc2d..4c9885c 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -17,6 +17,7 @@
package android.nfc.cardemulation;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Activity;
@@ -360,6 +361,8 @@
* @param service The component name of the service
* @return whether the registration was successful.
*/
+ @RequiresPermission(android.Manifest.permission.NFC)
+ @NonNull
public boolean unsetOffHostForService(@NonNull ComponentName service) {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
if (adapter == null) {
@@ -391,7 +394,9 @@
* through the manifest, or dynamically by using this API),
* it will be replaced with this one. All AIDs registered by
* this service will be re-routed to this Secure Element if
- * successful.
+ * successful. AIDs that was statically assigned using manifest
+ * will re-route to off-host SE that stated in manifest after NFC
+ * toggle.
*
* <p>Note that you can only set off-host SE for a service that
* is running under the same UID as the caller of this API. Typically
@@ -403,9 +408,19 @@
* exists on the device.
*
* @param service The component name of the service
- * @param offHostSecureElement Secure Element to register the AID to
+ * @param offHostSecureElement Secure Element to register the AID to. Only accept strings with
+ * prefix SIM or prefix eSE.
+ * Ref: GSMA TS.26 - NFC Handset Requirements
+ * TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be
+ * SIM[smartcard slot]
+ * (e.g. SIM/SIM1, SIM2… SIMn).
+ * TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be
+ * eSE[number]
+ * (e.g. eSE/eSE1, eSE2, etc.).
* @return whether the registration was successful.
*/
+ @RequiresPermission(android.Manifest.permission.NFC)
+ @NonNull
public boolean setOffHostForService(@NonNull ComponentName service,
@NonNull String offHostSecureElement) {
boolean validSecureElement = false;
@@ -421,6 +436,10 @@
return false;
}
+ if (!offHostSecureElement.startsWith("eSE") && !offHostSecureElement.startsWith("SIM")) {
+ return false;
+ }
+
if (offHostSecureElement.equals("eSE")) {
offHostSecureElement = "eSE1";
} else if (offHostSecureElement.equals("SIM")) {
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index e366fe0..32735aa 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -32,7 +32,7 @@
import libcore.io.IoUtils;
import java.io.File;
-import java.io.IOException;
+import java.io.FileNotFoundException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
@@ -146,7 +146,6 @@
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@NonNull BugreportCallback callback) {
- File tmpScreenshotFile = null;
try {
Preconditions.checkNotNull(bugreportFd);
Preconditions.checkNotNull(params);
@@ -155,13 +154,10 @@
if (screenshotFd == null) {
// Binder needs a valid File Descriptor to be passed
- tmpScreenshotFile = File.createTempFile("tmp", ".png");
- screenshotFd = ParcelFileDescriptor.open(tmpScreenshotFile,
+ screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
ParcelFileDescriptor.MODE_READ_ONLY);
}
- DumpstateListener dsListener = new DumpstateListener(executor,
- callback, tmpScreenshotFile);
-
+ DumpstateListener dsListener = new DumpstateListener(executor, callback);
// Note: mBinder can get callingUid from the binder transaction.
mBinder.startBugreport(-1 /* callingUid */,
mContext.getOpPackageName(),
@@ -169,13 +165,9 @@
screenshotFd.getFileDescriptor(),
params.getMode(), dsListener);
} catch (RemoteException e) {
- deleteFile(tmpScreenshotFile);
throw e.rethrowFromSystemServer();
- } catch (IOException e) {
- // Need to delete the file if it was created but failed while trying to get fd
- deleteFile(tmpScreenshotFile);
- Log.e(TAG, "Not able to create/open temporary screenshot file ", e);
- callback.onError(BugreportCallback.BUGREPORT_ERROR_RUNTIME);
+ } catch (FileNotFoundException e) {
+ Log.wtf(TAG, "Not able to find /dev/null file: ", e);
} finally {
// We can close the file descriptors here because binder would have duped them.
IoUtils.closeQuietly(bugreportFd);
@@ -197,26 +189,13 @@
}
}
- private void deleteFile(@Nullable File tmpScreenshotFile) {
- try {
- if (tmpScreenshotFile != null && tmpScreenshotFile.exists()) {
- tmpScreenshotFile.delete();
- }
- } catch (SecurityException e) {
- Log.e(TAG, "Not able to delete temporary screenshot file ", e);
- }
- }
-
private final class DumpstateListener extends IDumpstateListener.Stub {
private final Executor mExecutor;
private final BugreportCallback mCallback;
- private final File mTmpScreenshotFile;
- DumpstateListener(Executor executor, BugreportCallback callback,
- @Nullable File tmpScreenshotFile) {
+ DumpstateListener(Executor executor, BugreportCallback callback) {
mExecutor = executor;
mCallback = callback;
- mTmpScreenshotFile = tmpScreenshotFile;
}
@Override
@@ -240,7 +219,6 @@
});
} finally {
Binder.restoreCallingIdentity(identity);
- deleteFile(mTmpScreenshotFile);
}
}
@@ -253,7 +231,6 @@
});
} finally {
Binder.restoreCallingIdentity(identity);
- deleteFile(mTmpScreenshotFile);
}
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1c319fb..d3bed02 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -287,6 +287,7 @@
/**
* @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 f2e0bdd..1aaee18 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
import android.opengl.EGL14;
import android.os.Build;
import android.os.SystemProperties;
@@ -28,6 +29,10 @@
import dalvik.system.VMRuntime;
import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/** @hide */
public class GraphicsEnvironment {
@@ -44,6 +49,7 @@
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 GAME_DRIVER_WHITELIST_ALL = "*";
private ClassLoader mClassLoader;
private String mLayerPath;
@@ -52,9 +58,9 @@
/**
* Set up GraphicsEnvironment
*/
- public void setup(Context context) {
+ public void setup(Context context, Bundle coreSettings) {
setupGpuLayers(context);
- chooseDriver(context);
+ chooseDriver(context, coreSettings);
}
/**
@@ -92,15 +98,15 @@
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())
@@ -130,23 +136,29 @@
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) {
- String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
+ private static void chooseDriver(Context context, Bundle coreSettings) {
+ 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;
- }
- ApplicationInfo driverInfo;
+
+ final ApplicationInfo driverInfo;
try {
driverInfo = context.getPackageManager().getApplicationInfo(driverPackageName,
PackageManager.MATCH_SYSTEM_ONLY);
@@ -154,7 +166,69 @@
Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
return;
}
- String abi = chooseAbi(driverInfo);
+
+ // 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) {
+ Log.w(TAG, "updated driver package is not known to be compatible with O");
+ }
+ 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.
+ 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
@@ -164,23 +238,24 @@
}
return;
}
- if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
- // 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.
- Log.w(TAG, "updated driver package is not known to be compatible with O");
- 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);
}
/**
@@ -194,7 +269,7 @@
* 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);
},
@@ -203,7 +278,7 @@
}
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;
@@ -217,5 +292,5 @@
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 03e8c15..7f60b9c 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -363,18 +363,6 @@
boolean isNetworkActive();
/**
- * Setup a new physical network.
- * @param permission PERMISSION_NONE if no permissions required to access this network.
- * PERMISSION_NETWORK or PERMISSION_SYSTEM to set respective permission.
- */
- void createPhysicalNetwork(int netId, int permission);
-
- /**
- * Setup a new VPN.
- */
- void createVirtualNetwork(int netId, boolean secure);
-
- /**
* Add an interface to a network.
*/
void addInterfaceToNetwork(String iface, int netId);
@@ -396,9 +384,6 @@
*/
void setNetworkPermission(int netId, int permission);
- void setPermission(String permission, in int[] uids);
- void clearPermission(in int[] uids);
-
/**
* Allow UID to call protect().
*/
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index ef28f07..0827fd6 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -967,6 +967,23 @@
// 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 34e9eb3..e94d3a7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10336,8 +10336,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
/**
@@ -10346,8 +10344,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
/**
@@ -10356,8 +10352,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
/**
@@ -10367,8 +10361,6 @@
* The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
/**
@@ -10397,8 +10389,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
/**
@@ -10407,8 +10397,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
/**
@@ -10417,8 +10405,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
/**
@@ -10427,8 +10413,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
"captive_portal_other_fallback_urls";
@@ -10438,8 +10422,6 @@
* by "@@,@@".
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
"captive_portal_fallback_probe_specs";
@@ -10450,8 +10432,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
/**
@@ -10460,8 +10440,6 @@
*
* @hide
*/
- @SystemApi
- @TestApi
public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
/**
@@ -11446,6 +11424,57 @@
public static final String GPU_DEBUG_APP = "gpu_debug_app";
/**
+ * 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 GAME_DRIVER_WHITELIST = "game_driver_whitelist";
+
+ /**
+ * 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 GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries";
+
+ /**
* Ordered GPU debug layer list
* i.e. <layer1>:<layer2>:...:<layerN>
* @hide
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index e3de307..020205f 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -16,6 +16,8 @@
package android.util;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.IStatsManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -113,4 +115,14 @@
sService = IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
return sService;
}
+
+ /**
+ * Write an event to stats log using the raw format.
+ *
+ * @param buffer The encoded buffer of data to write..
+ * @param size The number of bytes from the buffer to write.
+ * @hide
+ */
+ @SystemApi
+ public static native void writeRaw(@NonNull byte[] buffer, int size);
}
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index 3861695..fc23c54 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -19,7 +19,7 @@
import android.annotation.Nullable;
import android.text.TextUtils;
-import libcore.net.MimeUtils;
+import libcore.net.MimeMap;
import java.util.regex.Pattern;
@@ -79,7 +79,7 @@
* @return {@code true} if there is a mimeType entry in the map.
*/
public boolean hasMimeType(String mimeType) {
- return MimeUtils.hasMimeType(mimeType);
+ return MimeMap.getDefault().hasMimeType(mimeType);
}
/**
@@ -89,12 +89,12 @@
*/
@Nullable
public String getMimeTypeFromExtension(String extension) {
- return MimeUtils.guessMimeTypeFromExtension(extension);
+ return MimeMap.getDefault().guessMimeTypeFromExtension(extension);
}
// Static method called by jni.
private static String mimeTypeFromExtension(String extension) {
- return MimeUtils.guessMimeTypeFromExtension(extension);
+ return MimeMap.getDefault().guessMimeTypeFromExtension(extension);
}
/**
@@ -103,7 +103,7 @@
* @return {@code true} if there is an extension entry in the map.
*/
public boolean hasExtension(String extension) {
- return MimeUtils.hasExtension(extension);
+ return MimeMap.getDefault().hasExtension(extension);
}
/**
@@ -115,7 +115,7 @@
*/
@Nullable
public String getExtensionFromMimeType(String mimeType) {
- return MimeUtils.guessExtensionFromMimeType(mimeType);
+ return MimeMap.getDefault().guessExtensionFromMimeType(mimeType);
}
/**
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 46edf47..53e145e 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -597,7 +597,7 @@
case Calendar.NOVEMBER:
return 30;
case Calendar.FEBRUARY:
- return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 29 : 28;
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 29 : 28;
default:
throw new IllegalArgumentException("Invalid Month");
}
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 9982732..80de6fc 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -850,7 +850,7 @@
case Calendar.NOVEMBER:
return 30;
case Calendar.FEBRUARY:
- return (year % 4 == 0) ? 29 : 28;
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 29 : 28;
default:
throw new IllegalArgumentException("Invalid Month");
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index e508b02a..6fcb78b 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -1,10 +1,10 @@
genrule {
- name: "android_util_StatsLog.cpp",
+ name: "android_util_StatsLogInternal.cpp",
tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --jni $(genDir)/android_util_StatsLog.cpp",
+ cmd: "$(location stats-log-api-gen) --jni $(genDir)/android_util_StatsLogInternal.cpp",
out: [
- "android_util_StatsLog.cpp",
+ "android_util_StatsLogInternal.cpp",
],
}
@@ -112,6 +112,7 @@
"android_util_Binder.cpp",
"android_util_EventLog.cpp",
"android_util_Log.cpp",
+ "android_util_StatsLog.cpp",
"android_util_MemoryIntArray.cpp",
"android_util_PathParser.cpp",
"android_util_Process.cpp",
@@ -292,7 +293,7 @@
"server_configurable_flags",
],
- generated_sources: ["android_util_StatsLog.cpp"],
+ generated_sources: ["android_util_StatsLogInternal.cpp"],
local_include_dirs: ["android/graphics"],
export_include_dirs: [
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a4be784..1854ea9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -120,6 +120,7 @@
extern int register_android_content_AssetManager(JNIEnv* env);
extern int register_android_util_EventLog(JNIEnv* env);
extern int register_android_util_StatsLog(JNIEnv* env);
+extern int register_android_util_StatsLogInternal(JNIEnv* env);
extern int register_android_util_Log(JNIEnv* env);
extern int register_android_util_MemoryIntArray(JNIEnv* env);
extern int register_android_util_PathParser(JNIEnv* env);
@@ -1396,6 +1397,7 @@
REG_JNI(register_android_util_MemoryIntArray),
REG_JNI(register_android_util_PathParser),
REG_JNI(register_android_util_StatsLog),
+ REG_JNI(register_android_util_StatsLogInternal),
REG_JNI(register_android_app_admin_SecurityLog),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index e22f581..076e99d 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 @@
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 @@
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 28c59db..c5fc9b3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -49,8 +49,8 @@
namespace android {
constexpr int MAXPACKETSIZE = 8 * 1024;
-// FrameworkListener limits the size of commands to 1024 bytes. TODO: fix this.
-constexpr int MAXCMDSIZE = 1024;
+// FrameworkListener limits the size of commands to 4096 bytes.
+constexpr int MAXCMDSIZE = 4096;
static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 8be617f..62c4d76 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 @@
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 @@
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 dfa5de6..b95d500 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 @@
}
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 9c60e6b..129b8af 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -188,7 +188,7 @@
if (env->IsInstanceOf(excep, gErrorClass)) {
/* It's an error */
LOG(ERROR) << "Forcefully exiting";
- exit(1);
+ _exit(1);
} else {
LOG(ERROR) << "Uncaught exception!";
}
diff --git a/core/jni/android_util_StatsLog.cpp b/core/jni/android_util_StatsLog.cpp
new file mode 100644
index 0000000..e749d34
--- /dev/null
+++ b/core/jni/android_util_StatsLog.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#define LOG_NAMESPACE "StatsLog.tag."
+#define LOG_TAG "StatsLog_println"
+
+#include <assert.h>
+#include <cutils/properties.h>
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include "utils/misc.h"
+#include "core_jni_helpers.h"
+#include "stats_event_list.h"
+
+namespace android {
+
+static void android_util_StatsLog_writeRaw(JNIEnv* env, jobject clazz, jbyteArray buf, jint size)
+{
+ if (buf == NULL) {
+ return;
+ }
+ jint actualSize = env->GetArrayLength(buf);
+ if (actualSize < size) {
+ return;
+ }
+
+ jbyte* bufferArray = env->GetByteArrayElements(buf, NULL);
+ if (bufferArray == NULL) {
+ return;
+ }
+ const uint32_t statsEventTag = 1937006964;
+ struct iovec vec[2];
+ vec[0].iov_base = (void*) &statsEventTag;
+ vec[0].iov_len = sizeof(statsEventTag);
+ vec[1].iov_base = (void*) bufferArray;
+ vec[1].iov_len = size;
+ write_to_statsd(vec, 2);
+
+ env->ReleaseByteArrayElements(buf, bufferArray, 0);
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "writeRaw", "([BI)V", (void*) android_util_StatsLog_writeRaw },
+};
+
+int register_android_util_StatsLog(JNIEnv* env)
+{
+ return RegisterMethodsOrDie(env, "android/util/StatsLog", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0e5f53b..04d2706 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -72,6 +72,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <bionic_malloc.h>
#include <cutils/ashmem.h>
#include <cutils/fs.h>
#include <cutils/multiuser.h>
@@ -476,12 +477,9 @@
}
}
-// The debug malloc library needs to know whether it's the zygote or a child.
-extern "C" int gMallocLeakZygoteChild;
-
static void PreApplicationInit() {
// The child process sets this to indicate it's not the zygote.
- gMallocLeakZygoteChild = 1;
+ android_mallopt(M_SET_ZYGOTE_CHILD, nullptr, 0);
// Set the jemalloc decay time to 1.
mallopt(M_DECAY_TIME, 1);
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index 8bf3772..973fa5a 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -460,7 +460,9 @@
optional int32 vts_coverage = 43;
optional string zygote = 44;
- // Next Tag: 45
+ optional string gfx_driver_whitelist_0 = 45;
+
+ // Next Tag: 46
}
optional Ro ro = 21;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 99f3034..a44ec9a 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -384,6 +384,26 @@
// App allowed to load GPU debug layers.
optional SettingProto debug_app = 1;
optional SettingProto debug_layers = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // 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/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3fe8689..e074db6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3691,7 +3691,7 @@
the settings for this service. -->
<attr name="settingsActivity"/>
<!-- Secure Element which the AIDs should be routed to -->
- <attr name="secureElementName"/>
+ <attr name="secureElementName" format="string"/>
</declare-styleable>
<!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8e383a5..76356ed 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -444,6 +444,13 @@
Settings.Global.ENABLE_GPU_DEBUG_LAYERS,
Settings.Global.GPU_DEBUG_APP,
Settings.Global.GPU_DEBUG_LAYERS,
+ 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 28099a1..c17f076 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,12 +33,18 @@
<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 @@
<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 0000000..1d06348
--- /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/graphics/proto/game_driver.proto b/graphics/proto/game_driver.proto
new file mode 100644
index 0000000..fd7ffcc
--- /dev/null
+++ b/graphics/proto/game_driver.proto
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+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;
+}
+
+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 0000000..4e40637
--- /dev/null
+++ b/graphics/proto/jarjar-rules.txt
@@ -0,0 +1 @@
+rule com.google.protobuf.** com.android.framework.protobuf.@1
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
index 4af6274..63a670c 100644
--- a/libs/usb/tests/AccessoryChat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -1 +1,25 @@
subdirs = ["accessorychat"]
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AccessoryChat",
+
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+
+}
diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk
deleted file mode 100644
index cfe2da1..0000000
--- a/libs/usb/tests/AccessoryChat/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessoryChat
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/nfc-extras/tests/Android.bp b/nfc-extras/tests/Android.bp
new file mode 100644
index 0000000..fc52006
--- /dev/null
+++ b/nfc-extras/tests/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2011, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "NfcExtrasTests",
+
+ // We only want this apk build for tests.
+
+ libs: [
+ "android.test.runner.stubs",
+ "com.android.nfc_extras.stubs",
+ "android.test.base.stubs",
+ ],
+
+ static_libs: ["junit"],
+
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+
+ sdk_version: "current",
+
+}
diff --git a/nfc-extras/tests/Android.mk b/nfc-extras/tests/Android.mk
deleted file mode 100644
index 8bba3ba..0000000
--- a/nfc-extras/tests/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2011, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner.stubs \
- com.android.nfc_extras.stubs \
- android.test.base.stubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NfcExtrasTests
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 44e0a65..ffd4d9d 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 5817118..62de2ba 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -37,6 +37,7 @@
"src/**/*.java",
":framework-networkstack-shared-srcs",
":services-networkstack-shared-srcs",
+ ":statslog-networkstack-java-gen",
],
static_libs: [
"androidx.annotation_annotation",
@@ -55,15 +56,24 @@
srcs: [
"jni/network_stack_utils_jni.cpp"
],
-
+ sdk_version: "current",
shared_libs: [
"liblog",
- "libcutils",
- "libnativehelper",
+ "libnativehelper_compat_libc++",
],
- static_libs: [
- "libpcap",
- ],
+
+ // We cannot use plain "libc++" here to link libc++ dynamically because it results in:
+ // java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found
+ // even if "libc++" is added into jni_libs below. Adding "libc++_shared" into jni_libs doesn't
+ // build because soong complains of:
+ // module NetworkStack missing dependencies: libc++_shared
+ //
+ // So, link libc++ statically. This means that we also need to ensure that all the C++ libraries
+ // we depend on do not dynamically link libc++. This is currently the case, because liblog is
+ // C-only and libnativehelper_compat_libc also uses stl: "c++_static".
+ //
+ // TODO: find a better solution for this in R.
+ stl: "c++_static",
cflags: [
"-Wall",
"-Werror",
@@ -78,7 +88,10 @@
static_libs: [
"NetworkStackBase",
],
- jni_libs: ["libnetworkstackutilsjni"],
+ jni_libs: [
+ "libnativehelper_compat_libc++",
+ "libnetworkstackutilsjni",
+ ],
// Resources already included in NetworkStackBase
resource_dirs: [],
jarjar_rules: "jarjar-rules-shared.txt",
@@ -104,3 +117,11 @@
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 5544eaa..f2ba575 100644
--- a/packages/NetworkStack/jni/network_stack_utils_jni.cpp
+++ b/packages/NetworkStack/jni/network_stack_utils_jni.cpp
@@ -31,7 +31,7 @@
#include <string>
#include <nativehelper/JNIHelp.h>
-#include <utils/Log.h>
+#include <android/log.h>
namespace android {
constexpr const char NETWORKSTACKUTILS_PKG_NAME[] = "android/net/util/NetworkStackUtils";
@@ -249,7 +249,7 @@
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
JNIEnv *env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed");
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
return JNI_ERR;
}
@@ -261,4 +261,4 @@
return JNI_VERSION_1_6;
}
-}; // namespace android
\ No newline at end of file
+}; // namespace android
diff --git a/packages/NetworkStack/res/values/config.xml b/packages/NetworkStack/res/values/config.xml
index 704788d..478ed6b 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 663e2f1..359c859 100644
--- a/packages/NetworkStack/src/android/net/apf/ApfFilter.java
+++ b/packages/NetworkStack/src/android/net/apf/ApfFilter.java
@@ -39,6 +39,7 @@
import android.content.IntentFilter;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;
@@ -1691,13 +1692,13 @@
}
/**
- * Add keepalive ack packet filter.
+ * Add TCP keepalive ack packet filter.
* This will add a filter to drop acks to the keepalive packet passed as an argument.
*
* @param slot The index used to access the filter.
* @param sentKeepalivePacket The attributes of the sent keepalive packet.
*/
- public synchronized void addKeepalivePacketFilter(final int slot,
+ public synchronized void addTcpKeepalivePacketFilter(final int slot,
final TcpKeepalivePacketDataParcelable sentKeepalivePacket) {
log("Adding keepalive ack(" + slot + ")");
if (null != mKeepaliveAcks.get(slot)) {
@@ -1711,6 +1712,18 @@
}
/**
+ * Add NATT keepalive packet filter.
+ * This will add a filter to drop NATT keepalive packet which is passed as an argument.
+ *
+ * @param slot The index used to access the filter.
+ * @param sentKeepalivePacket The attributes of the sent keepalive packet.
+ */
+ public synchronized void addNattKeepalivePacketFilter(final int slot,
+ final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
+ Log.e(TAG, "APF add NATT keepalive filter is not implemented");
+ }
+
+ /**
* Remove keepalive packet filter.
*
* @param slot The index used to access the filter.
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
index d7ff98b1..a15d423 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacket.java
@@ -195,6 +195,18 @@
public static final String VENDOR_INFO_ANDROID_METERED = "ANDROID_METERED";
/**
+ * DHCP Optional Type: Option overload option
+ */
+ protected static final byte DHCP_OPTION_OVERLOAD = 52;
+
+ /**
+ * Possible values of the option overload option.
+ */
+ private static final byte OPTION_OVERLOAD_FILE = 1;
+ private static final byte OPTION_OVERLOAD_SNAME = 2;
+ private static final byte OPTION_OVERLOAD_BOTH = 3;
+
+ /**
* DHCP Optional Type: DHCP Requested IP Address
*/
protected static final byte DHCP_REQUESTED_IP = 50;
@@ -309,6 +321,11 @@
protected final byte[] mClientMac;
/**
+ * The server host name from server.
+ */
+ protected String mServerHostName;
+
+ /**
* Asks the packet object to create a ByteBuffer serialization of
* the packet for transmission.
*/
@@ -848,6 +865,8 @@
Inet4Address ipDst = null;
Inet4Address bcAddr = null;
Inet4Address requestedIp = null;
+ String serverHostName;
+ byte optionOverload = 0;
// The following are all unsigned integers. Internally we store them as signed integers of
// the same length because that way we're guaranteed that they can't be out of the range of
@@ -989,9 +1008,9 @@
packet.get(clientMac);
// skip over address padding (16 octets allocated)
- packet.position(packet.position() + (16 - addrLen)
- + 64 // skip server host name (64 chars)
- + 128); // skip boot file name (128 chars)
+ packet.position(packet.position() + (16 - addrLen));
+ serverHostName = readAsciiString(packet, 64, false);
+ packet.position(packet.position() + 128);
// Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
if (packet.remaining() < 4) {
@@ -1102,6 +1121,11 @@
// Embedded nulls are safe as this does not get passed to netd.
vendorInfo = readAsciiString(packet, optionLen, true);
break;
+ case DHCP_OPTION_OVERLOAD:
+ expectedLen = 1;
+ optionOverload = packet.get();
+ optionOverload &= OPTION_OVERLOAD_BOTH;
+ break;
default:
// ignore any other parameters
for (int i = 0; i < optionLen; i++) {
@@ -1192,6 +1216,11 @@
newPacket.mT2 = T2;
newPacket.mVendorId = vendorId;
newPacket.mVendorInfo = vendorInfo;
+ if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) {
+ newPacket.mServerHostName = serverHostName;
+ } else {
+ newPacket.mServerHostName = "";
+ }
return newPacket;
}
@@ -1251,6 +1280,7 @@
results.vendorInfo = mVendorInfo;
results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE;
results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0;
+ results.serverHostName = mServerHostName;
return results;
}
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index d21b5f7..b8ab94c 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -647,4 +647,9 @@
}
}
}
+
+ @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 80d139c..dc74c04 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -29,6 +29,7 @@
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.NetworkStackIpMemoryStore;
import android.net.ProvisioningConfigurationParcelable;
import android.net.ProxyInfo;
@@ -371,6 +372,10 @@
private boolean mMulticastFiltering;
private long mStartTimeMillis;
+ /* This must match the definition in KeepaliveTracker.KeepaliveInfo */
+ private static final int TYPE_NATT = 1;
+ private static final int TYPE_TCP = 2;
+
/**
* Reading the snapshot is an asynchronous operation initiated by invoking
* Callback.startReadPacketFilter() and completed when the WiFi Service responds with an
@@ -553,10 +558,20 @@
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 @@
}
/**
- * 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 @@
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 547f04d..abfed3e 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -34,6 +34,77 @@
// TODO: Refer to DeviceConfig definition.
public static final String NAMESPACE_CONNECTIVITY = "connectivity";
+ /**
+ * A list of captive portal detection specifications used in addition to the fallback URLs.
+ * Each spec has the format url@@/@@statusCodeRegex@@/@@contentRegex. Specs are separated
+ * by "@@,@@".
+ */
+ public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
+ "captive_portal_fallback_probe_specs";
+
+ /**
+ * A comma separated list of URLs used for captive portal detection in addition to the
+ * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings.
+ */
+ public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
+ "captive_portal_other_fallback_urls";
+
+ /**
+ * Which User-Agent string to use in the header of the captive portal detection probes.
+ * The User-Agent field is unset when this setting has no value (HttpUrlConnection default).
+ */
+ public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
+
+ /**
+ * Whether to use HTTPS for network validation. This is enabled by default and the setting
+ * needs to be set to 0 to disable it. This setting is a misnomer because captive portals
+ * don't actually use HTTPS, but it's consistent with the other settings.
+ */
+ 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
similarity index 99%
rename from packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java
rename to packages/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java
index 225dc0f..2523ecd 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
similarity index 87%
rename from packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
rename to packages/NetworkStack/src/com/android/networkstack/metrics/DataStallStatsUtils.java
index c96411e..9308901 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 @@
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 @@
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 a0a90fd..a6d7484 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -251,6 +251,11 @@
}
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
@@ -325,5 +330,10 @@
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 884fc21..bacec78 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -43,6 +43,16 @@
import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_MIN_EVALUATE_TIME_MS;
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;
import static android.net.util.NetworkStackUtils.NAMESPACE_CONNECTIVITY;
import static android.net.util.NetworkStackUtils.isEmpty;
@@ -55,6 +65,7 @@
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;
@@ -65,8 +76,6 @@
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;
@@ -102,6 +111,8 @@
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;
@@ -118,6 +129,7 @@
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;
/**
@@ -132,8 +144,13 @@
+ "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);
@@ -1164,20 +1181,47 @@
}
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() {
- return mDependencies.getSetting(mContext, Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
+ return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+ CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
}
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));
+ }
}
/**
@@ -1189,8 +1233,7 @@
*/
public String getCaptivePortalServerHttpUrl() {
return getSettingFromResource(mContext, R.string.config_captive_portal_http_url,
- R.string.default_captive_portal_http_url,
- Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+ R.string.default_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL);
}
private int getConsecutiveDnsTimeoutThreshold() {
@@ -1219,13 +1262,13 @@
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)) {
- final String otherUrls = mDependencies.getSetting(mContext,
- Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, "");
+ final String otherUrls = mDependencies.getDeviceConfigProperty(
+ NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, "");
// otherUrls may be empty, but .split() ignores trailing empty strings
final String separator = ",";
final String[] urls = (firstUrl + separator + otherUrls).split(separator);
@@ -1245,8 +1288,9 @@
private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs() {
try {
- final String settingsValue = mDependencies.getSetting(
- mContext, Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
+ final String settingsValue = mDependencies.getDeviceConfigProperty(
+ NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
+
final CaptivePortalProbeSpec[] emptySpecs = new CaptivePortalProbeSpec[0];
final CaptivePortalProbeSpec[] providerValue = TextUtils.isEmpty(settingsValue)
? emptySpecs
@@ -1340,8 +1384,8 @@
}
private String getCaptivePortalUserAgent() {
- return mDependencies.getSetting(mContext,
- Settings.Global.CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT);
+ return mDependencies.getDeviceConfigProperty(NAMESPACE_CONNECTIVITY,
+ CAPTIVE_PORTAL_USER_AGENT, DEFAULT_USER_AGENT);
}
private URL nextFallbackUrl() {
@@ -1440,6 +1484,45 @@
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)) {
@@ -1451,7 +1534,7 @@
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());
@@ -1776,6 +1859,10 @@
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 5650f21..6a6bf83 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.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 @@
*/
@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 @@
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 @@
*/
@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 @@
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 2775fde..bea7052 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 @@
}
@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 fe3c1e8..039f6bf 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -56,6 +56,7 @@
"liblog",
"liblzma",
"libnativehelper",
+ "libnativehelper_compat_libc++",
"libnetworkstacktestsjni",
"libnetworkstackutilsjni",
"libpackagelistparser",
@@ -99,5 +100,4 @@
"libapf",
"libpcap",
],
-
}
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index a0e508f..93ab3be 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -1553,7 +1553,7 @@
parcel.seq = seqNum;
parcel.ack = ackNum;
- apfFilter.addKeepalivePacketFilter(slot1, parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
@@ -1592,7 +1592,7 @@
ipv6Parcel.seq = seqNum;
ipv6Parcel.ack = ackNum;
- apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv6 keepalive ack packet is dropped
@@ -1614,8 +1614,8 @@
apfFilter.removeKeepalivePacketFilter(slot1);
// Verify multiple filters
- apfFilter.addKeepalivePacketFilter(slot1, parcel);
- apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot1, parcel);
+ apfFilter.addTcpKeepalivePacketFilter(slot2, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
index 4d98403..a30d3e4 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
@@ -302,8 +302,9 @@
}
private void assertDhcpResults(String ipAddress, String gateway, String dnsServersString,
- String domains, String serverAddress, String vendorInfo, int leaseDuration,
- boolean hasMeteredHint, int mtu, DhcpResults dhcpResults) throws Exception {
+ String domains, String serverAddress, String serverHostName, String vendorInfo,
+ int leaseDuration, boolean hasMeteredHint, int mtu, DhcpResults dhcpResults)
+ throws Exception {
assertEquals(new LinkAddress(ipAddress), dhcpResults.ipAddress);
assertEquals(v4Address(gateway), dhcpResults.gateway);
@@ -316,6 +317,7 @@
assertEquals(domains, dhcpResults.domains);
assertEquals(v4Address(serverAddress), dhcpResults.serverAddress);
+ assertEquals(serverHostName, dhcpResults.serverHostName);
assertEquals(vendorInfo, dhcpResults.vendorInfo);
assertEquals(leaseDuration, dhcpResults.leaseDuration);
assertEquals(hasMeteredHint, dhcpResults.hasMeteredHint());
@@ -327,6 +329,7 @@
// TODO: Turn all of these into golden files. This will probably require using
// androidx.test.InstrumentationRegistry for obtaining a Context object
// to read such golden files, along with an appropriate Android.mk.
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"451001480000000080118849c0a89003c0a89ff7" +
@@ -347,16 +350,18 @@
// Options
"638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
"3a0400000e103b040000189cff00000000000000000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
- null, "192.168.144.3", null, 7200, false, 0, dhcpResults);
+ null, "192.168.144.3", "", null, 7200, false, 0, dhcpResults);
}
@Test
public void testOffer2() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -366,9 +371,9 @@
"02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
// MAC address.
"30766ff2a90c00000000000000000000" +
- // Server name.
- "0000000000000000000000000000000000000000000000000000000000000000" +
- "0000000000000000000000000000000000000000000000000000000000000000" +
+ // Server name ("dhcp.android.com" plus invalid "AAAA" after null terminator).
+ "646863702e616e64726f69642e636f6d00000000000000000000000000000000" +
+ "0000000000004141414100000000000000000000000000000000000000000000" +
// File.
"0000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000000000000000000000000000000000000" +
@@ -377,13 +382,15 @@
// Options
"638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
"1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+ // CHECKSTYLE:ON Generated code
assertEquals(337, packet.limit());
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.43.247/24", "192.168.43.1", "192.168.43.1",
- null, "192.168.43.1", "ANDROID_METERED", 3600, true, 0, dhcpResults);
+ null, "192.168.43.1", "dhcp.android.com", "ANDROID_METERED", 3600, true, 0,
+ dhcpResults);
assertTrue(dhcpResults.hasMeteredHint());
}
@@ -588,11 +595,12 @@
assertTrue(offerPacket instanceof DhcpOfferPacket); // Implicitly checks it's non-null.
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.159.247/20", "192.168.159.254", "8.8.8.8,8.8.4.4",
- null, "192.168.144.3", null, 7200, false, expectedMtu, dhcpResults);
+ null, "192.168.144.3", "", null, 7200, false, expectedMtu, dhcpResults);
}
@Test
public void testMtu() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"451001480000000080118849c0a89003c0a89ff7" +
@@ -613,6 +621,7 @@
// Options
"638253633501023604c0a89003330400001c200104fffff0000304c0a89ffe06080808080808080404" +
"3a0400000e103b040000189cff00000000"));
+ // CHECKSTYLE:ON Generated code
checkMtu(packet, 0, null);
checkMtu(packet, 0, mtuBytes(1501));
@@ -629,6 +638,7 @@
@Test
public void testBadHwaddrLength() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"450001518d0600004011144dc0a82b01c0a82bf7" +
@@ -649,6 +659,7 @@
// Options
"638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
"1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"));
+ // CHECKSTYLE:ON Generated code
String expectedClientMac = "30766FF2A90C";
final int hwAddrLenOffset = 20 + 8 + 2;
@@ -705,6 +716,7 @@
// store any information in the overloaded fields).
//
// For now, we just check that it parses correctly.
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"b4cef6000000e80462236e300800" +
@@ -727,16 +739,18 @@
// Options
"638253633501023604010101010104ffff000033040000a8c03401030304ac1101010604ac110101" +
"0000000000000000000000000000000000000000000000ff000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("172.17.152.118/16", "172.17.1.1", "172.17.1.1",
- null, "1.1.1.1", null, 43200, false, 0, dhcpResults);
+ null, "1.1.1.1", "", null, 43200, false, 0, dhcpResults);
}
@Test
public void testBug2111() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// IP header.
"4500014c00000000ff119beac3eaf3880a3f5d04" +
@@ -757,16 +771,18 @@
// Options.
"638253633501023604c00002fe33040000bfc60104fffff00003040a3f50010608c0000201c0000202" +
"0f0f646f6d61696e3132332e636f2e756b0000000000ff00000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
assertTrue(offerPacket instanceof DhcpOfferPacket);
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.63.93.4/20", "10.63.80.1", "192.0.2.1,192.0.2.2",
- "domain123.co.uk", "192.0.2.254", null, 49094, false, 0, dhcpResults);
+ "domain123.co.uk", "192.0.2.254", "", null, 49094, false, 0, dhcpResults);
}
@Test
public void testBug2136() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"bcf5ac000000d0c7890000000800" +
@@ -789,17 +805,19 @@
// Options.
"6382536335010236040a20ff80330400001c200104fffff00003040a20900106089458413494584135" +
"0f0b6c616e63732e61632e756b000000000000000000ff00000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
assertEquals("BCF5AC000000", HexDump.toHexString(offerPacket.getClientMac()));
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.32.158.205/20", "10.32.144.1", "148.88.65.52,148.88.65.53",
- "lancs.ac.uk", "10.32.255.128", null, 7200, false, 0, dhcpResults);
+ "lancs.ac.uk", "10.32.255.128", "", null, 7200, false, 0, dhcpResults);
}
@Test
public void testUdpServerAnySourcePort() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"9cd917000000001c2e0000000800" +
@@ -823,6 +841,7 @@
// Options.
"6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
"d18180060f0777766d2e6564751c040a0fffffff000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
@@ -830,11 +849,12 @@
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("10.15.122.242/16", "10.15.200.23",
"209.129.128.3,209.129.148.3,209.129.128.6",
- "wvm.edu", "10.1.105.252", null, 86400, false, 0, dhcpResults);
+ "wvm.edu", "10.1.105.252", "", null, 86400, false, 0, dhcpResults);
}
@Test
public void testUdpInvalidDstPort() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"9cd917000000001c2e0000000800" +
@@ -858,6 +878,7 @@
// Options.
"6382536335010236040a0169fc3304000151800104ffff000003040a0fc817060cd1818003d1819403" +
"d18180060f0777766d2e6564751c040a0fffffff000000"));
+ // CHECKSTYLE:ON Generated code
try {
DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
@@ -867,6 +888,7 @@
@Test
public void testMultipleRouters() throws Exception {
+ // CHECKSTYLE:OFF Generated code
final ByteBuffer packet = ByteBuffer.wrap(HexDump.hexStringToByteArray(
// Ethernet header.
"fc3d93000000" + "081735000000" + "0800" +
@@ -889,13 +911,14 @@
// Options.
"638253633501023604c0abbd023304000070803a04000038403b04000062700104ffffff00" +
"0308c0a8bd01ffffff0006080808080808080404ff000000000000"));
+ // CHECKSTYLE:ON Generated code
DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L2);
assertTrue(offerPacket instanceof DhcpOfferPacket);
assertEquals("FC3D93000000", HexDump.toHexString(offerPacket.getClientMac()));
DhcpResults dhcpResults = offerPacket.toDhcpResults();
assertDhcpResults("192.168.189.49/24", "192.168.189.1", "8.8.8.8,8.8.4.4",
- null, "192.171.189.2", null, 28800, false, 0, dhcpResults);
+ null, "192.171.189.2", "", null, 28800, false, 0, dhcpResults);
}
@Test
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
index 7d5e9e3..f0e2f1b 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 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 fa41284..0dc1cbf 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -26,10 +26,14 @@
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_MIN_EVALUATE_INTERVAL;
import static android.net.util.DataStallUtils.CONFIG_DATA_STALL_VALID_DNS_TIME_THRESHOLD;
import static android.net.util.DataStallUtils.DATA_STALL_EVALUATION_TYPE_DNS;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
+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;
@@ -38,6 +42,7 @@
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;
@@ -52,6 +57,7 @@
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;
@@ -59,8 +65,6 @@
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;
@@ -68,6 +72,7 @@
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;
@@ -78,6 +83,10 @@
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;
@@ -92,8 +101,12 @@
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;
@@ -107,6 +120,7 @@
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;
@@ -152,14 +166,40 @@
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);
- when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_USE_HTTPS),
+ when(mDependencies.getDeviceConfigPropertyInt(any(), eq(CAPTIVE_PORTAL_USE_HTTPS),
anyInt())).thenReturn(1);
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
.thenReturn(TEST_HTTP_URL);
@@ -200,9 +240,8 @@
}).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));
@@ -309,6 +348,44 @@
}
@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);
@@ -638,6 +715,45 @@
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(
@@ -682,13 +798,13 @@
}
private void setOtherFallbackUrls(String urls) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS), any())).thenReturn(urls);
+ when(mDependencies.getDeviceConfigProperty(any(),
+ eq(CAPTIVE_PORTAL_OTHER_FALLBACK_URLS), any())).thenReturn(urls);
}
private void setFallbackSpecs(String specs) {
- when(mDependencies.getSetting(any(),
- eq(Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS), any())).thenReturn(specs);
+ when(mDependencies.getDeviceConfigProperty(any(),
+ eq(CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS), any())).thenReturn(specs);
}
private void setCaptivePortalMode(int mode) {
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 94cc589..87346e5 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.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 IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -156,6 +161,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -163,9 +173,9 @@
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 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 IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -219,6 +239,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index d5efcb5..c60e352 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -647,6 +647,27 @@
dumpSetting(s, p,
Settings.Global.GPU_DEBUG_LAYERS,
GlobalSettingsProto.Gpu.DEBUG_LAYERS);
+ dumpSetting(s, p,
+ Settings.Global.GAME_DRIVER_ALL_APPS,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_ALL_APPS);
+ dumpSetting(s, p,
+ 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/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
new file mode 100644
index 0000000..fe1bb26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M1.22,8.49l0.43-4.96h4.33v1.17H2.67L2.44,7.41c0.41-0.29,0.85-0.43,1.33-0.43c0.77,0,1.38,0.3,1.83,0.9 s0.66,1.41,0.66,2.43c0,1.03-0.24,1.84-0.72,2.43s-1.14,0.88-1.98,0.88c-0.75,0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07,0.57,0.23,1,0.49,1.29c0.26,0.29,0.59,0.43,1.01,0.43c0.47,0,0.84-0.2,1.1-0.61c0.26-0.41,0.4-0.96,0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.96,8.11,3.47,8.11c-0.4,0-0.72,0.1-0.96,0.31L2.19,8.75L1.22,8.49z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M14.14,12.24l-0.22,0.27c-0.63,0.73-1.55,1.1-2.76,1.1c-1.08,0-1.92-0.36-2.53-1.07c-0.61-0.71-0.93-1.72-0.94-3.02V7.56 c0-1.39,0.28-2.44,0.84-3.13c0.56-0.7,1.39-1.04,2.51-1.04c0.95,0,1.69,0.26,2.23,0.79c0.54,0.53,0.83,1.28,0.89,2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45c-0.29-0.35-0.74-0.52-1.34-0.52c-0.72,0-1.24,0.23-1.57,0.7C9.14,5.63,8.96,6.37,8.95,7.4v2.03 c0,1,0.19,1.77,0.57,2.31c0.38,0.54,0.93,0.8,1.65,0.8c0.67,0,1.19-0.16,1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M20.96,8.88h-3.52v3.53h4.1v1.07h-5.35V3.52h5.28V4.6h-4.03V7.8h3.52V8.88z" />
+
+</vector>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4437f49..ccf345b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -390,6 +390,9 @@
<!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
<string name="data_connection_lte_plus">LTE+</string>
+ <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5ge" translate="false">5Ge</string>
+
<!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
<string name="data_connection_5g" translate="false">5G</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 2f7e3b18..b7c20aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -46,6 +46,8 @@
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class MobileSignalController extends SignalController<
@@ -72,6 +74,8 @@
private SignalStrength mSignalStrength;
private MobileIconGroup mDefaultIcons;
private Config mConfig;
+ // Some specific carriers have 5GE network which is special LTE CA network.
+ private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
// TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
// need listener lists anymore.
@@ -235,6 +239,8 @@
TelephonyIcons.LTE_PLUS);
}
}
+ mNetworkToIconLookup.put(NETWORK_TYPE_LTE_CA_5GE,
+ TelephonyIcons.LTE_CA_5G_E);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
}
@@ -400,6 +406,26 @@
}
}
+ private boolean isCarrierSpecificDataIcon() {
+ if (mConfig.patternOfCarrierSpecificDataIcon == null
+ || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
+ return false;
+ }
+
+ Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
+ String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
+ mServiceState.getOperatorAlphaShortRaw()};
+ for (String opName : operatorNames) {
+ if (!TextUtils.isEmpty(opName)) {
+ Matcher matcher = stringPattern.matcher(opName);
+ if (matcher.find()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Updates the network's name based on incoming spn and plmn.
*/
@@ -566,12 +592,8 @@
+ " dataState=" + state.getDataRegState());
}
mServiceState = state;
- if (state != null) {
- mDataNetType = state.getDataNetworkType();
- if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
- mServiceState.isUsingCarrierAggregation()) {
- mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
- }
+ if (mServiceState != null) {
+ updateDataNetType(mServiceState.getDataNetworkType());
}
updateTelephony();
}
@@ -583,14 +605,21 @@
+ " type=" + networkType);
}
mDataState = state;
- mDataNetType = networkType;
- if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
- mServiceState.isUsingCarrierAggregation()) {
- mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
- }
+ updateDataNetType(networkType);
updateTelephony();
}
+ private void updateDataNetType(int networkType) {
+ mDataNetType = networkType;
+ if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
+ if (isCarrierSpecificDataIcon()) {
+ mDataNetType = NETWORK_TYPE_LTE_CA_5GE;
+ } else if (mServiceState != null && mServiceState.isUsingCarrierAggregation()) {
+ mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
+ }
+ }
+ }
+
@Override
public void onDataActivity(int direction) {
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b4f0fec..5c6634c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -1084,6 +1084,7 @@
boolean hspaDataDistinguishable;
boolean inflateSignalStrengths = false;
boolean alwaysShowDataRatIcon = false;
+ public String patternOfCarrierSpecificDataIcon = "";
/**
* Mapping from NR 5G status string to an integer. The NR 5G status string should match
@@ -1122,6 +1123,8 @@
CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
config.hideLtePlus = b.getBoolean(
CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
+ config.patternOfCarrierSpecificDataIcon = b.getString(
+ CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
String nr5GIconConfiguration =
b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 7347f66..2c4b1f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -35,6 +35,7 @@
static final int ICON_3G = R.drawable.ic_3g_mobiledata;
static final int ICON_4G = R.drawable.ic_4g_mobiledata;
static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+ static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
static final int ICON_1X = R.drawable.ic_1x_mobiledata;
static final int ICON_5G = R.drawable.ic_5g_mobiledata;
static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
@@ -204,6 +205,19 @@
TelephonyIcons.ICON_LTE_PLUS,
true);
+ static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+ "5Ge",
+ null,
+ null,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ 0,
+ 0,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.data_connection_5ge,
+ TelephonyIcons.ICON_5G_E,
+ true);
+
static final MobileIconGroup NR_5G = new MobileIconGroup(
"5G",
null,
@@ -260,6 +274,7 @@
ICON_NAME_TO_ICON.put("h+", H_PLUS);
ICON_NAME_TO_ICON.put("4g", FOUR_G);
ICON_NAME_TO_ICON.put("4g+", FOUR_G_PLUS);
+ ICON_NAME_TO_ICON.put("5ge", LTE_CA_5G_E);
ICON_NAME_TO_ICON.put("lte", LTE);
ICON_NAME_TO_ICON.put("lte+", LTE_PLUS);
ICON_NAME_TO_ICON.put("5g", NR_5G);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d79d833..6902a70 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -6492,6 +6492,11 @@
// 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 1c9a43a..9c21e8f 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,9 @@
-artikz@google.com
+alsutton@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
+nathch@google.com
+rthakohov@google.com
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index c1aff75..63fd2fd 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.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 @@
* 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 @@
* - 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 @@
}
// 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 @@
}
}
- 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
try {
nai.networkMonitor().notifyNetworkDisconnected();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
mNetworkAgentInfos.remove(nai.messenger);
nai.clatd.update();
@@ -3062,11 +3070,7 @@
// fallback network the default or requested a new network from the
// NetworkFactories, so network traffic isn't interrupted for an unnecessarily
// long time.
- try {
- mNetd.networkDestroy(nai.network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- loge("Exception destroying network: " + e);
- }
+ destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
}
synchronized (mNetworkForNetId) {
@@ -3074,6 +3078,35 @@
}
}
+ private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ // This should never fail. Specifying an already in use NetID will cause failure.
+ if (networkAgent.isVPN()) {
+ mNetd.networkCreateVpn(networkAgent.network.netId,
+ (networkAgent.networkMisc == null
+ || !networkAgent.networkMisc.allowBypass));
+ } else {
+ mNetd.networkCreatePhysical(networkAgent.network.netId,
+ getNetworkPermission(networkAgent.networkCapabilities));
+ }
+ mDnsResolver.createNetworkCache(networkAgent.network.netId);
+ return true;
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Error creating network " + networkAgent.network.netId + ": "
+ + e.getMessage());
+ return false;
+ }
+ }
+
+ private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
+ try {
+ mNetd.networkDestroy(networkAgent.network.netId);
+ mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Exception destroying network: " + e);
+ }
+ }
+
// If this method proves to be too slow then we can maintain a separate
// pendingIntent => NetworkRequestInfo map.
// This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
@@ -3412,7 +3445,7 @@
try {
nai.networkMonitor().setAcceptPartialConnectivity();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
}
@@ -3448,7 +3481,7 @@
try {
nai.networkMonitor().launchCaptivePortalApp();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
});
}
@@ -4076,7 +4109,7 @@
try {
nai.networkMonitor().forceReevaluation(uid);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
}
@@ -5371,7 +5404,8 @@
}
}
- private boolean isDefaultNetwork(NetworkAgentInfo nai) {
+ @VisibleForTesting
+ protected boolean isDefaultNetwork(NetworkAgentInfo nai) {
return nai == getDefaultNetwork();
}
@@ -5455,7 +5489,7 @@
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 @@
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 @@
// 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 @@
networkAgent.networkMonitor().notifyNetworkConnected(
networkAgent.linkProperties, networkAgent.networkCapabilities);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ e.rethrowAsRuntimeException();
}
scheduleUnvalidatedPrompt(networkAgent);
@@ -6671,7 +6691,8 @@
}
}
- 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 @@
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 2055b64..c1f5255 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 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.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.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 @@
}
/**
+ * 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 @@
*/
@VisibleForTesting
public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient {
- private final T mResource;
- private final List<RefcountedResource> mChildren;
- int mRefCount = 1; // starts at 1 for user's reference.
- IBinder mBinder;
- RefcountedResource(T resource, IBinder binder, RefcountedResource... children) {
+ @NonNull private final T mResource;
+ @NonNull private final List<RefcountedResource> mChildren;
+ int mRefCount = 1; // starts at 1 for user's reference.
+
+ /*
+ * 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 @@
return;
}
- mBinder.unlinkToDeath(this, 0);
+ if (mBinder != DUMMY_BINDER) {
+ mBinder.unlinkToDeath(this, 0);
+ }
mBinder = null;
mResource.invalidate();
-
releaseReference();
}
@@ -381,6 +413,8 @@
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 @@
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 @@
mEncapSocketRecords.remove(resourceId);
}
+ void removeNattKeepaliveRecord(int resourceId) {
+ mNattKeepaliveRecords.remove(resourceId);
+ }
+
@Override
public String toString() {
return new StringBuilder()
@@ -421,6 +461,8 @@
.append(mTransformQuotaTracker)
.append(", mSocketQuotaTracker=")
.append(mSocketQuotaTracker)
+ .append(", mNattKeepaliveQuotaTracker=")
+ .append(mNattKeepaliveQuotaTracker)
.append(", mTunnelQuotaTracker=")
.append(mTunnelQuotaTracker)
.append(", mSpiRecords=")
@@ -429,6 +471,8 @@
.append(mTransformRecords)
.append(", mEncapSocketRecords=")
.append(mEncapSocketRecords)
+ .append(", mNattKeepaliveRecords=")
+ .append(mNattKeepaliveRecords)
.append(", mTunnelInterfaceRecords=")
.append(mTunnelInterfaceRecords)
.append("}")
@@ -573,6 +617,11 @@
mArray.remove(key);
}
+ @VisibleForTesting
+ int size() {
+ return mArray.size();
+ }
+
@Override
public String toString() {
return mArray.toString();
@@ -984,6 +1033,50 @@
}
/**
+ * 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 @@
}
}
+ 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 1ff50b2..6dbe3ad 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2045,28 +2045,6 @@
}
@Override
- public void createPhysicalNetwork(int netId, int permission) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkCreatePhysical(netId, permission);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void createVirtualNetwork(int netId, boolean secure) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkCreateVpn(netId, secure);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
public void addInterfaceToNetwork(String iface, int netId) {
modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
}
@@ -2143,38 +2121,6 @@
}
}
- private int parsePermission(String permission) {
- if (permission.equals("NETWORK")) {
- return INetd.PERMISSION_NETWORK;
- }
- if (permission.equals("SYSTEM")) {
- return INetd.PERMISSION_SYSTEM;
- }
- return INetd.PERMISSION_NONE;
- }
-
- @Override
- public void setPermission(String permission, int[] uids) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkSetPermissionForUser(parsePermission(permission), uids);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void clearPermission(int[] uids) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
- try {
- mNetdService.networkClearPermissionForUser(uids);
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
@Override
public void allowProtect(int uid) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 85787f2..a172fde 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2283,6 +2283,7 @@
.setCallingPid(r.callerPid)
.setCallingUid(r.callerUid)
.setMethod("TelephonyRegistry push")
+ .setLogAsInfo(true) // we don't need to log an error every time we push
.setMinSdkVersionForFine(minSdk)
.build();
@@ -2300,6 +2301,7 @@
.setCallingPid(r.callerPid)
.setCallingUid(r.callerUid)
.setMethod("TelephonyRegistry push")
+ .setLogAsInfo(true) // we don't need to log an error every time we push
.setMinSdkVersionForCoarse(minSdk)
.build();
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 40bf7bc..d19d2dd 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -19,6 +19,7 @@
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.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
+import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/** @hide */
@@ -226,6 +228,8 @@
@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 @@
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 @@
* <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 @@
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 e18f374..5ebd173 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.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 @@
}
} 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 @@
} 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 160c753..9ff47e0 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -55,6 +55,13 @@
// add other system settings here...
sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.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 e33392d..2321afb 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -263,12 +263,6 @@
}
public void removeNetwork(Network network) {
- try {
- mDnsResolver.clearResolverConfiguration(network.netId);
- } catch (RemoteException | ServiceSpecificException e) {
- Slog.e(TAG, "Error clearing DNS configuration: " + e);
- return;
- }
mPrivateDnsMap.remove(network.netId);
mPrivateDnsValidationMap.remove(network.netId);
}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 77a18e2..bde430c 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 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.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 @@
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 @@
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 @@
@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 @@
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 @@
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 @@
+ 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 @@
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 @@
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 @@
}
}
+ // 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 void startNattKeepalive(@Nullable NetworkAgentInfo nai,
@Nullable FileDescriptor fd,
+ int encapSocketResourceId,
int intervalSeconds,
@NonNull ISocketKeepaliveCallback cb,
@NonNull String srcAddrString,
@@ -569,7 +652,7 @@
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 @@
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 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 @@
}
// 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 38eb0bc..8186343 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -16,7 +16,6 @@
package com.android.server.connectivity.tethering;
-import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -164,11 +163,6 @@
}
private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
- if (ipServer.interfaceType() == ConnectivityManager.TETHERING_BLUETOOTH) {
- // TODO: Figure out IPv6 support on PAN interfaces.
- return null;
- }
-
final Downstream ds = findDownstream(ipServer);
if (ds == null) return null;
diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java
new file mode 100644
index 0000000..647727f
--- /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 af9b12a..62ea95b 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -34,11 +34,11 @@
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 SELinuxMMAC.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
per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 54a7e2a..ba2b37f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10722,7 +10722,7 @@
sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
- pkg.applicationInfo.targetSandboxVersion, targetSdkVersion);
+ targetSdkVersion);
pkg.applicationInfo.seInfoUser = SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState(
userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId));
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index b4154c7..b94047e 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -69,9 +69,6 @@
// Append privapp to existing seinfo label
private static final String PRIVILEGED_APP_STR = ":privapp";
- // Append v2 to existing seinfo label
- private static final String SANDBOX_V2_STR = ":v2";
-
// Append targetSdkVersion=n to existing seinfo label where n is the app's targetSdkVersion
private static final String TARGETSDKVERSION_STR = ":targetSdkVersion=";
@@ -323,14 +320,13 @@
*
* @param pkg object representing the package to be labeled.
* @param isPrivileged boolean.
- * @param targetSandboxVersion int.
* @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the
* greater of: lowest targetSdk for all pkgs in the sharedUser, or
* MINIMUM_TARGETSDKVERSION.
* @return String representing the resulting seinfo.
*/
public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged,
- int targetSandboxVersion, int targetSdkVersion) {
+ int targetSdkVersion) {
String seInfo = null;
synchronized (sPolicies) {
if (!sPolicyRead) {
@@ -351,10 +347,6 @@
seInfo = DEFAULT_SEINFO;
}
- if (targetSandboxVersion == 2) {
- seInfo += SANDBOX_V2_STR;
- }
-
if (isPrivileged) {
seInfo += PRIVILEGED_APP_STR;
}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index ca08415..cd7ded5 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -139,7 +139,7 @@
for (PackageParser.Package pkg : pkgList) {
final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
- pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion);
+ seInfoTargetSdkVersion);
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7be7ab2..f0292aa 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.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 @@
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 8f48f5b..ab11fe4 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,8 +3,6 @@
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 @@
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 @@
"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 @@
},
},
api_dir: "aidl/networkstack",
+ imports: ["ipmemorystore-aidl-interfaces"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
}
java_library_static {
@@ -59,9 +65,10 @@
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 @@
],
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 0000000..a8cbab2
--- /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 0000000..cf02c26
--- /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 0000000..291dbef
--- /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 0000000..52f40d4
--- /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 0000000..7853514
--- /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 0000000..3dd2ae6
--- /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 0000000..46d4ecb
--- /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 0000000..54e654b
--- /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 0000000..9531ea3
--- /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 0000000..414272b
--- /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 0000000..92c6779
--- /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 0000000..a8cbab2
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..92b5345
--- /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 0000000..b19f522
--- /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 0000000..ee9871d
--- /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 0000000..7da11e4
--- /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 0000000..f6ca6f7
--- /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 0000000..c80a787
--- /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 0000000..2de790b
--- /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 0000000..3a6c304
--- /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 0000000..e121c06
--- /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 0000000..67193ae
--- /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 0000000..9143158
--- /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 0000000..dcc4489
--- /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 0000000..95a1574
--- /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 0000000..d6bc808
--- /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 0000000..31891de
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,9 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..029968b
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkMonitor.aidl
@@ -0,0 +1,24 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..65de883
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..77d5917
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ip/IIpClient.aidl
@@ -0,0 +1,15 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+}
diff --git a/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31891de
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,9 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..029968b
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkMonitor.aidl
@@ -0,0 +1,24 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..65de883
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..176a5ce
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ip/IIpClient.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+}
diff --git a/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/java/android/net/DhcpResultsParcelable.aidl b/services/net/java/android/net/DhcpResultsParcelable.aidl
index 978638b..c98d9c2 100644
--- a/services/net/java/android/net/DhcpResultsParcelable.aidl
+++ b/services/net/java/android/net/DhcpResultsParcelable.aidl
@@ -24,4 +24,5 @@
int mtu;
String serverAddress;
String vendorInfo;
-}
\ No newline at end of file
+ String serverHostName;
+}
diff --git a/services/net/java/android/net/IIpMemoryStore.aidl b/services/net/java/android/net/IIpMemoryStore.aidl
index 6f88dec..63feae6 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.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 @@
* @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 @@
* @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 b32ef12..3fc81a3 100644
--- a/services/net/java/android/net/INetworkMonitor.aidl
+++ b/services/net/java/android/net/INetworkMonitor.aidl
@@ -40,6 +40,20 @@
// for https probe.
const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ // Network validation flags indicate probe result and types. If no NETWORK_VALIDATION_RESULT_*
+ // are set, then it's equal to NETWORK_TEST_RESULT_INVALID. If NETWORK_VALIDATION_RESULT_VALID
+ // is set, then the network validates and equal to NETWORK_TEST_RESULT_VALID. If
+ // NETWORK_VALIDATION_RESULT_PARTIAL is set, then the network has partial connectivity which
+ // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. NETWORK_VALIDATION_PROBE_* is set
+ // when the specific probe result of the network is resolved.
+ const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+ const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
+
void start();
void launchCaptivePortalApp();
void notifyCaptivePortalAppFinished(int response);
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 9248299..4a115e6 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -41,6 +41,11 @@
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 2f4fdbd..379c017 100644
--- a/services/net/java/android/net/IpMemoryStoreClient.java
+++ b/services/net/java/android/net/IpMemoryStoreClient.java
@@ -20,14 +20,13 @@
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 @@
@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 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 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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
similarity index 84%
rename from core/java/android/net/NattKeepalivePacketData.java
rename to services/net/java/android/net/NattKeepalivePacketData.java
index bdb246f..27ed11e 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/services/net/java/android/net/NattKeepalivePacketData.java
@@ -19,8 +19,10 @@
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import android.annotation.NonNull;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils;
+import android.os.Parcelable;
import android.system.OsConstants;
import java.net.Inet4Address;
@@ -29,8 +31,7 @@
import java.nio.ByteOrder;
/** @hide */
-public final class NattKeepalivePacketData extends KeepalivePacketData {
-
+public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
@@ -77,4 +78,18 @@
return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
}
+
+ /**
+ * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public NattKeepalivePacketDataParcelable toStableParcelable() {
+ final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = srcPort;
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = dstPort;
+ return parcel;
+ }
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
similarity index 66%
copy from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
copy to services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
index a73ba50..6f006d4 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/services/net/java/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -1,12 +1,11 @@
/*
- *
- * Copyright 2019, The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,6 +14,12 @@
* limitations under the License.
*/
-package android.telephony.ims;
+package android.net;
-parcelable RcsMessageQueryResult;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
+
diff --git a/services/net/java/android/net/ip/IIpClient.aidl b/services/net/java/android/net/ip/IIpClient.aidl
index 1e77264..9989c52 100644
--- a/services/net/java/android/net/ip/IIpClient.aidl
+++ b/services/net/java/android/net/ip/IIpClient.aidl
@@ -17,6 +17,7 @@
import android.net.ProxyInfo;
import android.net.ProvisioningConfigurationParcelable;
+import android.net.NattKeepalivePacketDataParcelable;
import android.net.TcpKeepalivePacketDataParcelable;
/** @hide */
@@ -33,4 +34,5 @@
void addKeepalivePacketFilter(int slot, in TcpKeepalivePacketDataParcelable pkt);
void removeKeepalivePacketFilter(int slot);
void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ void addNattKeepalivePacketFilter(int slot, in NattKeepalivePacketDataParcelable pkt);
}
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 90624e0..714ade1 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -175,6 +175,11 @@
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 fc1128b..66884c6 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -277,6 +277,11 @@
}
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
similarity index 94%
rename from services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl
rename to services/net/java/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
index fb4ca3b..870e217 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.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
similarity index 89%
rename from services/net/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl
rename to services/net/java/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
index 294bd3b..b8ccfb9 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.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 0000000..a17483a
--- /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 0000000..e608aec
--- /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 0000000..ca6f302
--- /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 0000000..67f8da8
--- /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 0000000..4262efd
--- /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 44d8e0c..172dc24 100644
--- a/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
+++ b/services/net/java/android/net/shared/IpConfigurationParcelableUtil.java
@@ -41,6 +41,7 @@
p.mtu = results.mtu;
p.serverAddress = parcelAddress(results.serverAddress);
p.vendorInfo = results.vendorInfo;
+ p.serverHostName = results.serverHostName;
return p;
}
@@ -54,6 +55,7 @@
results.mtu = p.mtu;
results.serverAddress = (Inet4Address) unparcelAddress(p.serverAddress);
results.vendorInfo = p.vendorInfo;
+ results.serverHostName = p.serverHostName;
return results;
}
diff --git a/startop/iorap/TEST_MAPPING b/startop/iorap/DISABLED_TEST_MAPPING
similarity index 100%
rename from startop/iorap/TEST_MAPPING
rename to startop/iorap/DISABLED_TEST_MAPPING
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index e25c17d..0f63853 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Build;
@@ -174,4 +175,21 @@
in.readString(),
UserHandle.CREATOR.createFromParcel(in));
}
+
+ /**
+ * Determines if two {@link PhoneAccountHandle}s are from the same package.
+ *
+ * @param a Phone account handle to check for same {@link ConnectionService} package.
+ * @param b Other phone account handle to check for same {@link ConnectionService} package.
+ * @return {@code true} if the two {@link PhoneAccountHandle}s passed in belong to the same
+ * {@link ConnectionService} / package, {@code false} otherwise. Note: {@code null} phone
+ * account handles are considered equivalent to other {@code null} phone account handles.
+ * @hide
+ */
+ public static boolean areFromSamePackage(@Nullable PhoneAccountHandle a,
+ @Nullable PhoneAccountHandle b) {
+ String aPackageName = a != null ? a.getComponentName().getPackageName() : null;
+ String bPackageName = b != null ? b.getComponentName().getPackageName() : null;
+ return Objects.equals(aPackageName, bPackageName);
+ }
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index ecb0daf..e727a6e 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -4259,6 +4259,22 @@
* @hide
*/
public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
+
+ /**
+ * The current registered raw data network operator name in long alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaLongRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_LONG_RAW = "operator_alpha_long_raw";
+
+ /**
+ * The current registered raw data network operator name in short alphanumeric format.
+ * <p>
+ * This is the same as {@link ServiceState#getOperatorAlphaShortRaw()}.
+ * @hide
+ */
+ public static final String OPERATOR_ALPHA_SHORT_RAW = "operator_alpha_short_raw";
}
/**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index bd528b8..c32e164 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1199,6 +1199,82 @@
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 @@
"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 @@
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 @@
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);
@@ -3048,17 +3151,21 @@
/**
* Overrides the carrier config of the provided subscription ID with the provided values.
*
- * Any further queries to carrier config from any process will return
- * the overriden values after this method returns. The overrides are effective for the lifetime
- * of the phone process.
+ * Any further queries to carrier config from any process will return the overridden values
+ * after this method returns. The overrides are effective for the lifetime of the phone process
+ * until the user passes in {@code null} for {@code overrideValues}. This removes all previous
+ * overrides and sets the carrier config back to production values.
*
* 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.
+ *
* @param subscriptionId The subscription ID for which the override should be done.
- * @param overrideValues Key-value pairs of the values that are to be overriden. If null,
- * all previous overrides will be disabled and the config reset back to
- * its initial state.
+ * @param overrideValues Key-value pairs of the values that are to be overridden. If set to
+ * {@code null}, this will remove all previous overrides and set the
+ * carrier configuration back to production values.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index a83d8f0..cbe5e71 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -49,10 +49,10 @@
// long alpha Operator Name String or Enhanced Operator Name String
/** @hide */
- protected final String mAlphaLong;
+ protected String mAlphaLong;
// short alpha Operator Name String or Enhanced Operator Name String
/** @hide */
- protected final String mAlphaShort;
+ protected String mAlphaShort;
/** @hide */
protected CellIdentity(String tag, int type, String mcc, String mnc, String alphal,
@@ -145,6 +145,13 @@
}
/**
+ * @hide
+ */
+ public void setOperatorAlphaLong(String alphaLong) {
+ mAlphaLong = alphaLong;
+ }
+
+ /**
* @return The short alpha tag associated with the current scan result (may be the operator
* name string or extended operator name string). May be null if unknown.
*/
@@ -154,6 +161,13 @@
}
/**
+ * @hide
+ */
+ public void setOperatorAlphaShort(String alphaShort) {
+ mAlphaShort = alphaShort;
+ }
+
+ /**
* @return a CellLocation object for this CellIdentity
* @hide
*/
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 2cb369d..3dd9318 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -95,6 +95,21 @@
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/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index b9d8eb6..eb744f6 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -63,15 +63,18 @@
public final int callingPid;
public final int minSdkVersionForCoarse;
public final int minSdkVersionForFine;
+ public final boolean logAsInfo;
public final String method;
private LocationPermissionQuery(String callingPackage, int callingUid, int callingPid,
- int minSdkVersionForCoarse, int minSdkVersionForFine, String method) {
+ int minSdkVersionForCoarse, int minSdkVersionForFine, boolean logAsInfo,
+ String method) {
this.callingPackage = callingPackage;
this.callingUid = callingUid;
this.callingPid = callingPid;
this.minSdkVersionForCoarse = minSdkVersionForCoarse;
this.minSdkVersionForFine = minSdkVersionForFine;
+ this.logAsInfo = logAsInfo;
this.method = method;
}
@@ -81,6 +84,7 @@
private int mCallingPid;
private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
private int mMinSdkVersionForFine = Integer.MAX_VALUE;
+ private boolean mLogAsInfo = false;
private String mMethod;
/**
@@ -135,14 +139,27 @@
return this;
}
+ /**
+ * If called with {@code true}, log messages will only be printed at the info level.
+ */
+ public Builder setLogAsInfo(boolean logAsInfo) {
+ mLogAsInfo = logAsInfo;
+ return this;
+ }
+
public LocationPermissionQuery build() {
return new LocationPermissionQuery(mCallingPackage, mCallingUid,
- mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine, mMethod);
+ mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
+ mLogAsInfo, mMethod);
}
}
}
- private static void logError(Context context, String errorMsg) {
+ private static void logError(Context context, LocationPermissionQuery query, String errorMsg) {
+ if (query.logAsInfo) {
+ Log.i(TAG, errorMsg);
+ return;
+ }
Log.e(TAG, errorMsg);
try {
if (Build.IS_DEBUGGABLE) {
@@ -201,13 +218,13 @@
+ " because we're not enforcing API " + minSdkVersion + " yet."
+ " Please fix this app because it will break in the future. Called from "
+ query.method;
- logError(context, errorMsg);
+ logError(context, query, errorMsg);
return null;
} else if (!isAppAtLeastSdkVersion(context, query.callingPackage, minSdkVersion)) {
String errorMsg = "Allowing " + query.callingPackage + " " + locationTypeForLog
+ " because it doesn't target API " + minSdkVersion + " yet."
+ " Please fix this app. Called from " + query.method;
- logError(context, errorMsg);
+ logError(context, query, errorMsg);
return null;
} else {
// If we're not allowing it due to the above two conditions, this means that the app
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 7b9f6d5..2fae949 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -280,6 +280,39 @@
}
/**
+ * 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 f4a6984..0ad1abe 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -339,6 +339,9 @@
private List<NetworkRegistrationInfo> mNetworkRegistrationInfos = new ArrayList<>();
+ private String mOperatorAlphaLongRaw;
+ private String mOperatorAlphaShortRaw;
+
/**
* get String description of roaming type
* @hide
@@ -418,8 +421,10 @@
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 @@
mChannelNumber = in.readInt();
mCellBandwidths = in.createIntArray();
mNrFrequencyRange = in.readInt();
+ mOperatorAlphaLongRaw = in.readString();
+ mOperatorAlphaShortRaw = in.readString();
}
public void writeToParcel(Parcel out, int flags) {
@@ -478,6 +485,8 @@
out.writeInt(mChannelNumber);
out.writeIntArray(mCellBandwidths);
out.writeInt(mNrFrequencyRange);
+ out.writeString(mOperatorAlphaLongRaw);
+ out.writeString(mOperatorAlphaShortRaw);
}
public int describeContents() {
@@ -836,7 +845,9 @@
mIsEmergencyOnly,
mLteEarfcnRsrpBoost,
mNetworkRegistrationInfos,
- mNrFrequencyRange);
+ mNrFrequencyRange,
+ mOperatorAlphaLongRaw,
+ mOperatorAlphaShortRaw);
}
@Override
@@ -862,6 +873,8 @@
&& equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
s.mCdmaDefaultRoamingIndicator)
&& mIsEmergencyOnly == s.mIsEmergencyOnly
+ && equalsHandlesNulls(mOperatorAlphaLongRaw, s.mOperatorAlphaLongRaw)
+ && equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
&& (mNetworkRegistrationInfos == null
? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
&& mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
@@ -1019,6 +1032,8 @@
.append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
.append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
.append(", mNrFrequencyRange=").append(mNrFrequencyRange)
+ .append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
+ .append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
.append("}").toString();
}
@@ -1056,6 +1071,8 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
+ mOperatorAlphaLongRaw = null;
+ mOperatorAlphaShortRaw = null;
}
public void setStateOutOfService() {
@@ -1113,16 +1130,16 @@
/** @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 @@
/** @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 @@
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 @@
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 @@
// 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 @@
* @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 @@
@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 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
if (networkRegistrationInfo.getTransportType() == transportType) {
- list.add(networkRegistrationInfo);
+ list.add(new NetworkRegistrationInfo(networkRegistrationInfo));
}
}
}
@@ -1819,7 +1842,7 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
if (networkRegistrationInfo.getDomain() == domain) {
- list.add(networkRegistrationInfo);
+ list.add(new NetworkRegistrationInfo(networkRegistrationInfo));
}
}
}
@@ -1844,7 +1867,7 @@
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
if (networkRegistrationInfo.getTransportType() == transportType
&& networkRegistrationInfo.getDomain() == domain) {
- return networkRegistrationInfo;
+ return new NetworkRegistrationInfo(networkRegistrationInfo);
}
}
}
@@ -1856,20 +1879,20 @@
* @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 @@
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/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 586c815..43acfdd 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -294,6 +294,19 @@
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 @@
} else {
logd("putPhoneIdAndSubIdExtra: no valid subs");
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
}
@@ -2063,9 +2075,6 @@
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- //FIXME this is using phoneId and slotIndex interchangeably
- //Eventually, this should be removed as it is not the slot id
- intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
}
/**
@@ -3087,6 +3096,31 @@
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 e1425b9..510e7c9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -64,6 +64,7 @@
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 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
}
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 d95a499..2246ccc 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -101,7 +101,7 @@
/**
* Get the embedded ID (EID) of the eUICC. If the UiccCardInfo is not an eUICC
- * (see {@link #isEuicc()}), returns null.
+ * (see {@link #isEuicc()}), or the EID is not available, returns null.
* <p>
* Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}).
@@ -115,7 +115,7 @@
}
/**
- * Get the ICCID of the UICC.
+ * Get the ICCID of the UICC. If the ICCID is not availble, returns null.
* <p>
* Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}).
diff --git a/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java
index 18a533a..d43181e 100644
--- a/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/VoiceSpecificRegistrationInfo.java
@@ -65,6 +65,19 @@
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 dba2207..2d6402d 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -635,7 +635,7 @@
!= 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 f1a5778..ee287d5 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -321,6 +321,18 @@
"android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
/**
+ * Key for an extra set on privileged actions {@link #ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED}
+ * providing the physical slot ID of the target slot.
+ *
+ * <p>Expected type of the extra data: int
+ *
+ * @hide
+ */
+ // TODO: Make this a @SystemApi.
+ public static final String EXTRA_PHYSICAL_SLOT_ID =
+ "android.telephony.euicc.extra.PHYSICAL_SLOT_ID";
+
+ /**
* Optional meta-data attribute for a carrier app providing an icon to use to represent the
* carrier. If not provided, the app's launcher icon will be used as a fallback.
*/
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 568c11b..fd58f7e 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -545,7 +545,8 @@
+ ", emergencyUrns=" + mEmergencyUrns
+ ", emergencyCallRouting=" + mEmergencyCallRouting
+ ", emergencyCallTesting=" + mEmergencyCallTesting
- + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }";
+ + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency
+ + ", mRestrictCause=" + mRestrictCause + " }";
}
@Override
@@ -565,6 +566,7 @@
out.writeInt(mEmergencyCallRouting);
out.writeBoolean(mEmergencyCallTesting);
out.writeBoolean(mHasKnownUserIntentEmergency);
+ out.writeInt(mRestrictCause);
}
private void readFromParcel(Parcel in) {
@@ -577,6 +579,7 @@
mEmergencyCallRouting = in.readInt();
mEmergencyCallTesting = in.readBoolean();
mHasKnownUserIntentEmergency = in.readBoolean();
+ mRestrictCause = in.readInt();
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index c008711..e6777c17 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -40,8 +40,6 @@
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting;
-import static android.Manifest.permission.MODIFY_PHONE_STATE;
-
/**
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
* ImsService must register the service in their AndroidManifest to be detected by the framework.
@@ -229,8 +227,8 @@
private void setupFeature(ImsFeature f, int slotId, int featureType,
IImsFeatureStatusCallback c) {
- f.addImsFeatureStatusCallback(c);
f.initialize(this, slotId);
+ f.addImsFeatureStatusCallback(c);
addImsFeature(slotId, featureType, f);
}
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index 0bb1b43..39e9789b 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -33,8 +33,8 @@
*
* @hide
*/
- public Rcs1To1Thread(int threadId) {
- super(threadId);
+ public Rcs1To1Thread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
mThreadId = threadId;
}
@@ -56,7 +56,7 @@
*/
@WorkerThread
public long getFallbackThreadId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
+ return mRcsControllerCall.call(iRcs -> iRcs.get1To1ThreadFallbackThreadId(mThreadId));
}
/**
@@ -69,7 +69,7 @@
*/
@WorkerThread
public void setFallbackThreadId(long fallbackThreadId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.set1To1ThreadFallbackThreadId(mThreadId, fallbackThreadId));
}
@@ -81,6 +81,7 @@
@WorkerThread
public RcsParticipant getRecipient() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.get1To1ThreadOtherParticipantId(mThreadId)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
index 5512c4c..3bd441e 100644
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ b/telephony/java/android/telephony/ims/RcsControllerCall.java
@@ -27,7 +27,13 @@
* @hide - not meant for public use
*/
class RcsControllerCall {
- static <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
+ private final Context mContext;
+
+ RcsControllerCall(Context context) {
+ mContext = context;
+ }
+
+ <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
if (iRcs == null) {
throw new RcsMessageStoreException("Could not connect to RCS storage service");
@@ -40,18 +46,12 @@
}
}
- static void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
+ void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
throws RcsMessageStoreException {
- IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
- if (iRcs == null) {
- throw new RcsMessageStoreException("Could not connect to RCS storage service");
- }
-
- try {
+ call(iRcs -> {
serviceCall.methodOnIRcs(iRcs);
- } catch (RemoteException exception) {
- throw new RcsMessageStoreException(exception.getMessage());
- }
+ return null;
+ });
}
interface RcsServiceCall<R> {
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index 994b27a..9dd0720 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -40,5 +40,5 @@
*
* @hide
*/
- abstract void persist() throws RcsMessageStoreException;
+ abstract void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException;
}
diff --git a/telephony/java/android/telephony/ims/RcsEventDescriptor.java b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
index 8e3f6cd..b44adea 100644
--- a/telephony/java/android/telephony/ims/RcsEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventDescriptor.java
@@ -38,7 +38,7 @@
* descriptor.
*/
@VisibleForTesting(visibility = PROTECTED)
- public abstract RcsEvent createRcsEvent();
+ public abstract RcsEvent createRcsEvent(RcsControllerCall rcsControllerCall);
RcsEventDescriptor(Parcel in) {
mTimestamp = in.readLong();
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
index e30745b7..b972d55 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResultDescriptor.java
@@ -39,9 +39,9 @@
mEvents = events;
}
- protected RcsEventQueryResult getRcsEventQueryResult() {
+ protected RcsEventQueryResult getRcsEventQueryResult(RcsControllerCall rcsControllerCall) {
List<RcsEvent> rcsEvents = mEvents.stream()
- .map(RcsEventDescriptor::createRcsEvent)
+ .map(rcsEvent -> rcsEvent.createRcsEvent(rcsControllerCall))
.collect(Collectors.toList());
return new RcsEventQueryResult(mContinuationToken, rcsEvents);
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 3816cd4..9926658 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -103,12 +103,15 @@
public @interface RcsFileTransferStatus {
}
+ private final RcsControllerCall mRcsControllerCall;
+
private int mId;
/**
* @hide
*/
- RcsFileTransferPart(int id) {
+ RcsFileTransferPart(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -134,7 +137,7 @@
*/
@WorkerThread
public void setFileTransferSessionId(String sessionId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferSessionId(mId, sessionId));
}
/**
@@ -143,7 +146,7 @@
*/
@WorkerThread
public String getFileTransferSessionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferSessionId(mId));
}
/**
@@ -155,7 +158,8 @@
*/
@WorkerThread
public void setContentUri(Uri contentUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
+ mRcsControllerCall.callWithNoReturn(
+ iRcs -> iRcs.setFileTransferContentUri(mId, contentUri));
}
/**
@@ -165,7 +169,7 @@
@Nullable
@WorkerThread
public Uri getContentUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferContentUri(mId));
}
/**
@@ -177,7 +181,7 @@
*/
@WorkerThread
public void setContentMimeType(String contentMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setFileTransferContentType(mId, contentMimeType));
}
@@ -188,7 +192,7 @@
@WorkerThread
@Nullable
public String getContentMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferContentType(mId));
}
/**
@@ -199,7 +203,7 @@
*/
@WorkerThread
public void setFileSize(long contentLength) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setFileTransferFileSize(mId, contentLength));
}
@@ -209,7 +213,7 @@
*/
@WorkerThread
public long getFileSize() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferFileSize(mId));
}
/**
@@ -222,7 +226,7 @@
*/
@WorkerThread
public void setTransferOffset(long transferOffset) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setFileTransferTransferOffset(mId, transferOffset));
}
@@ -232,7 +236,7 @@
*/
@WorkerThread
public long getTransferOffset() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferTransferOffset(mId));
}
/**
@@ -244,7 +248,7 @@
@WorkerThread
public void setFileTransferStatus(@RcsFileTransferStatus int status)
throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferStatus(mId, status));
}
/**
@@ -253,7 +257,7 @@
*/
@WorkerThread
public @RcsFileTransferStatus int getFileTransferStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferStatus(mId));
}
/**
@@ -262,7 +266,7 @@
*/
@WorkerThread
public int getWidth() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferWidth(mId));
}
/**
@@ -273,7 +277,7 @@
*/
@WorkerThread
public void setWidth(int width) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferWidth(mId, width));
}
/**
@@ -282,7 +286,7 @@
*/
@WorkerThread
public int getHeight() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferHeight(mId));
}
/**
@@ -293,7 +297,7 @@
*/
@WorkerThread
public void setHeight(int height) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferHeight(mId, height));
}
/**
@@ -302,7 +306,7 @@
*/
@WorkerThread
public long getLength() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferLength(mId));
}
/**
@@ -313,7 +317,7 @@
*/
@WorkerThread
public void setLength(long length) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferLength(mId, length));
}
/**
@@ -323,7 +327,7 @@
*/
@WorkerThread
public Uri getPreviewUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewUri(mId));
}
/**
@@ -334,7 +338,8 @@
*/
@WorkerThread
public void setPreviewUri(Uri previewUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
+ mRcsControllerCall.callWithNoReturn(
+ iRcs -> iRcs.setFileTransferPreviewUri(mId, previewUri));
}
/**
@@ -343,7 +348,7 @@
*/
@WorkerThread
public String getPreviewMimeType() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getFileTransferPreviewType(mId));
}
/**
@@ -354,7 +359,7 @@
*/
@WorkerThread
public void setPreviewMimeType(String previewMimeType) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setFileTransferPreviewType(mId, previewMimeType));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index baec19a..0482f57 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -38,8 +38,8 @@
*
* @hide
*/
- public RcsGroupThread(int threadId) {
- super(threadId);
+ public RcsGroupThread(RcsControllerCall rcsControllerCall, int threadId) {
+ super(rcsControllerCall, threadId);
}
/**
@@ -58,7 +58,7 @@
@Nullable
@WorkerThread
public String getGroupName() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadName(mThreadId));
}
/**
@@ -69,7 +69,7 @@
*/
@WorkerThread
public void setGroupName(String groupName) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadName(mThreadId, groupName));
}
/**
@@ -79,7 +79,7 @@
*/
@Nullable
public Uri getGroupIcon() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadIcon(mThreadId));
}
/**
@@ -90,7 +90,7 @@
*/
@WorkerThread
public void setGroupIcon(@Nullable Uri groupIcon) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setGroupThreadIcon(mThreadId, groupIcon));
}
/**
@@ -100,8 +100,9 @@
@Nullable
@WorkerThread
public RcsParticipant getOwner() throws RcsMessageStoreException {
- return new RcsParticipant(RcsControllerCall.call(
- iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
+ return new RcsParticipant(
+ mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadOwner(mThreadId)));
}
/**
@@ -114,7 +115,7 @@
*/
@WorkerThread
public void setOwner(@Nullable RcsParticipant participant) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setGroupThreadOwner(mThreadId, participant.getId()));
}
@@ -133,7 +134,7 @@
return;
}
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.addParticipantToGroupThread(mThreadId, participant.getId()));
}
@@ -150,7 +151,7 @@
return;
}
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.removeParticipantFromGroupThread(mThreadId, participant.getId()));
}
@@ -170,7 +171,8 @@
new RcsParticipantQueryParams.Builder().setThread(this).build();
RcsParticipantQueryResult queryResult = new RcsParticipantQueryResult(
- RcsControllerCall.call(
+ mRcsControllerCall,
+ mRcsControllerCall.call(
iRcs -> iRcs.getParticipants(queryParameters)));
List<RcsParticipant> participantList = queryResult.getParticipants();
@@ -187,7 +189,7 @@
@Nullable
@WorkerThread
public Uri getConferenceUri() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getGroupThreadConferenceUri(mThreadId));
}
/**
@@ -200,7 +202,7 @@
@Nullable
@WorkerThread
public void setConferenceUri(Uri conferenceUri) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setGroupThreadConferenceUri(mThreadId, conferenceUri));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 4a6b963..f4beef7f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -23,14 +23,14 @@
* @hide
*/
public abstract class RcsGroupThreadEvent extends RcsEvent {
- private final int mRcsGroupThreadId;
- private final int mOriginatingParticipantId;
+ private final RcsGroupThread mRcsGroupThread;
+ private final RcsParticipant mOriginatingParticipant;
- RcsGroupThreadEvent(long timestamp, int rcsGroupThreadId,
- int originatingParticipantId) {
+ RcsGroupThreadEvent(long timestamp, RcsGroupThread rcsGroupThread,
+ RcsParticipant originatingParticipant) {
super(timestamp);
- mRcsGroupThreadId = rcsGroupThreadId;
- mOriginatingParticipantId = originatingParticipantId;
+ mRcsGroupThread = rcsGroupThread;
+ mOriginatingParticipant = originatingParticipant;
}
/**
@@ -38,7 +38,7 @@
*/
@NonNull
public RcsGroupThread getRcsGroupThread() {
- return new RcsGroupThread(mRcsGroupThreadId);
+ return mRcsGroupThread;
}
/**
@@ -46,6 +46,6 @@
*/
@NonNull
public RcsParticipant getOriginatingParticipant() {
- return new RcsParticipant(mOriginatingParticipantId);
+ return mOriginatingParticipant;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index 3c6c74f..d17401f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -40,9 +40,10 @@
* @param newIcon {@link Uri} to the new icon of this {@link RcsGroupThread}
* @see RcsMessageStore#persistRcsEvent(RcsEvent)
*/
- public RcsGroupThreadIconChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
- @NonNull RcsParticipant originatingParticipant, @Nullable Uri newIcon) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ public RcsGroupThreadIconChangedEvent(long timestamp,
+ @NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
+ @Nullable Uri newIcon) {
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewIcon = newIcon;
}
@@ -61,9 +62,9 @@
* @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 -> iRcs.createGroupThreadIconChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
getOriginatingParticipant().getId(), mNewIcon));
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
index bcadc80..9350e40 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEventDescriptor.java
@@ -38,9 +38,10 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadIconChangedEvent createRcsEvent() {
- return new RcsGroupThreadIconChangedEvent(mTimestamp, new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId), mNewIcon);
+ public RcsGroupThreadIconChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
+ return new RcsGroupThreadIconChangedEvent(mTimestamp,
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId), mNewIcon);
}
public static final @NonNull Creator<RcsGroupThreadIconChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index 5403253..8430dc4 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -41,7 +41,7 @@
*/
public RcsGroupThreadNameChangedEvent(long timestamp, @NonNull RcsGroupThread rcsGroupThread,
@NonNull RcsParticipant originatingParticipant, @Nullable String newName) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mNewName = newName;
}
@@ -60,8 +60,8 @@
* @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 -> iRcs.createGroupThreadNameChangedEvent(
getTimestamp(), getRcsGroupThread().getThreadId(),
getOriginatingParticipant().getId(), mNewName));
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
index 597fa0a..f9ccdd5 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEventDescriptor.java
@@ -37,11 +37,11 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadNameChangedEvent createRcsEvent() {
+ public RcsGroupThreadNameChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadNameChangedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
mNewName);
}
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 48be479..2cdf960a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -42,7 +42,7 @@
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,8 +59,8 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
iRcs -> iRcs.createGroupThreadParticipantJoinedEvent(getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
getJoinedParticipant().getId()));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
index abea10a..4a6803e 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEventDescriptor.java
@@ -36,12 +36,13 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantJoinedEvent createRcsEvent() {
+ public RcsGroupThreadParticipantJoinedEvent createRcsEvent(
+ RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantJoinedEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mJoinedParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mJoinedParticipantId));
}
public static final @NonNull Creator<RcsGroupThreadParticipantJoinedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index b724a3f..22d48fc 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -44,7 +44,7 @@
public RcsGroupThreadParticipantLeftEvent(long timestamp,
@NonNull RcsGroupThread rcsGroupThread, @NonNull RcsParticipant originatingParticipant,
@NonNull RcsParticipant leavingParticipant) {
- super(timestamp, rcsGroupThread.getThreadId(), originatingParticipant.getId());
+ super(timestamp, rcsGroupThread, originatingParticipant);
mLeavingParticipant = leavingParticipant;
}
@@ -58,8 +58,8 @@
}
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(
iRcs -> iRcs.createGroupThreadParticipantLeftEvent(getTimestamp(),
getRcsGroupThread().getThreadId(), getOriginatingParticipant().getId(),
getLeavingParticipant().getId()));
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
index f287db1..9b1085c 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEventDescriptor.java
@@ -37,12 +37,12 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsGroupThreadParticipantLeftEvent createRcsEvent() {
+ public RcsGroupThreadParticipantLeftEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsGroupThreadParticipantLeftEvent(
mTimestamp,
- new RcsGroupThread(mRcsGroupThreadId),
- new RcsParticipant(mOriginatingParticipantId),
- new RcsParticipant(mLeavingParticipantId));
+ new RcsGroupThread(rcsControllerCall, mRcsGroupThreadId),
+ new RcsParticipant(rcsControllerCall, mOriginatingParticipantId),
+ new RcsParticipant(rcsControllerCall, mLeavingParticipantId));
}
@NonNull
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 06e2a41..87ddbbf 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -26,8 +26,8 @@
/**
* @hide
*/
- RcsIncomingMessage(int id) {
- super(id);
+ RcsIncomingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -39,7 +39,7 @@
*/
@WorkerThread
public void setArrivalTimestamp(long arrivalTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setMessageArrivalTimestamp(mId, true, arrivalTimestamp));
}
@@ -50,7 +50,7 @@
*/
@WorkerThread
public long getArrivalTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
+ return mRcsControllerCall.call(iRcs -> iRcs.getMessageArrivalTimestamp(mId, true));
}
/**
@@ -62,7 +62,7 @@
*/
@WorkerThread
public void setSeenTimestamp(long notifiedTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setMessageSeenTimestamp(mId, true, notifiedTimestamp));
}
@@ -73,7 +73,7 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
+ return mRcsControllerCall.call(iRcs -> iRcs.getMessageSeenTimestamp(mId, true));
}
/**
@@ -83,7 +83,8 @@
@WorkerThread
public RcsParticipant getSenderParticipant() throws RcsMessageStoreException {
return new RcsParticipant(
- RcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
+ mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.getSenderParticipant(mId)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index 63dc1ac..0d6ca3c 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -25,20 +25,19 @@
*/
@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
+ private final RcsMessageStore mRcsMessageStore;
/**
* @hide
*/
- public RcsManager() {
- // empty constructor
+ public RcsManager(Context context) {
+ mRcsMessageStore = new RcsMessageStore(context);
}
- private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
-
/**
* Returns an instance of {@link RcsMessageStore}
*/
public RcsMessageStore getRcsMessageStore() {
- return sRcsMessageStoreInstance;
+ return mRcsMessageStore;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index b0d0d5a..1c466b9 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -86,6 +86,11 @@
/**
* @hide
*/
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
protected final int mId;
@IntDef({
@@ -95,7 +100,8 @@
public @interface RcsMessageStatus {
}
- RcsMessage(int id) {
+ RcsMessage(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -115,7 +121,7 @@
* @see android.telephony.SubscriptionInfo#getSubscriptionId
*/
public int getSubscriptionId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
+ return mRcsControllerCall.call(iRcs -> iRcs.getMessageSubId(mId, isIncoming()));
}
/**
@@ -128,7 +134,7 @@
*/
@WorkerThread
public void setSubscriptionId(int subId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setMessageSubId(mId, isIncoming(), subId));
}
/**
@@ -139,7 +145,7 @@
*/
@WorkerThread
public void setStatus(@RcsMessageStatus int rcsMessageStatus) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setMessageStatus(mId, isIncoming(), rcsMessageStatus));
}
@@ -150,7 +156,7 @@
*/
@WorkerThread
public @RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
+ return mRcsControllerCall.call(iRcs -> iRcs.getMessageStatus(mId, isIncoming()));
}
/**
@@ -163,7 +169,7 @@
*/
@WorkerThread
public void setOriginationTimestamp(long timestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setMessageOriginationTimestamp(mId, isIncoming(), timestamp));
}
@@ -175,7 +181,7 @@
*/
@WorkerThread
public long getOriginationTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
+ return mRcsControllerCall.call(
iRcs -> iRcs.getMessageOriginationTimestamp(mId, isIncoming()));
}
@@ -189,7 +195,7 @@
*/
@WorkerThread
public void setRcsMessageId(String rcsMessageGlobalId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setGlobalMessageIdForMessage(mId, isIncoming(), rcsMessageGlobalId));
}
@@ -200,7 +206,8 @@
*/
@WorkerThread
public String getRcsMessageId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(
+ iRcs -> iRcs.getGlobalMessageIdForMessage(mId, isIncoming()));
}
/**
@@ -209,7 +216,7 @@
*/
@WorkerThread
public String getText() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(iRcs -> iRcs.getTextForMessage(mId, isIncoming()));
}
/**
@@ -220,7 +227,8 @@
*/
@WorkerThread
public void setText(String text) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
+ mRcsControllerCall.callWithNoReturn(
+ iRcs -> iRcs.setTextForMessage(mId, isIncoming(), text));
}
/**
@@ -231,7 +239,7 @@
*/
@WorkerThread
public double getLatitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(iRcs -> iRcs.getLatitudeForMessage(mId, isIncoming()));
}
/**
@@ -242,7 +250,7 @@
*/
@WorkerThread
public void setLatitude(double latitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setLatitudeForMessage(mId, isIncoming(), latitude));
}
@@ -254,7 +262,7 @@
*/
@WorkerThread
public double getLongitude() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
+ return mRcsControllerCall.call(iRcs -> iRcs.getLongitudeForMessage(mId, isIncoming()));
}
/**
@@ -265,7 +273,7 @@
*/
@WorkerThread
public void setLongitude(double longitude) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.setLongitudeForMessage(mId, isIncoming(), longitude));
}
@@ -282,7 +290,7 @@
public RcsFileTransferPart insertFileTransfer(
RcsFileTransferCreationParams fileTransferCreationParameters)
throws RcsMessageStoreException {
- return new RcsFileTransferPart(RcsControllerCall.call(
+ return new RcsFileTransferPart(mRcsControllerCall, mRcsControllerCall.call(
iRcs -> iRcs.storeFileTransfer(mId, isIncoming(), fileTransferCreationParameters)));
}
@@ -296,11 +304,11 @@
public Set<RcsFileTransferPart> getFileTransferParts() throws RcsMessageStoreException {
Set<RcsFileTransferPart> fileTransferParts = new HashSet<>();
- int[] fileTransferIds = RcsControllerCall.call(
+ int[] fileTransferIds = mRcsControllerCall.call(
iRcs -> iRcs.getFileTransfersAttachedToMessage(mId, isIncoming()));
for (int fileTransfer : fileTransferIds) {
- fileTransferParts.add(new RcsFileTransferPart(fileTransfer));
+ fileTransferParts.add(new RcsFileTransferPart(mRcsControllerCall, fileTransfer));
}
return Collections.unmodifiableSet(fileTransferParts);
@@ -319,7 +327,7 @@
return;
}
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.deleteFileTransfer(fileTransferPart.getId()));
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index 5df929b..36bb78a 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -20,13 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import com.android.ims.RcsTypeIdPair;
-
-import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
@@ -35,23 +31,14 @@
*
* @hide
*/
-public final class RcsMessageQueryResult implements Parcelable {
- // The token to continue the query to get the next batch of results
- private RcsQueryContinuationToken mContinuationToken;
- // The message type and message ID pairs for all the messages in this query result
- private List<RcsTypeIdPair> mMessageTypeIdPairs;
+public final class RcsMessageQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
+ private final RcsMessageQueryResultParcelable mRcsMessageQueryResultParcelable;
- /**
- * Internal constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
- * to create query results
- *
- * @hide
- */
- public RcsMessageQueryResult(
- RcsQueryContinuationToken continuationToken,
- List<RcsTypeIdPair> messageTypeIdPairs) {
- mContinuationToken = continuationToken;
- mMessageTypeIdPairs = messageTypeIdPairs;
+ RcsMessageQueryResult(RcsControllerCall rcsControllerCall,
+ RcsMessageQueryResultParcelable rcsMessageQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
+ mRcsMessageQueryResultParcelable = rcsMessageQueryResultParcelable;
}
/**
@@ -61,7 +48,7 @@
*/
@Nullable
public RcsQueryContinuationToken getContinuationToken() {
- return mContinuationToken;
+ return mRcsMessageQueryResultParcelable.mContinuationToken;
}
/**
@@ -71,45 +58,10 @@
*/
@NonNull
public List<RcsMessage> getMessages() {
- List<RcsMessage> messages = new ArrayList<>();
- for (RcsTypeIdPair typeIdPair : mMessageTypeIdPairs) {
- if (typeIdPair.getType() == MESSAGE_TYPE_INCOMING) {
- messages.add(new RcsIncomingMessage(typeIdPair.getId()));
- } else {
- messages.add(new RcsOutgoingMessage(typeIdPair.getId()));
- }
- }
-
- return messages;
- }
-
- private RcsMessageQueryResult(Parcel in) {
- mContinuationToken = in.readParcelable(
- RcsQueryContinuationToken.class.getClassLoader());
- in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
- }
-
- public static final @android.annotation.NonNull Creator<RcsMessageQueryResult> CREATOR =
- new Creator<RcsMessageQueryResult>() {
- @Override
- public RcsMessageQueryResult createFromParcel(Parcel in) {
- return new RcsMessageQueryResult(in);
- }
-
- @Override
- public RcsMessageQueryResult[] newArray(int size) {
- return new RcsMessageQueryResult[size];
- }
- };
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mContinuationToken, flags);
- dest.writeTypedList(mMessageTypeIdPairs);
+ return mRcsMessageQueryResultParcelable.mMessageTypeIdPairs.stream()
+ .map(typeIdPair -> typeIdPair.getType() == MESSAGE_TYPE_INCOMING
+ ? new RcsIncomingMessage(mRcsControllerCall, typeIdPair.getId())
+ : new RcsOutgoingMessage(mRcsControllerCall, typeIdPair.getId()))
+ .collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
similarity index 93%
rename from telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
rename to telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
index a73ba50..86928bf 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.aidl
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.aidl
@@ -17,4 +17,4 @@
package android.telephony.ims;
-parcelable RcsMessageQueryResult;
+parcelable RcsMessageQueryResultParcelable;
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
new file mode 100644
index 0000000..4972f9b
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResultParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.ims.RcsTypeIdPair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide - used only for internal communication with the ircs service
+ */
+public class RcsMessageQueryResultParcelable implements Parcelable {
+ // The token to continue the query to get the next batch of results
+ final RcsQueryContinuationToken mContinuationToken;
+ // The message type and message ID pairs for all the messages in this query result
+ final List<RcsTypeIdPair> mMessageTypeIdPairs;
+
+ public RcsMessageQueryResultParcelable(
+ RcsQueryContinuationToken continuationToken,
+ List<RcsTypeIdPair> messageTypeIdPairs) {
+ mContinuationToken = continuationToken;
+ mMessageTypeIdPairs = messageTypeIdPairs;
+ }
+
+ private RcsMessageQueryResultParcelable(Parcel in) {
+ mContinuationToken = in.readParcelable(
+ RcsQueryContinuationToken.class.getClassLoader());
+
+ mMessageTypeIdPairs = new ArrayList<>();
+ in.readTypedList(mMessageTypeIdPairs, RcsTypeIdPair.CREATOR);
+ }
+
+ public static final Creator<RcsMessageQueryResultParcelable> CREATOR =
+ new Creator<RcsMessageQueryResultParcelable>() {
+ @Override
+ public RcsMessageQueryResultParcelable createFromParcel(Parcel in) {
+ return new RcsMessageQueryResultParcelable(in);
+ }
+
+ @Override
+ public RcsMessageQueryResultParcelable[] newArray(int size) {
+ return new RcsMessageQueryResultParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mContinuationToken, flags);
+ dest.writeTypedList(mMessageTypeIdPairs);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 6fcb62b..20b47c0 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.WorkerThread;
+import android.content.Context;
import android.net.Uri;
import java.util.List;
@@ -30,6 +31,12 @@
* @hide
*/
public class RcsMessageStore {
+ RcsControllerCall mRcsControllerCall;
+
+ RcsMessageStore(Context context) {
+ mRcsControllerCall = new RcsControllerCall(context);
+ }
+
/**
* Returns the first chunk of existing {@link RcsThread}s in the common storage.
*
@@ -41,8 +48,8 @@
@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 -> iRcs.getRcsThreads(queryParameters)));
}
/**
@@ -56,8 +63,8 @@
@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 -> iRcs.getRcsThreadsWithToken(continuationToken)));
}
/**
@@ -72,8 +79,8 @@
public RcsParticipantQueryResult getRcsParticipants(
@Nullable RcsParticipantQueryParams queryParameters)
throws RcsMessageStoreException {
- return new RcsParticipantQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters)));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.getParticipants(queryParameters)));
}
/**
@@ -89,22 +96,23 @@
public RcsParticipantQueryResult getRcsParticipants(
@NonNull RcsQueryContinuationToken continuationToken)
throws RcsMessageStoreException {
- return new RcsParticipantQueryResult(
- RcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken)));
+ return new RcsParticipantQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.getParticipantsWithToken(continuationToken)));
}
/**
* 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 -> iRcs.getMessages(queryParams)));
}
/**
@@ -118,7 +126,8 @@
@NonNull
public RcsMessageQueryResult getRcsMessages(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken));
+ return new RcsMessageQueryResult(mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.getMessagesWithToken(continuationToken)));
}
/**
@@ -132,8 +141,8 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@Nullable RcsEventQueryParams queryParams) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(iRcs -> iRcs.getEvents(queryParams))
+ .getRcsEventQueryResult(mRcsControllerCall);
}
/**
@@ -147,14 +156,14 @@
@NonNull
public RcsEventQueryResult getRcsEvents(
@NonNull RcsQueryContinuationToken continuationToken) throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
- .getRcsEventQueryResult();
+ return mRcsControllerCall.call(iRcs -> iRcs.getEventsWithToken(continuationToken))
+ .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 +173,8 @@
*/
@WorkerThread
@NonNull
- public void persistRcsEvent(RcsEvent persistableEvent) throws RcsMessageStoreException {
- persistableEvent.persist();
+ public void persistRcsEvent(RcsEvent rcsEvent) throws RcsMessageStoreException {
+ rcsEvent.persist(mRcsControllerCall);
}
/**
@@ -180,7 +189,8 @@
public Rcs1To1Thread createRcs1To1Thread(@NonNull RcsParticipant recipient)
throws RcsMessageStoreException {
return new Rcs1To1Thread(
- RcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
+ mRcsControllerCall,
+ mRcsControllerCall.call(iRcs -> iRcs.createRcs1To1Thread(recipient.getId())));
}
/**
@@ -202,8 +212,11 @@
}
int[] finalRecipientIds = recipientIds;
- return new RcsGroupThread(RcsControllerCall.call(
- iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon)));
+
+ int threadId = mRcsControllerCall.call(
+ iRcs -> iRcs.createGroupThread(finalRecipientIds, groupName, groupIcon));
+
+ return new RcsGroupThread(mRcsControllerCall, threadId);
}
/**
@@ -218,7 +231,7 @@
return;
}
- boolean isDeleteSucceeded = RcsControllerCall.call(
+ boolean isDeleteSucceeded = mRcsControllerCall.call(
iRcs -> iRcs.deleteThread(thread.getThreadId(), thread.getThreadType()));
if (!isDeleteSucceeded) {
@@ -237,7 +250,7 @@
@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 -> iRcs.createRcsParticipant(canonicalAddress, alias)));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 1b4bfe5..e81231b 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -27,8 +27,8 @@
* @hide
*/
public class RcsOutgoingMessage extends RcsMessage {
- RcsOutgoingMessage(int id) {
- super(id);
+ RcsOutgoingMessage(RcsControllerCall rcsControllerCall, int id) {
+ super(rcsControllerCall, id);
}
/**
@@ -45,12 +45,13 @@
int[] deliveryParticipants;
List<RcsOutgoingMessageDelivery> messageDeliveries = new ArrayList<>();
- deliveryParticipants = RcsControllerCall.call(
+ deliveryParticipants = mRcsControllerCall.call(
iRcs -> iRcs.getMessageRecipients(mId));
if (deliveryParticipants != null) {
for (Integer deliveryParticipant : deliveryParticipants) {
- messageDeliveries.add(new RcsOutgoingMessageDelivery(deliveryParticipant, mId));
+ messageDeliveries.add(new RcsOutgoingMessageDelivery(
+ mRcsControllerCall, deliveryParticipant, mId));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index 2db49c6..af9a84b 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -25,6 +25,7 @@
* @hide
*/
public class RcsOutgoingMessageDelivery {
+ private final RcsControllerCall mRcsControllerCall;
// The participant that this delivery is intended for
private final int mRecipientId;
// The message this delivery is associated with
@@ -35,7 +36,9 @@
*
* @hide
*/
- RcsOutgoingMessageDelivery(int recipientId, int messageId) {
+ RcsOutgoingMessageDelivery(
+ RcsControllerCall rcsControllerCall, int recipientId, int messageId) {
+ mRcsControllerCall = rcsControllerCall;
mRecipientId = recipientId;
mRcsOutgoingMessageId = messageId;
}
@@ -49,7 +52,7 @@
*/
@WorkerThread
public void setDeliveredTimestamp(long deliveredTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryDeliveredTimestamp(
mRcsOutgoingMessageId, mRecipientId, deliveredTimestamp));
}
@@ -61,7 +64,7 @@
*/
@WorkerThread
public long getDeliveredTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
+ return mRcsControllerCall.call(iRcs -> iRcs.getOutgoingDeliveryDeliveredTimestamp(
mRcsOutgoingMessageId, mRecipientId));
}
@@ -74,7 +77,7 @@
*/
@WorkerThread
public void setSeenTimestamp(long seenTimestamp) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliverySeenTimestamp(
mRcsOutgoingMessageId, mRecipientId, seenTimestamp));
}
@@ -86,7 +89,7 @@
*/
@WorkerThread
public long getSeenTimestamp() throws RcsMessageStoreException {
- return RcsControllerCall.call(
+ return mRcsControllerCall.call(
iRcs -> iRcs.getOutgoingDeliverySeenTimestamp(mRcsOutgoingMessageId, mRecipientId));
}
@@ -99,7 +102,7 @@
*/
@WorkerThread
public void setStatus(@RcsMessage.RcsMessageStatus int status) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setOutgoingDeliveryStatus(
mRcsOutgoingMessageId, mRecipientId, status));
}
@@ -109,7 +112,7 @@
*/
@WorkerThread
public @RcsMessage.RcsMessageStatus int getStatus() throws RcsMessageStoreException {
- return RcsControllerCall.call(
+ return mRcsControllerCall.call(
iRcs -> iRcs.getOutgoingDeliveryStatus(mRcsOutgoingMessageId, mRecipientId));
}
@@ -118,7 +121,7 @@
*/
@NonNull
public RcsParticipant getRecipient() {
- return new RcsParticipant(mRecipientId);
+ return new RcsParticipant(mRcsControllerCall, mRecipientId);
}
/**
@@ -126,6 +129,6 @@
*/
@NonNull
public RcsOutgoingMessage getMessage() {
- return new RcsOutgoingMessage(mRcsOutgoingMessageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, mRcsOutgoingMessageId);
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index bcf134a..9ea55ba 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -24,8 +24,9 @@
* @hide
*/
public class RcsParticipant {
+ private final RcsControllerCall mRcsControllerCall;
// The row ID of this participant in the database
- private int mId;
+ private final int mId;
/**
* Constructor for {@link com.android.internal.telephony.ims.RcsMessageStoreController}
@@ -33,7 +34,8 @@
*
* @hide
*/
- public RcsParticipant(int id) {
+ public RcsParticipant(RcsControllerCall rcsControllerCall, int id) {
+ mRcsControllerCall = rcsControllerCall;
mId = id;
}
@@ -45,7 +47,7 @@
@Nullable
@WorkerThread
public String getCanonicalAddress() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantCanonicalAddress(mId));
}
/**
@@ -57,7 +59,7 @@
@Nullable
@WorkerThread
public String getAlias() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantAlias(mId));
}
/**
@@ -70,7 +72,7 @@
*/
@WorkerThread
public void setAlias(String alias) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
+ mRcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantAlias(mId, alias));
}
/**
@@ -82,7 +84,7 @@
@Nullable
@WorkerThread
public String getContactId() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getRcsParticipantContactId(mId));
}
/**
@@ -95,7 +97,8 @@
*/
@WorkerThread
public void setContactId(String contactId) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
+ mRcsControllerCall.callWithNoReturn(
+ iRcs -> iRcs.setRcsParticipantContactId(mId, contactId));
}
@Override
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index 61801f3..8d2e8f2 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -69,8 +69,8 @@
* @hide - not meant for public use.
*/
@Override
- public void persist() throws RcsMessageStoreException {
- RcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
+ void persist(RcsControllerCall rcsControllerCall) throws RcsMessageStoreException {
+ rcsControllerCall.call(iRcs -> iRcs.createParticipantAliasChangedEvent(
getTimestamp(), getParticipant().getId(), getNewAlias()));
}
}
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
index b29896c..43b918c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEventDescriptor.java
@@ -41,9 +41,9 @@
@Override
@VisibleForTesting(visibility = PROTECTED)
- public RcsParticipantAliasChangedEvent createRcsEvent() {
+ public RcsParticipantAliasChangedEvent createRcsEvent(RcsControllerCall rcsControllerCall) {
return new RcsParticipantAliasChangedEvent(
- mTimestamp, new RcsParticipant(mParticipantId), mNewAlias);
+ mTimestamp, new RcsParticipant(rcsControllerCall, mParticipantId), mNewAlias);
}
public static final @NonNull Creator<RcsParticipantAliasChangedEventDescriptor> CREATOR =
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 731c94e..0721dfd 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -30,10 +30,13 @@
* @hide
*/
public final class RcsParticipantQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
private final RcsParticipantQueryResultParcelable mRcsParticipantQueryResultParcelable;
RcsParticipantQueryResult(
+ RcsControllerCall rcsControllerCall,
RcsParticipantQueryResultParcelable rcsParticipantQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
mRcsParticipantQueryResultParcelable = rcsParticipantQueryResultParcelable;
}
@@ -55,7 +58,7 @@
@NonNull
public List<RcsParticipant> getParticipants() {
return mRcsParticipantQueryResultParcelable.mParticipantIds.stream()
- .map(RcsParticipant::new)
+ .map(participantId -> new RcsParticipant(mRcsControllerCall, participantId))
.collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index cf1dc76..638b12a 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -33,6 +33,7 @@
public abstract class RcsThread {
/**
* The rcs_participant_thread_id that represents this thread in the database
+ *
* @hide
*/
protected int mThreadId;
@@ -40,8 +41,14 @@
/**
* @hide
*/
- protected RcsThread(int threadId) {
+ protected final RcsControllerCall mRcsControllerCall;
+
+ /**
+ * @hide
+ */
+ protected RcsThread(RcsControllerCall rcsControllerCall, int threadId) {
mThreadId = threadId;
+ mRcsControllerCall = rcsControllerCall;
}
/**
@@ -51,7 +58,7 @@
@WorkerThread
@NonNull
public RcsMessageSnippet getSnippet() throws RcsMessageStoreException {
- return RcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
+ return mRcsControllerCall.call(iRcs -> iRcs.getMessageSnippet(mThreadId));
}
/**
@@ -64,8 +71,9 @@
public RcsIncomingMessage addIncomingMessage(
@NonNull RcsIncomingMessageCreationParams rcsIncomingMessageCreationParams)
throws RcsMessageStoreException {
- return new RcsIncomingMessage(RcsControllerCall.call(iRcs -> iRcs.addIncomingMessage(
- mThreadId, rcsIncomingMessageCreationParams)));
+ int messageId = mRcsControllerCall.call(
+ iRcs -> iRcs.addIncomingMessage(mThreadId, rcsIncomingMessageCreationParams));
+ return new RcsIncomingMessage(mRcsControllerCall, messageId);
}
/**
@@ -78,10 +86,10 @@
public RcsOutgoingMessage addOutgoingMessage(
@NonNull RcsOutgoingMessageCreationParams rcsOutgoingMessageCreationParams)
throws RcsMessageStoreException {
- int messageId = RcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
+ int messageId = mRcsControllerCall.call(iRcs -> iRcs.addOutgoingMessage(
mThreadId, rcsOutgoingMessageCreationParams));
- return new RcsOutgoingMessage(messageId);
+ return new RcsOutgoingMessage(mRcsControllerCall, messageId);
}
/**
@@ -92,7 +100,7 @@
*/
@WorkerThread
public void deleteMessage(@NonNull RcsMessage rcsMessage) throws RcsMessageStoreException {
- RcsControllerCall.callWithNoReturn(
+ mRcsControllerCall.callWithNoReturn(
iRcs -> iRcs.deleteMessage(rcsMessage.getId(), rcsMessage.isIncoming(), mThreadId,
isGroup()));
}
@@ -108,9 +116,10 @@
@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 -> iRcs.getMessages(queryParams)));
}
/**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index c77bdb3..3de25de 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -33,9 +33,12 @@
* @hide
*/
public final class RcsThreadQueryResult {
+ private final RcsControllerCall mRcsControllerCall;
private final RcsThreadQueryResultParcelable mRcsThreadQueryResultParcelable;
- RcsThreadQueryResult(RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+ RcsThreadQueryResult(RcsControllerCall rcsControllerCall,
+ RcsThreadQueryResultParcelable rcsThreadQueryResultParcelable) {
+ mRcsControllerCall = rcsControllerCall;
mRcsThreadQueryResultParcelable = rcsThreadQueryResultParcelable;
}
@@ -58,8 +61,8 @@
public List<RcsThread> getThreads() {
return mRcsThreadQueryResultParcelable.mRcsThreadIds.stream()
.map(typeIdPair -> typeIdPair.getType() == THREAD_TYPE_1_TO_1
- ? new Rcs1To1Thread(typeIdPair.getId())
- : new RcsGroupThread(typeIdPair.getId()))
+ ? new Rcs1To1Thread(mRcsControllerCall, typeIdPair.getId())
+ : new RcsGroupThread(mRcsControllerCall, typeIdPair.getId()))
.collect(Collectors.toList());
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 50dc587..6eb966a 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -23,7 +23,7 @@
import android.telephony.ims.RcsIncomingMessageCreationParams;
import android.telephony.ims.RcsMessageSnippet;
import android.telephony.ims.RcsMessageQueryParams;
-import android.telephony.ims.RcsMessageQueryResult;
+import android.telephony.ims.RcsMessageQueryResultParcelable;
import android.telephony.ims.RcsOutgoingMessageCreationParams;
import android.telephony.ims.RcsParticipantQueryParams;
import android.telephony.ims.RcsParticipantQueryResultParcelable;
@@ -49,9 +49,9 @@
RcsParticipantQueryResultParcelable getParticipantsWithToken(
in RcsQueryContinuationToken continuationToken);
- RcsMessageQueryResult getMessages(in RcsMessageQueryParams queryParams);
+ RcsMessageQueryResultParcelable getMessages(in RcsMessageQueryParams queryParams);
- RcsMessageQueryResult getMessagesWithToken(
+ RcsMessageQueryResultParcelable getMessagesWithToken(
in RcsQueryContinuationToken continuationToken);
RcsEventQueryResultDescriptor getEvents(in RcsEventQueryParams queryParams);
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 6e8d038..bb5c251 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -94,6 +94,7 @@
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 118f5e2..f248893 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -283,4 +283,6 @@
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 d173cc9..71ea881 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1586,7 +1586,7 @@
int getCardIdForDefaultEuicc(int subId, String callingPackage);
/**
- * Gets information about currently inserted UICCs and enabled eUICCs.
+ * Gets information about currently inserted UICCs and eUICCs.
* <p>
* Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
* <p>
@@ -1958,4 +1958,8 @@
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/test-base/api/TEST_MAPPING b/test-base/api/TEST_MAPPING
index 3535954..86e8f76 100644
--- a/test-base/api/TEST_MAPPING
+++ b/test-base/api/TEST_MAPPING
@@ -1,7 +1,7 @@
{
"presubmit": [
{
- "name": "CtsAndroidTestBase27ApiSignatureTestCases"
+ "name": "CtsAndroidTestBase28ApiSignatureTestCases"
}
]
}
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
index 89d32ab..658c3ed 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadIconChangedEventTest.java
@@ -49,9 +49,7 @@
RcsGroupThreadIconChangedEventDescriptor.CREATOR.createFromParcel(parcel);
RcsGroupThreadIconChangedEvent iconChangedEvent =
- iconChangedEventDescriptor.createRcsEvent();
-
-
+ iconChangedEventDescriptor.createRcsEvent(null);
assertThat(iconChangedEvent.getNewIcon()).isEqualTo(newIconUri);
assertThat(iconChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
index 726b9cd..9fe67ad 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadNameChangedEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsGroupThreadNameChangedEvent nameChangedEvent =
- nameChangedEventDescriptor.createRcsEvent();
+ nameChangedEventDescriptor.createRcsEvent(null);
assertThat(nameChangedEvent.getNewName()).isEqualTo(newName);
assertThat(nameChangedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
index a109310..18d5621 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantJoinedEventTest.java
@@ -47,7 +47,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantJoinedEvent participantJoinedEvent =
- participantJoinedEventDescriptor.createRcsEvent();
+ participantJoinedEventDescriptor.createRcsEvent(null);
assertThat(participantJoinedEvent.getJoinedParticipant().getId()).isEqualTo(2);
assertThat(participantJoinedEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
index de2688c..53a6bba 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsGroupThreadParticipantLeftEventTest.java
@@ -48,7 +48,7 @@
.createFromParcel(parcel);
RcsGroupThreadParticipantLeftEvent participantLeftEvent =
- participantLeftEventDescriptor.createRcsEvent();
+ participantLeftEventDescriptor.createRcsEvent(null);
assertThat(participantLeftEvent.getRcsGroupThread().getThreadId()).isEqualTo(1);
assertThat(participantLeftEvent.getLeavingParticipant().getId()).isEqualTo(2);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
index 5724054..dcf68ff 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsParticipantAliasChangedEventTest.java
@@ -47,7 +47,7 @@
.createFromParcel(parcel);
RcsParticipantAliasChangedEvent aliasChangedEvent =
- aliasChangedEventDescriptor.createRcsEvent();
+ aliasChangedEventDescriptor.createRcsEvent(null);
assertThat(aliasChangedEvent.getParticipant().getId()).isEqualTo(mParticipantId);
assertThat(aliasChangedEvent.getNewAlias()).isEqualTo(NEW_ALIAS);
diff --git a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
index beb4f8a..551a228 100644
--- a/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
+++ b/tests/RcsTests/src/com/android/tests/ims/RcsThreadQueryParamsTest.java
@@ -33,7 +33,7 @@
@Test
public void testCanUnparcel() {
- RcsParticipant rcsParticipant = new RcsParticipant(1);
+ RcsParticipant rcsParticipant = new RcsParticipant(null, 1);
RcsThreadQueryParams rcsThreadQueryParams = new RcsThreadQueryParams.Builder()
.setThreadType(THREAD_TYPE_GROUP)
.setParticipant(rcsParticipant)
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 9098f90..1fbb658 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -6,6 +6,7 @@
static_libs: [
"FrameworksNetCommonTests",
"frameworks-base-testutils",
+ "frameworks-net-testutils",
"framework-protos",
"androidx.test.rules",
"mockito-target-minus-junit4",
@@ -63,7 +64,7 @@
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 0a1ac75..07525a6 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 0000000..eed7159f
--- /dev/null
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.RemoteException;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CaptivePortalTest {
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ private static final String TEST_PACKAGE_NAME = "com.google.android.test";
+
+ private final class MyCaptivePortalImpl extends ICaptivePortal.Stub {
+ int mCode = -1;
+ String mPackageName = null;
+
+ @Override
+ public void appResponse(final int response) throws RemoteException {
+ mCode = response;
+ }
+
+ @Override
+ public void logEvent(int eventId, String packageName) throws RemoteException {
+ mCode = eventId;
+ mPackageName = packageName;
+ }
+ }
+
+ private interface TestFunctor {
+ void useCaptivePortal(CaptivePortal o);
+ }
+
+ private MyCaptivePortalImpl runCaptivePortalTest(TestFunctor f) {
+ final MyCaptivePortalImpl cp = new MyCaptivePortalImpl();
+ f.useCaptivePortal(new CaptivePortal(cp.asBinder()));
+ return cp;
+ }
+
+ @Test
+ public void testReportCaptivePortalDismissed() {
+ final MyCaptivePortalImpl result =
+ runCaptivePortalTest(c -> c.reportCaptivePortalDismissed());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_DISMISSED);
+ }
+
+ @Test
+ public void testIgnoreNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.ignoreNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_UNWANTED);
+ }
+
+ @Test
+ public void testUseNetwork() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.useNetwork());
+ assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
+ }
+
+ @Test
+ public void testLogEvent() {
+ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent(
+ MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
+ TEST_PACKAGE_NAME));
+ assertEquals(result.mCode, MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
+ assertEquals(result.mPackageName, TEST_PACKAGE_NAME);
+ }
+}
diff --git a/tests/net/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
similarity index 100%
rename from tests/net/java/android/net/LinkAddressTest.java
rename to 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
similarity index 99%
rename from tests/net/java/android/net/LinkPropertiesTest.java
rename to tests/net/common/java/android/net/LinkPropertiesTest.java
index 4177291..709f5f6 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -868,12 +868,12 @@
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
similarity index 96%
rename from tests/net/java/android/net/NetworkCapabilitiesTest.java
rename to tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index ad76388..6bc7c1b 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_WIFI_P2P;
import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
@@ -585,4 +587,20 @@
nc2.set(nc1); // Overwrites, as opposed to combineCapabilities
assertEquals(nc1, nc2);
}
+
+ @Test
+ public void testGetTransportTypes() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ nc.addTransportType(TRANSPORT_CELLULAR);
+ nc.addTransportType(TRANSPORT_WIFI);
+ nc.addTransportType(TRANSPORT_VPN);
+ nc.addTransportType(TRANSPORT_TEST);
+
+ final int[] transportTypes = nc.getTransportTypes();
+ assertEquals(4, transportTypes.length);
+ assertEquals(TRANSPORT_CELLULAR, transportTypes[0]);
+ assertEquals(TRANSPORT_WIFI, transportTypes[1]);
+ assertEquals(TRANSPORT_VPN, transportTypes[2]);
+ assertEquals(TRANSPORT_TEST, transportTypes[3]);
+ }
}
diff --git a/tests/net/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java
similarity index 94%
rename from tests/net/java/android/net/NetworkTest.java
rename to tests/net/common/java/android/net/NetworkTest.java
index 0bee7cd..bef66b2 100644
--- a/tests/net/java/android/net/NetworkTest.java
+++ b/tests/net/common/java/android/net/NetworkTest.java
@@ -155,4 +155,12 @@
private static <T> void assertNotEqual(T t1, T t2) {
assertFalse(Objects.equals(t1, t2));
}
+
+ @Test
+ public void testGetPrivateDnsBypassingCopy() {
+ final Network copy = mNetwork.getPrivateDnsBypassingCopy();
+ assertEquals(mNetwork.netId, copy.netId);
+ assertNotEqual(copy.netId, copy.getNetIdForResolv());
+ assertNotEqual(mNetwork.getNetIdForResolv(), copy.getNetIdForResolv());
+ }
}
diff --git a/tests/net/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java
similarity index 100%
rename from tests/net/java/android/net/RouteInfoTest.java
rename to 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
similarity index 77%
rename from tests/net/java/android/net/StaticIpConfigurationTest.java
rename to tests/net/common/java/android/net/StaticIpConfigurationTest.java
index 8449ca7..5096be2 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.runner.RunWith;
import java.net.InetAddress;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
@RunWith(AndroidJUnit4.class)
@@ -46,6 +48,7 @@
private static final InetAddress DNS2 = IpAddress("8.8.4.4");
private static final InetAddress DNS3 = IpAddress("4.2.2.2");
private static final String IFACE = "eth0";
+ private static final String FAKE_DOMAINS = "google.com";
private static InetAddress IpAddress(String addr) {
return InetAddress.parseNumericAddress(addr);
@@ -69,7 +72,7 @@
s.dnsServers.add(DNS1);
s.dnsServers.add(DNS2);
s.dnsServers.add(DNS3);
- s.domains = "google.com";
+ s.domains = FAKE_DOMAINS;
return s;
}
@@ -178,8 +181,8 @@
expected.addDnsServer(DNS3);
assertEquals(expected, s.toLinkProperties(IFACE));
- s.domains = "google.com";
- expected.setDomains("google.com");
+ s.domains = FAKE_DOMAINS;
+ expected.setDomains(FAKE_DOMAINS);
assertEquals(expected, s.toLinkProperties(IFACE));
s.gateway = null;
@@ -218,4 +221,53 @@
StaticIpConfiguration s2 = passThroughParcel(s);
assertEquals(s, s2);
}
+
+ @Test
+ public void testBuilder() {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<>();
+ dnsServers.add(DNS1);
+
+ final StaticIpConfiguration s = new StaticIpConfiguration.Builder()
+ .setIpAddress(ADDR)
+ .setGateway(GATEWAY)
+ .setDomains(FAKE_DOMAINS)
+ .setDnsServers(dnsServers)
+ .build();
+
+ assertEquals(s.ipAddress, s.getIpAddress());
+ assertEquals(ADDR, s.getIpAddress());
+ assertEquals(s.gateway, s.getGateway());
+ assertEquals(GATEWAY, s.getGateway());
+ assertEquals(s.domains, s.getDomains());
+ assertEquals(FAKE_DOMAINS, s.getDomains());
+ assertTrue(s.dnsServers.equals(s.getDnsServers()));
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+ }
+
+ @Test
+ public void testAddDnsServers() {
+ final StaticIpConfiguration s = new StaticIpConfiguration((StaticIpConfiguration) null);
+ checkEmpty(s);
+
+ s.addDnsServer(DNS1);
+ assertEquals(1, s.getDnsServers().size());
+ assertEquals(DNS1, s.getDnsServers().get(0));
+
+ s.addDnsServer(DNS2);
+ s.addDnsServer(DNS3);
+ assertEquals(3, s.getDnsServers().size());
+ assertEquals(DNS2, s.getDnsServers().get(1));
+ assertEquals(DNS3, s.getDnsServers().get(2));
+ }
+
+ @Test
+ public void testGetRoutes() {
+ final StaticIpConfiguration s = makeTestObject();
+ final List<RouteInfo> routeInfoList = s.getRoutes(IFACE);
+
+ assertEquals(2, routeInfoList.size());
+ assertEquals(new RouteInfo(ADDR, (InetAddress) null, IFACE), routeInfoList.get(0));
+ assertEquals(new RouteInfo((IpPrefix) null, GATEWAY, IFACE), routeInfoList.get(1));
+ }
}
diff --git a/tests/net/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
similarity index 92%
rename from tests/net/java/android/net/apf/ApfCapabilitiesTest.java
rename to tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
index 75752c3..3ed8a86 100644
--- a/tests/net/java/android/net/apf/ApfCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java
@@ -19,11 +19,10 @@
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 @@
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 0000000..8d055c9
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfProgramEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfProgramEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasFlag(flag: Int) = (this and (1 shl flag)) != 0
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfProgramEvent = ApfProgramEvent.Builder()
+ .setLifetime(1)
+ .setActualLifetime(2)
+ .setFilteredRas(3)
+ .setCurrentRas(4)
+ .setProgramLength(5)
+ .setFlags(true, true)
+ .build()
+
+ assertEquals(1, apfProgramEvent.lifetime)
+ assertEquals(2, apfProgramEvent.actualLifetime)
+ assertEquals(3, apfProgramEvent.filteredRas)
+ assertEquals(4, apfProgramEvent.currentRas)
+ assertEquals(5, apfProgramEvent.programLength)
+ assertEquals(ApfProgramEvent.flagsFor(true, true), apfProgramEvent.flags)
+
+ testParcel(apfProgramEvent, 6)
+ }
+
+ @Test
+ fun testFlagsFor() {
+ var flags = ApfProgramEvent.flagsFor(false, false)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, false)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(false, true)
+ assertFalse(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+
+ flags = ApfProgramEvent.flagsFor(true, true)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_HAS_IPV4_ADDRESS)
+ assertTrue(flags hasFlag ApfProgramEvent.FLAG_MULTICAST_FILTER_ON)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ApfStatsTest.kt b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
new file mode 100644
index 0000000..f8eb40c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ApfStatsTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ApfStatsTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val apfStats = ApfStats.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setReceivedRas(1)
+ .setMatchingRas(2)
+ .setDroppedRas(3)
+ .setZeroLifetimeRas(4)
+ .setParseErrors(5)
+ .setProgramUpdates(6)
+ .setProgramUpdatesAll(7)
+ .setProgramUpdatesAllowingMulticast(8)
+ .setMaxProgramSize(9)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, apfStats.durationMs)
+ assertEquals(1, apfStats.receivedRas)
+ assertEquals(2, apfStats.matchingRas)
+ assertEquals(3, apfStats.droppedRas)
+ assertEquals(4, apfStats.zeroLifetimeRas)
+ assertEquals(5, apfStats.parseErrors)
+ assertEquals(6, apfStats.programUpdates)
+ assertEquals(7, apfStats.programUpdatesAll)
+ assertEquals(8, apfStats.programUpdatesAllowingMulticast)
+ assertEquals(9, apfStats.maxProgramSize)
+
+ testParcel(apfStats, 10)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
new file mode 100644
index 0000000..36e9f8c
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/DhcpClientEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FAKE_MESSAGE = "test"
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class DhcpClientEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testBuilderAndParcel() {
+ val dhcpClientEvent = DhcpClientEvent.Builder()
+ .setMsg(FAKE_MESSAGE)
+ .setDurationMs(Integer.MAX_VALUE)
+ .build()
+
+ assertEquals(FAKE_MESSAGE, dhcpClientEvent.msg)
+ assertEquals(Integer.MAX_VALUE, dhcpClientEvent.durationMs)
+
+ testParcel(dhcpClientEvent, 2)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt b/tests/net/common/java/android/net/metrics/DhcpErrorEventTest.kt
new file mode 100644
index 0000000..e9d5e6d
--- /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 0000000..d4780d3
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpConnectivityLogTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import android.net.ConnectivityMetricsEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.BitUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityLogTest {
+ private static final int FAKE_NET_ID = 100;
+ private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI);
+ private static final long FAKE_TIME_STAMP = System.currentTimeMillis();
+ private static final String FAKE_INTERFACE_NAME = "test";
+ private static final IpReachabilityEvent FAKE_EV =
+ new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+
+ @Mock IIpConnectivityMetrics mMockService;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testLoggingEvents() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ assertTrue(logger.log(FAKE_EV));
+ assertTrue(logger.log(FAKE_TIME_STAMP, FAKE_EV));
+ assertTrue(logger.log(FAKE_NET_ID, FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(new Network(FAKE_NET_ID), FAKE_TRANSPORT_TYPES, FAKE_EV));
+ assertTrue(logger.log(FAKE_INTERFACE_NAME, FAKE_EV));
+ assertTrue(logger.log(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID, TRANSPORT_WIFI,
+ FAKE_INTERFACE_NAME)));
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(6);
+ assertEventsEqual(makeExpectedEvent(got.get(0).timestamp, 0, 0, null), got.get(0));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, 0, 0, null), got.get(1));
+ assertEventsEqual(makeExpectedEvent(got.get(2).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(2));
+ assertEventsEqual(makeExpectedEvent(got.get(3).timestamp, FAKE_NET_ID,
+ TRANSPORT_WIFI, null), got.get(3));
+ assertEventsEqual(makeExpectedEvent(got.get(4).timestamp, 0, 0, FAKE_INTERFACE_NAME),
+ got.get(4));
+ assertEventsEqual(makeExpectedEvent(FAKE_TIME_STAMP, FAKE_NET_ID,
+ TRANSPORT_WIFI, FAKE_INTERFACE_NAME), got.get(5));
+ }
+
+ @Test
+ public void testLoggingEventsWithMultipleCallers() throws Exception {
+ IpConnectivityLog logger = new IpConnectivityLog(mMockService);
+
+ final int nCallers = 10;
+ final int nEvents = 10;
+ for (int n = 0; n < nCallers; n++) {
+ final int i = n;
+ new Thread() {
+ public void run() {
+ for (int j = 0; j < nEvents; j++) {
+ assertTrue(logger.log(makeExpectedEvent(
+ FAKE_TIME_STAMP + i * 100 + j,
+ FAKE_NET_ID + i * 100 + j,
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR,
+ FAKE_INTERFACE_NAME)));
+ }
+ }
+ }.start();
+ }
+
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
+ Collections.sort(got, EVENT_COMPARATOR);
+ Iterator<ConnectivityMetricsEvent> iter = got.iterator();
+ for (int i = 0; i < nCallers; i++) {
+ for (int j = 0; j < nEvents; j++) {
+ final long expectedTimestamp = FAKE_TIME_STAMP + i * 100 + j;
+ final int expectedNetId = FAKE_NET_ID + i * 100 + j;
+ final long expectedTransports =
+ ((i + j) % 2 == 0) ? TRANSPORT_WIFI : TRANSPORT_CELLULAR;
+ assertEventsEqual(makeExpectedEvent(expectedTimestamp, expectedNetId,
+ expectedTransports, FAKE_INTERFACE_NAME), iter.next());
+ }
+ }
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+ ArgumentCaptor<ConnectivityMetricsEvent> captor =
+ ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+ verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
+ return captor.getAllValues();
+ }
+
+ private List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+ return verifyEvents(n, 10);
+ }
+
+
+ private ConnectivityMetricsEvent makeExpectedEvent(long timestamp, int netId, long transports,
+ String ifname) {
+ ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
+ ev.timestamp = timestamp;
+ ev.data = FAKE_EV;
+ ev.netId = netId;
+ ev.transports = transports;
+ ev.ifname = ifname;
+ return ev;
+ }
+
+ /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+ private void assertEventsEqual(ConnectivityMetricsEvent expected,
+ ConnectivityMetricsEvent got) {
+ assertEquals(expected.data, got.data);
+ assertEquals(expected.timestamp, got.timestamp);
+ assertEquals(expected.netId, got.netId);
+ assertEquals(expected.transports, got.transports);
+ assertEquals(expected.ifname, got.ifname);
+ }
+
+ static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
+ Comparator.comparingLong((ev) -> ev.timestamp);
+}
diff --git a/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
new file mode 100644
index 0000000..5144ca5
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpManagerEventTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpManagerEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpManagerEvent.PROVISIONING_OK..IpManagerEvent.ERROR_INTERFACE_NOT_FOUND).forEach {
+ val ipManagerEvent = IpManagerEvent(it, Long.MAX_VALUE)
+ assertEquals(it, ipManagerEvent.eventType)
+ assertEquals(Long.MAX_VALUE, ipManagerEvent.durationMs)
+
+ testParcel(ipManagerEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
new file mode 100644
index 0000000..d76ebf6
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/IpReachabilityEventTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class IpReachabilityEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (IpReachabilityEvent.PROBE..IpReachabilityEvent.PROVISIONING_LOST_ORGANIC).forEach {
+ val ipReachabilityEvent = IpReachabilityEvent(it)
+ assertEquals(it, ipReachabilityEvent.eventType)
+
+ testParcel(ipReachabilityEvent, 1)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/NetworkEventTest.kt b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
new file mode 100644
index 0000000..8b52e81
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/NetworkEventTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ (NetworkEvent.NETWORK_CONNECTED..NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY).forEach {
+ var networkEvent = NetworkEvent(it)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(0, networkEvent.durationMs)
+
+ networkEvent = NetworkEvent(it, Long.MAX_VALUE)
+ assertEquals(it, networkEvent.eventType)
+ assertEquals(Long.MAX_VALUE, networkEvent.durationMs)
+
+ testParcel(networkEvent, 2)
+ }
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/RaEventTest.kt b/tests/net/common/java/android/net/metrics/RaEventTest.kt
new file mode 100644
index 0000000..f38d328
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/RaEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val NO_LIFETIME: Long = -1L
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class RaEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ @Test
+ fun testConstructorAndParcel() {
+ var raEvent = RaEvent.Builder().build()
+ assertEquals(NO_LIFETIME, raEvent.routerLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixValidLifetime)
+ assertEquals(NO_LIFETIME, raEvent.prefixPreferredLifetime)
+ assertEquals(NO_LIFETIME, raEvent.routeInfoLifetime)
+ assertEquals(NO_LIFETIME, raEvent.rdnssLifetime)
+ assertEquals(NO_LIFETIME, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(1)
+ .updatePrefixValidLifetime(2)
+ .updatePrefixPreferredLifetime(3)
+ .updateRouteInfoLifetime(4)
+ .updateRdnssLifetime(5)
+ .updateDnsslLifetime(6)
+ .build()
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ raEvent = RaEvent.Builder()
+ .updateRouterLifetime(Long.MIN_VALUE)
+ .updateRouterLifetime(Long.MAX_VALUE)
+ .build()
+ assertEquals(Long.MIN_VALUE, raEvent.routerLifetime)
+
+ raEvent = RaEvent(1, 2, 3, 4, 5, 6)
+ assertEquals(1, raEvent.routerLifetime)
+ assertEquals(2, raEvent.prefixValidLifetime)
+ assertEquals(3, raEvent.prefixPreferredLifetime)
+ assertEquals(4, raEvent.routeInfoLifetime)
+ assertEquals(5, raEvent.rdnssLifetime)
+ assertEquals(6, raEvent.dnsslLifetime)
+
+ testParcel(raEvent, 6)
+ }
+}
diff --git a/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
new file mode 100644
index 0000000..c0cef8f
--- /dev/null
+++ b/tests/net/common/java/android/net/metrics/ValidationProbeEventTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics
+
+import android.os.Parcelable
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.util.ParcelableTestUtil
+import com.android.internal.util.TestUtils
+import java.lang.reflect.Modifier
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val FIRST_VALIDATION: Int = 1 shl 8
+private const val REVALIDATION: Int = 2 shl 8
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ValidationProbeEventTest {
+ private fun <T: Parcelable> testParcel(obj: T, fieldCount: Int) {
+ ParcelableTestUtil.assertFieldCountEquals(fieldCount, obj::class.java)
+ TestUtils.assertParcelingIsLossless(obj)
+ }
+
+ private infix fun Int.hasType(type: Int) = (type and this) == type
+
+ @Test
+ fun testBuilderAndParcel() {
+ var validationProbeEvent = ValidationProbeEvent.Builder()
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, false).build()
+
+ assertTrue(validationProbeEvent.probeType hasType REVALIDATION)
+
+ validationProbeEvent = ValidationProbeEvent.Builder()
+ .setDurationMs(Long.MAX_VALUE)
+ .setProbeType(ValidationProbeEvent.PROBE_DNS, true)
+ .setReturnCode(ValidationProbeEvent.DNS_SUCCESS)
+ .build()
+
+ assertEquals(Long.MAX_VALUE, validationProbeEvent.durationMs)
+ assertTrue(validationProbeEvent.probeType hasType ValidationProbeEvent.PROBE_DNS)
+ assertTrue(validationProbeEvent.probeType hasType FIRST_VALIDATION)
+ assertEquals(ValidationProbeEvent.DNS_SUCCESS, validationProbeEvent.returnCode)
+
+ testParcel(validationProbeEvent, 3)
+ }
+
+ @Test
+ fun testGetProbeName() {
+ val probeFields = ValidationProbeEvent::class.java.declaredFields.filter {
+ it.type == Int::class.javaPrimitiveType
+ && Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers)
+ && it.name.contains("PROBE")
+ }
+
+ probeFields.forEach {
+ val intValue = it.getInt(null)
+ val stringValue = ValidationProbeEvent.getProbeName(intValue)
+ assertEquals(it.name, stringValue)
+ }
+
+ }
+}
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
index e0b7227..583d3fd 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
@@ -79,7 +79,7 @@
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 27bc13d..2fb8b19 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 21a4988..f9dbdc7 100644
--- a/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
+++ b/tests/net/java/android/net/shared/IpConfigurationParcelableUtilTest.java
@@ -19,7 +19,8 @@
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 @@
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 @@
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 6fad89e..382afe0 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 e3c6c41..37af461 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
@@ -103,6 +105,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -146,6 +149,7 @@
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
+import android.os.Binder;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
@@ -272,6 +276,7 @@
@Mock IDnsResolver mMockDnsResolver;
@Mock INetd mMockNetd;
@Mock NetworkStackClient mNetworkStack;
+ @Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
@@ -357,7 +362,12 @@
public Resources getResources() {
return mResources;
}
- }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+ }
public void waitForIdle(int timeoutMsAsInt) {
long timeoutMs = timeoutMsAsInt;
@@ -557,6 +567,16 @@
protected void preventAutomaticReconnect() {
mPreventReconnectReceived.open();
}
+
+ @Override
+ protected void addKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Add keepalive packet filter.");
+ }
+
+ @Override
+ protected void removeKeepalivePacketFilter(Message msg) {
+ Log.i(TAG, "Remove keepalive packet filter.");
+ }
};
assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
@@ -1232,6 +1252,7 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
+ mockDefaultPackages();
FakeSettingsProvider.clearSettingsProvider();
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1284,7 +1305,24 @@
FakeSettingsProvider.clearSettingsProvider();
}
- private static int transportToLegacyType(int transport) {
+ private void mockDefaultPackages() throws Exception {
+ final String testPackageName = mContext.getPackageName();
+ final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
+ testPackageName, PackageManager.GET_PERMISSIONS);
+ when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
+ new String[] {testPackageName});
+ when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
+ eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ Arrays.asList(new PackageInfo[] {
+ buildPackageInfo(/* SYSTEM */ false, APP1_UID),
+ buildPackageInfo(/* SYSTEM */ false, APP2_UID),
+ buildPackageInfo(/* SYSTEM */ false, VPN_UID)
+ }));
+ }
+
+ private static int transportToLegacyType(int transport) {
switch (transport) {
case TRANSPORT_ETHERNET:
return TYPE_ETHERNET;
@@ -4228,6 +4266,25 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
@Test
- @Ignore
public void testFullyRoutedVpnResultsInInterfaceFilteringRules() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6173,7 +6243,6 @@
}
@Test
- @Ignore
public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6187,7 +6256,6 @@
}
@Test
- @Ignore
public void testLocalIpv4OnlyVpnDoesNotResultInInterfaceFilteringRule()
throws Exception {
LinkProperties lp = new LinkProperties();
@@ -6203,7 +6271,6 @@
}
@Test
- @Ignore
public void testVpnHandoverChangesInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
@@ -6253,7 +6320,6 @@
}
@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 4a35015..6b5a220 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -118,6 +118,7 @@
INetd mMockNetd;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
IpSecService mIpSecService;
+ int mUid = Os.getuid();
@Before
public void setUp() throws Exception {
@@ -665,4 +666,99 @@
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 0000000..f0453694
--- /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 d5b2c87..3a07166 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -21,11 +21,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -59,16 +56,11 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -98,48 +90,6 @@
}
@Test
- public void testLoggingEvents() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- assertTrue(logger.log(1, FAKE_EV));
- assertTrue(logger.log(2, FAKE_EV));
- assertTrue(logger.log(3, FAKE_EV));
-
- List<ConnectivityMetricsEvent> got = verifyEvents(3);
- assertEventsEqual(expectedEvent(1), got.get(0));
- assertEventsEqual(expectedEvent(2), got.get(1));
- assertEventsEqual(expectedEvent(3), got.get(2));
- }
-
- @Test
- public void testLoggingEventsWithMultipleCallers() throws Exception {
- IpConnectivityLog logger = new IpConnectivityLog(mMockService);
-
- final int nCallers = 10;
- final int nEvents = 10;
- for (int n = 0; n < nCallers; n++) {
- final int i = n;
- new Thread() {
- public void run() {
- for (int j = 0; j < nEvents; j++) {
- assertTrue(logger.log(1 + i * 100 + j, FAKE_EV));
- }
- }
- }.start();
- }
-
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
- Collections.sort(got, EVENT_COMPARATOR);
- Iterator<ConnectivityMetricsEvent> iter = got.iterator();
- for (int i = 0; i < nCallers; i++) {
- for (int j = 0; j < nEvents; j++) {
- int expectedTimestamp = 1 + i * 100 + j;
- assertEventsEqual(expectedEvent(expectedTimestamp), iter.next());
- }
- }
- }
-
- @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -653,16 +603,7 @@
return nai;
}
- List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
- ArgumentCaptor<ConnectivityMetricsEvent> captor =
- ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
- verify(mMockService, timeout(timeoutMs).times(n)).logEvent(captor.capture());
- return captor.getAllValues();
- }
- List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
- return verifyEvents(n, 10);
- }
static void verifySerialization(String want, String output) {
try {
@@ -674,28 +615,4 @@
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s).append("\n");
- }
- return b.toString();
- }
-
- static ConnectivityMetricsEvent expectedEvent(int timestamp) {
- ConnectivityMetricsEvent ev = new ConnectivityMetricsEvent();
- ev.timestamp = timestamp;
- ev.data = FAKE_EV;
- return ev;
- }
-
- /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
- static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
- assertEquals(expected.timestamp, got.timestamp);
- assertEquals(expected.data, got.data);
- }
-
- static final Comparator<ConnectivityMetricsEvent> EVENT_COMPARATOR =
- Comparator.comparingLong((ev) -> ev.timestamp);
}
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/net/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index fb84611..a83faf3 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 0000000..d8c502d
--- /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
similarity index 97%
rename from tests/net/java/android/net/shared/ParcelableTestUtil.java
rename to tests/net/util/java/com/android/internal/util/ParcelableTestUtil.java
index 088ea3c..87537b9 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
similarity index 74%
rename from tests/net/java/com/android/internal/util/TestUtils.java
rename to tests/net/util/java/com/android/internal/util/TestUtils.java
index 57cc172..a99cd47 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 @@
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.Parcel;
import android.os.Parcelable;
+import androidx.annotation.NonNull;
+
import java.util.concurrent.Executor;
public final class TestUtils {
@@ -36,7 +37,7 @@
* 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 @@
}
}
- // 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 @@
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 99420de..609e366 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -497,9 +497,9 @@
}
// 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 8ebde75..b4b6ff1 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 @@
{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 @@
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 9fa29f2..adb034a 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -57,7 +57,7 @@
};
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 4c23bd3..2ef8b99 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -705,35 +705,24 @@
}
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 c856cc3..e883c6b 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -29,6 +29,7 @@
FLAG_BLACKLIST = "blacklist"
FLAG_GREYLIST_MAX_O = "greylist-max-o"
FLAG_GREYLIST_MAX_P = "greylist-max-p"
+FLAG_GREYLIST_MAX_Q = "greylist-max-q"
FLAG_CORE_PLATFORM_API = "core-platform-api"
FLAG_PUBLIC_API = "public-api"
FLAG_SYSTEM_API = "system-api"
@@ -41,6 +42,7 @@
FLAG_BLACKLIST,
FLAG_GREYLIST_MAX_O,
FLAG_GREYLIST_MAX_P,
+ FLAG_GREYLIST_MAX_Q,
]
ALL_FLAGS = FLAGS_API_LIST + [
FLAG_CORE_PLATFORM_API,
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Main.java
index edb9a49..828cce7 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.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 @@
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/preload-check/device/src/com/android/preload/check/Initialized.java b/tools/preload-check/device/src/com/android/preload/check/Initialized.java
index b21b5f6..81c074c 100644
--- a/tools/preload-check/device/src/com/android/preload/check/Initialized.java
+++ b/tools/preload-check/device/src/com/android/preload/check/Initialized.java
@@ -16,6 +16,9 @@
package com.android.preload.check;
+/**
+ * Test that the given boot classpath class is initialized.
+ */
public class Initialized {
public static void main(String[] args) throws Exception {
Util.assertInitialized(args[0], null);
diff --git a/tools/preload-check/device/src/com/android/preload/check/IntegrityCheck.java b/tools/preload-check/device/src/com/android/preload/check/IntegrityCheck.java
index 6cc3946..1c1e927 100644
--- a/tools/preload-check/device/src/com/android/preload/check/IntegrityCheck.java
+++ b/tools/preload-check/device/src/com/android/preload/check/IntegrityCheck.java
@@ -16,13 +16,16 @@
package com.android.preload.check;
+/**
+ * Test that a helper class is first seen as uninitialized, then initialized after forced.
+ */
public class IntegrityCheck {
public static void main(String[] args) throws Exception {
ClassLoader loader = IntegrityCheck.class.getClassLoader();
Util.assertNotInitialized("com.android.preload.check.IntegrityCheck$StatusHelper", loader);
- Class<?> klass = Class.forName("com.android.preload.check.IntegrityCheck$StatusHelper",
+ Class.forName("com.android.preload.check.IntegrityCheck$StatusHelper",
/* initialize */ true, loader);
Util.assertInitialized("com.android.preload.check.IntegrityCheck$StatusHelper", loader);
@@ -30,6 +33,7 @@
System.out.println("OK");
}
+ @SuppressWarnings("unused")
private static class StatusHelper {
private final static Object defer = new Object();
}
diff --git a/tools/preload-check/device/src/com/android/preload/check/NotInitialized.java b/tools/preload-check/device/src/com/android/preload/check/NotInitialized.java
index d2e98fe..c3d2c77 100644
--- a/tools/preload-check/device/src/com/android/preload/check/NotInitialized.java
+++ b/tools/preload-check/device/src/com/android/preload/check/NotInitialized.java
@@ -16,6 +16,9 @@
package com.android.preload.check;
+/**
+ * Test that the given boot classpath class is not initialized.
+ */
public class NotInitialized {
public static void main(String[] args) throws Exception {
Util.assertNotInitialized(args[0], null);
diff --git a/tools/preload-check/device/src/com/android/preload/check/NotInitializedRegex.java b/tools/preload-check/device/src/com/android/preload/check/NotInitializedRegex.java
new file mode 100644
index 0000000..d942bad
--- /dev/null
+++ b/tools/preload-check/device/src/com/android/preload/check/NotInitializedRegex.java
@@ -0,0 +1,66 @@
+/*
+ * 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.preload.check;
+
+import dalvik.system.DexFile;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Test boot classpath classes that satisfy a given regular expression to be not initialized.
+ * Optionally check that at least one class was matched.
+ */
+public class NotInitializedRegex {
+ /**
+ * First arg (mandatory): regular exception. Second arg (optional): boolean to denote a
+ * required match.
+ */
+ public static void main(String[] args) throws Exception {
+ Matcher m = Pattern.compile(args[0]).matcher("");
+ boolean requiresMatch = args.length > 1 ? Boolean.parseBoolean(args[1]) : false;
+
+ Collection<DexFile> dexFiles = Util.getBootDexFiles();
+ int matched = 0, notMatched = 0;
+ for (DexFile dexFile : dexFiles) {
+ Enumeration<String> entries = dexFile.entries();
+ while (entries.hasMoreElements()) {
+ String entry = entries.nextElement();
+ m.reset(entry);
+ if (m.matches()) {
+ System.out.println(entry + ": match");
+ matched++;
+ check(entry);
+ } else {
+ System.out.println(entry + ": no match");
+ notMatched++;
+ }
+ }
+ }
+ System.out.println("Matched: " + matched + " Not-Matched: " + notMatched);
+ if (requiresMatch && matched == 0) {
+ throw new RuntimeException("Did not find match");
+ }
+ System.out.println("OK");
+ }
+
+ private static void check(String name) {
+ Util.assertNotInitialized(name, null);
+ }
+}
diff --git a/tools/preload-check/device/src/com/android/preload/check/Util.java b/tools/preload-check/device/src/com/android/preload/check/Util.java
index 662f67a..fccea0a0 100644
--- a/tools/preload-check/device/src/com/android/preload/check/Util.java
+++ b/tools/preload-check/device/src/com/android/preload/check/Util.java
@@ -16,7 +16,18 @@
package com.android.preload.check;
+import dalvik.system.DexFile;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
public class Util {
private static Field statusField;
@@ -29,6 +40,51 @@
} catch (Throwable t) {
throw new RuntimeException(t);
}
+ // Reset the framework's kill handler.
+ Thread.setDefaultUncaughtExceptionHandler(null);
+ }
+
+ public static Collection<DexFile> getBootDexFiles() throws Exception {
+ Class<?> vmClassLoaderClass = Class.forName("java.lang.VMClassLoader");
+ Method getResources = vmClassLoaderClass.getDeclaredMethod("getResources", String.class);
+ getResources.setAccessible(true);
+ LinkedList<DexFile> res = new LinkedList<>();
+ for (int i = 1;; i++) {
+ try {
+ String name = "classes" + (i > 1 ? String.valueOf(i) : "") + ".dex";
+ @SuppressWarnings("unchecked")
+ List<URL> urls = (List<URL>) getResources.invoke(null, name);
+ if (urls.isEmpty()) {
+ break;
+ }
+ for (URL url : urls) {
+ // Make temp copy, so we can use public API. Would be nice to use in-memory, but
+ // those are unstable.
+ String tmp = "/data/local/tmp/tmp.dex";
+ try (BufferedInputStream in = new BufferedInputStream(url.openStream());
+ BufferedOutputStream out = new BufferedOutputStream(
+ new FileOutputStream(tmp))) {
+ byte[] buf = new byte[4096];
+ for (;;) {
+ int r = in.read(buf);
+ if (r == -1) {
+ break;
+ }
+ out.write(buf, 0, r);
+ }
+ }
+ try {
+ res.add(new DexFile(tmp));
+ } catch (Exception dexError) {
+ dexError.printStackTrace(System.out);
+ }
+ new File(tmp).delete();
+ }
+ } catch (Exception ignored) {
+ break;
+ }
+ }
+ return res;
}
public static boolean isInitialized(Class<?> klass) throws Exception {
diff --git a/tools/preload-check/src/com/android/preload/check/PreloadCheck.java b/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
index 1fde402..00fd414e3 100644
--- a/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
+++ b/tools/preload-check/src/com/android/preload/check/PreloadCheck.java
@@ -16,7 +16,7 @@
package com.android.preload.check;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -97,6 +97,14 @@
}
}
+ /**
+ * Test the classes ending in NoPreloadHolder are not initialized.
+ */
+ @Test
+ public void testNoPreloadHolder() throws Exception {
+ run("com.android.preload.check.NotInitializedRegex", ".*NoPreloadHolder$", "true");
+ }
+
private void run(String cmd, String... args) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append("app_process ")
@@ -107,7 +115,7 @@
sb.append(' ').append(escape(arg));
}
String res = mTestDevice.executeShellCommand(sb.toString());
- assertEquals(sb.toString(), "OK", res.trim());
+ assertTrue(sb.toString() + "\n===\n" + res, res.trim().endsWith("OK"));
}
private static String escape(String input) {
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 49eee07..dc18b8d 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -219,6 +219,14 @@
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 e0ea2077..8e4cb9f 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -48,6 +48,7 @@
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 @@
} // 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 73a0fe1..43b79cc 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -27,6 +27,11 @@
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_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 @@
}
// 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 @@
}
}
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 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 @@
// 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 @@
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 @@
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 @@
}
}
}
+}
+
+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)
{
@@ -1319,10 +1750,10 @@
fprintf(out, "\n");
// Print registration function
- fprintf(out, "int register_android_util_StatsLog(JNIEnv* env) {\n");
+ fprintf(out, "int register_android_util_StatsLogInternal(JNIEnv* env) {\n");
fprintf(out, " return RegisterMethodsOrDie(\n");
fprintf(out, " env,\n");
- fprintf(out, " \"android/util/StatsLog\",\n");
+ fprintf(out, " \"android/util/StatsLogInternal\",\n");
fprintf(out, " gRegisterMethods, NELEM(gRegisterMethods));\n");
fprintf(out, "}\n");
@@ -1346,7 +1777,11 @@
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 @@
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 @@
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 @@
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 @@
fclose(out);
}
- return 0;
+ return errorCount;
}
}
diff --git a/wifi/tests/runtests.sh b/wifi/tests/runtests.sh
index 4e52b8f..9eb9a92 100755
--- a/wifi/tests/runtests.sh
+++ b/wifi/tests/runtests.sh
@@ -19,7 +19,8 @@
adb root
adb wait-for-device
-adb install -r -g "$OUT/data/app/FrameworksWifiApiTests/FrameworksWifiApiTests.apk"
+TARGET_ARCH=$($ANDROID_BUILD_TOP/build/soong/soong_ui.bash --dumpvar-mode TARGET_ARCH)
+adb install -r -g "$OUT/testcases/FrameworksWifiApiTests/$TARGET_ARCH/FrameworksWifiApiTests.apk"
adb shell am instrument --no-hidden-api-checks -w "$@" \
'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'