summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/proto/android/server/connectivity/Android.bp2
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java1
-rw-r--r--packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java1
-rw-r--r--proto/Android.bp2
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java9
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java7
-rw-r--r--services/core/java/com/android/server/storage/AppFuseBridge.java12
-rw-r--r--services/core/jni/com_android_server_storage_AppFuseBridge.cpp18
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java2
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java26
10 files changed, 59 insertions, 21 deletions
diff --git a/core/proto/android/server/connectivity/Android.bp b/core/proto/android/server/connectivity/Android.bp
index 413623963851..50c238b96307 100644
--- a/core/proto/android/server/connectivity/Android.bp
+++ b/core/proto/android/server/connectivity/Android.bp
@@ -21,4 +21,6 @@ java_library_static {
"data_stall_event.proto",
],
sdk_version: "system_current",
+ // this is part of updatable modules(NetworkStack) which targets 29(Q)
+ min_sdk_version: "29",
}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 4cc35b42d93a..e24fc2958933 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -1322,6 +1322,7 @@ public class IpServer extends StateMachine {
class UnavailableState extends State {
@Override
public void enter() {
+ mIpNeighborMonitor.stop();
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
sendInterfaceState(STATE_UNAVAILABLE);
}
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 4f8860539158..05cf58ab84ff 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -859,6 +859,7 @@ public class IpServerTest {
verify(mBpfCoordinator).tetherOffloadRuleClear(mIpServer);
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
+ verify(mIpNeighborMonitor).stop();
resetNetdAndBpfCoordinator();
}
diff --git a/proto/Android.bp b/proto/Android.bp
index 65bccbb4aac8..ac1b852abf55 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -26,4 +26,6 @@ java_library_static {
},
srcs: ["src/metrics_constants/metrics_constants.proto"],
sdk_version: "system_current",
+ // this is part of updatable modules(CaptivePortalLogin) which targets 29(Q)
+ min_sdk_version: "29",
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 6e01592c51a0..fd8ac061bbe0 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -442,7 +442,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- new HandlerExecutor(mHandler), this);
+ mHandler.getLooper(), new HandlerExecutor(mHandler), this);
mContentResolver = mContext.getContentResolver();
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
mNetworkStatsSubscriptionsMonitor);
@@ -468,11 +468,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/
@NonNull
public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
- @NonNull Executor executor, @NonNull NetworkStatsService service) {
+ @NonNull Looper looper, @NonNull Executor executor,
+ @NonNull NetworkStatsService service) {
// TODO: Update RatType passively in NSS, instead of querying into the monitor
// when forceUpdateIface.
- return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) ->
- service.handleOnCollapsedRatTypeChanged());
+ return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
+ (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
}
/**
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index dc3c30a18a58..7711c6a21d20 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -20,6 +20,7 @@ import static android.net.NetworkTemplate.getCollapsedRatType;
import android.annotation.NonNull;
import android.content.Context;
+import android.os.Looper;
import android.telephony.Annotation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
@@ -75,9 +76,9 @@ public class NetworkStatsSubscriptionsMonitor extends
@NonNull
private final Executor mExecutor;
- NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor,
- @NonNull Delegate delegate) {
- super();
+ NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Looper looper,
+ @NonNull Executor executor, @NonNull Delegate delegate) {
+ super(looper);
mSubscriptionManager = (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index 9d6a64701e85..b00540fd2a52 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -56,6 +56,15 @@ public class AppFuseBridge implements Runnable {
public ParcelFileDescriptor addBridge(MountScope mountScope)
throws FuseUnavailableMountException, NativeDaemonConnectorException {
+ /*
+ ** Dead Lock between Java lock (AppFuseBridge.java) and Native lock (FuseBridgeLoop.cc)
+ **
+ ** (Thread A) Got Java lock (addBrdige) -> Try to get Native lock (native_add_brdige)
+ ** (Thread B) Got Native lock (FuseBrdigeLoop.start) -> Try to get Java lock (onClosed)
+ **
+ ** Guarantee the lock order (native lock -> java lock) when adding Bridge.
+ */
+ native_lock();
try {
synchronized (this) {
Preconditions.checkArgument(mScopes.indexOfKey(mountScope.mountId) < 0);
@@ -73,6 +82,7 @@ public class AppFuseBridge implements Runnable {
return result;
}
} finally {
+ native_unlock();
IoUtils.closeQuietly(mountScope);
}
}
@@ -159,4 +169,6 @@ public class AppFuseBridge implements Runnable {
private native void native_delete(long loop);
private native void native_start_loop(long loop);
private native int native_add_bridge(long loop, int mountId, int deviceId);
+ private native void native_lock();
+ private native void native_unlock();
}
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
index e51963340ae1..20210abd0ea8 100644
--- a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -123,6 +123,14 @@ jint com_android_server_storage_AppFuseBridge_add_bridge(
return proxyFd[1].release();
}
+void com_android_server_storage_AppFuseBridge_lock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Lock();
+}
+
+void com_android_server_storage_AppFuseBridge_unlock(JNIEnv* env, jobject self) {
+ fuse::FuseBridgeLoop::Unlock();
+}
+
const JNINativeMethod methods[] = {
{
"native_new",
@@ -143,6 +151,16 @@ const JNINativeMethod methods[] = {
"native_add_bridge",
"(JII)I",
reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_add_bridge)
+ },
+ {
+ "native_lock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_lock)
+ },
+ {
+ "native_unlock",
+ "()V",
+ reinterpret_cast<void*>(com_android_server_storage_AppFuseBridge_unlock)
}
};
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 9c0d33fe5a37..1307a849f1eb 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -245,7 +245,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
@Override
public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(
- @NonNull Context context, @NonNull Executor executor,
+ @NonNull Context context, @NonNull Looper looper, @NonNull Executor executor,
@NonNull NetworkStatsService service) {
return mNetworkStatsSubscriptionsMonitor;
diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index 208505369162..c813269744ef 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -17,6 +17,7 @@
package com.android.server.net;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
@@ -29,14 +30,13 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.Context;
-import android.os.Looper;
+import android.os.test.TestLooper;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import com.android.internal.util.CollectionUtils;
-import com.android.server.net.NetworkStatsSubscriptionsMonitor.Delegate;
import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener;
import org.junit.Before;
@@ -64,20 +64,17 @@ public final class NetworkStatsSubscriptionsMonitorTest {
@Mock private PhoneStateListener mPhoneStateListener;
@Mock private SubscriptionManager mSubscriptionManager;
@Mock private TelephonyManager mTelephonyManager;
- @Mock private Delegate mDelegate;
+ @Mock private NetworkStatsSubscriptionsMonitor.Delegate mDelegate;
private final List<Integer> mTestSubList = new ArrayList<>();
private final Executor mExecutor = Executors.newSingleThreadExecutor();
private NetworkStatsSubscriptionsMonitor mMonitor;
+ private TestLooper mTestLooper = new TestLooper();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
@@ -85,7 +82,8 @@ public final class NetworkStatsSubscriptionsMonitorTest {
when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE)))
.thenReturn(mTelephonyManager);
- mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mExecutor, mDelegate);
+ mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mTestLooper.getLooper(),
+ mExecutor, mDelegate);
}
@Test
@@ -117,16 +115,18 @@ public final class NetworkStatsSubscriptionsMonitorTest {
when(serviceState.getDataNetworkType()).thenReturn(type);
final RatTypeListener match = CollectionUtils
.find(listeners, it -> it.getSubId() == subId);
- if (match != null) {
- match.onServiceStateChanged(serviceState);
+ if (match == null) {
+ fail("Could not find listener with subId: " + subId);
}
+ match.onServiceStateChanged(serviceState);
}
private void addTestSub(int subId, String subscriberId) {
// add SubId to TestSubList.
- if (!mTestSubList.contains(subId)) {
- mTestSubList.add(subId);
- }
+ if (mTestSubList.contains(subId)) fail("The subscriber list already contains this ID");
+
+ mTestSubList.add(subId);
+
final int[] subList = convertArrayListToIntArray(mTestSubList);
when(mSubscriptionManager.getActiveAndHiddenSubscriptionIdList()).thenReturn(subList);
when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);