diff options
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); |