Loading core/java/android/net/ConnectivityDiagnosticsManager.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -676,7 +676,8 @@ public class ConnectivityDiagnosticsManager { } } try { try { mService.registerConnectivityDiagnosticsCallback(binder, request); mService.registerConnectivityDiagnosticsCallback( binder, request, mContext.getOpPackageName()); } catch (RemoteException exception) { } catch (RemoteException exception) { exception.rethrowFromSystemServer(); exception.rethrowFromSystemServer(); } } Loading core/java/android/net/IConnectivityManager.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -222,7 +222,7 @@ interface IConnectivityManager boolean isCallerCurrentAlwaysOnVpnLockdownApp(); boolean isCallerCurrentAlwaysOnVpnLockdownApp(); void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, in NetworkRequest request); in NetworkRequest request, String callingPackageName); void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); IBinder startOrGetTestNetworkService(); IBinder startOrGetTestNetworkService(); Loading core/java/android/net/NetworkCapabilities.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -858,8 +858,8 @@ public final class NetworkCapabilities implements Parcelable { * * * <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator. * <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator. * * * <p>An app is granted owner privileges over Networks that it supplies. Owner privileges * <p>An app is granted owner privileges over Networks that it supplies. The owner UID MUST * implicitly include administrator privileges. * always be included in administratorUids. * * * @param administratorUids the UIDs to be set as administrators of this Network. * @param administratorUids the UIDs to be set as administrators of this Network. * @hide * @hide Loading services/core/java/com/android/server/ConnectivityService.java +266 −88 Original line number Original line Diff line number Diff line Loading @@ -48,8 +48,11 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.IPPROTO_UDP; import static java.util.Map.Entry; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.app.BroadcastOptions; import android.app.NotificationManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.PendingIntent; Loading @@ -62,6 +65,7 @@ import android.content.res.Configuration; import android.database.ContentObserver; import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.CaptivePortal; import android.net.ConnectionInfo; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityManager; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; import android.net.IConnectivityDiagnosticsCallback; Loading Loading @@ -130,6 +134,7 @@ import android.os.Message; import android.os.Messenger; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.PowerManager; import android.os.PowerManager; import android.os.Process; import android.os.Process; import android.os.RemoteException; import android.os.RemoteException; Loading Loading @@ -170,6 +175,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.internal.util.MessageUtils; import com.android.internal.util.XmlUtils; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; import com.android.server.am.BatteryStatsService; Loading Loading @@ -492,9 +498,9 @@ public class ConnectivityService extends IConnectivityManager.Stub /** /** * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * been tested. * been tested. * obj = String representing URL that Internet probe was redirect to, if it was redirected. * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor. * arg1 = One of the NETWORK_TESTED_RESULT_* constants. * data = PersistableBundle of extras passed from NetworkMonitor. If {@link * arg2 = NetID. * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null. */ */ private static final int EVENT_NETWORK_TESTED = 41; private static final int EVENT_NETWORK_TESTED = 41; Loading Loading @@ -596,6 +602,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set<String> mWolSupportedInterfaces; private Set<String> mWolSupportedInterfaces; private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager; private final AppOpsManager mAppOpsManager; private final LocationPermissionChecker mLocationPermissionChecker; private KeepaliveTracker mKeepaliveTracker; private KeepaliveTracker mKeepaliveTracker; private NetworkNotificationManager mNotifier; private NetworkNotificationManager mNotifier; Loading Loading @@ -992,6 +1001,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetd = netd; mNetd = netd; mKeyStore = KeyStore.getInstance(); mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mLocationPermissionChecker = new LocationPermissionChecker(mContext); // To ensure uid rules are synchronized with Network Policy, register for // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService Loading Loading @@ -2101,6 +2112,12 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } } private boolean checkNetworkStackPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_STACK, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, Loading Loading @@ -2747,15 +2764,79 @@ public class ConnectivityService extends IConnectivityManager.Stub break; break; } } case EVENT_NETWORK_TESTED: { case EVENT_NETWORK_TESTED: { final NetworkTestedResults results = (NetworkTestedResults) msg.obj; final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(results.mNetId); if (nai == null) break; handleNetworkTested(nai, results.mTestResult, (results.mRedirectUrl == null) ? "" : results.mRedirectUrl); // Invoke ConnectivityReport generation for this Network test event. final Message m = mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, new ConnectivityReportEvent(results.mTimestampMillis, nai)); m.setData(msg.getData()); mConnectivityDiagnosticsHandler.sendMessage(m); break; } case EVENT_PROVISIONING_NOTIFICATION: { final int netId = msg.arg2; final boolean visible = toBool(msg.arg1); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.name()); nai.asyncChannel.sendMessage( NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT); teardownUnneededNetwork(nai); break; } updateCapabilities(oldScore, nai, nai.networkCapabilities); } if (!visible) { // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other // notifications belong to the same network may be cleared unexpectedly. mNotifier.clearNotification(netId, NotificationType.SIGN_IN); mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH); } else { if (nai == null) { loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } if (!nai.networkAgentConfig.provisioningNotificationDisabled) { mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, (PendingIntent) msg.obj, nai.networkAgentConfig.explicitlySelected); } } break; } case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; if (nai == null) break; updatePrivateDns(nai, (PrivateDnsConfig) msg.obj); break; } } return true; } private void handleNetworkTested( @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) { final boolean wasPartial = nai.partialConnectivity; final boolean wasPartial = nai.partialConnectivity; nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); final boolean partialConnectivityChanged = final boolean partialConnectivityChanged = (wasPartial != nai.partialConnectivity); (wasPartial != nai.partialConnectivity); final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean wasValidated = nai.lastValidated; final boolean wasValidated = nai.lastValidated; final boolean wasDefault = isDefaultNetwork(nai); final boolean wasDefault = isDefaultNetwork(nai); // Only show a connected notification if the network is pending validation // Only show a connected notification if the network is pending validation Loading @@ -2766,8 +2847,6 @@ public class ConnectivityService extends IConnectivityManager.Stub showNetworkNotification(nai, NotificationType.LOGGED_IN); showNetworkNotification(nai, NotificationType.LOGGED_IN); } } final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : ""; if (DBG) { if (DBG) { final String logMsg = !TextUtils.isEmpty(redirectUrl) final String logMsg = !TextUtils.isEmpty(redirectUrl) ? " with redirect to " + redirectUrl ? " with redirect to " + redirectUrl Loading Loading @@ -2829,54 +2908,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (wasValidated && !nai.lastValidated) { if (wasValidated && !nai.lastValidated) { handleNetworkUnvalidated(nai); handleNetworkUnvalidated(nai); } } break; } case EVENT_PROVISIONING_NOTIFICATION: { final int netId = msg.arg2; final boolean visible = toBool(msg.arg1); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.name()); nai.asyncChannel.sendMessage( NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT); teardownUnneededNetwork(nai); break; } updateCapabilities(oldScore, nai, nai.networkCapabilities); } if (!visible) { // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other // notifications belong to the same network may be cleared unexpectedly. mNotifier.clearNotification(netId, NotificationType.SIGN_IN); mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH); } else { if (nai == null) { loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } if (!nai.networkAgentConfig.provisioningNotificationDisabled) { mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, (PendingIntent) msg.obj, nai.networkAgentConfig.explicitlySelected); } } break; } case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; updatePrivateDns(nai, (PrivateDnsConfig) msg.obj); break; } } return true; } } private int getCaptivePortalMode() { private int getCaptivePortalMode() { Loading Loading @@ -2927,8 +2958,23 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override @Override public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED, notifyNetworkTestedWithExtras(testResult, redirectUrl, SystemClock.elapsedRealtime(), testResult, mNetId, redirectUrl)); PersistableBundle.EMPTY); } @Override public void notifyNetworkTestedWithExtras( int testResult, @Nullable String redirectUrl, long timestampMillis, @NonNull PersistableBundle extras) { final Message msg = mTrackerHandler.obtainMessage( EVENT_NETWORK_TESTED, new NetworkTestedResults( mNetId, testResult, timestampMillis, redirectUrl)); msg.setData(new Bundle(extras)); mTrackerHandler.sendMessage(msg); } } @Override @Override Loading Loading @@ -7373,7 +7419,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") @GuardedBy("mVpns") private Vpn getVpnIfOwner() { private Vpn getVpnIfOwner() { final int uid = Binder.getCallingUid(); return getVpnIfOwner(Binder.getCallingUid()); } @GuardedBy("mVpns") private Vpn getVpnIfOwner(int uid) { final int user = UserHandle.getUserId(uid); final int user = UserHandle.getUserId(uid); final Vpn vpn = mVpns.get(user); final Vpn vpn = mVpns.get(user); Loading Loading @@ -7485,6 +7535,17 @@ public class ConnectivityService extends IConnectivityManager.Stub */ */ private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; /** * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks * after processing {@link #EVENT_NETWORK_TESTED} events. * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from * NetworkMonitor. * data = PersistableBundle of extras passed from NetworkMonitor. * * <p>See {@link ConnectivityService#EVENT_NETWORK_TESTED}. */ private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; private ConnectivityDiagnosticsHandler(Looper looper) { private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); super(looper); } } Loading @@ -7502,6 +7563,19 @@ public class ConnectivityService extends IConnectivityManager.Stub (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); break; break; } } case EVENT_NETWORK_TESTED: { final ConnectivityReportEvent reportEvent = (ConnectivityReportEvent) msg.obj; // This is safe because {@link // NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} receives a // PersistableBundle and converts it to the Bundle in the incoming Message. If // {@link NetworkMonitorCallbacks#notifyNetworkTested} is called, msg.data will // not be set. This is also safe, as msg.getData() will return an empty Bundle. final PersistableBundle extras = new PersistableBundle(msg.getData()); handleNetworkTestedWithExtras(reportEvent, extras); break; } } } } } } } Loading @@ -7511,12 +7585,16 @@ public class ConnectivityService extends IConnectivityManager.Stub class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { @NonNull private final IConnectivityDiagnosticsCallback mCb; @NonNull private final IConnectivityDiagnosticsCallback mCb; @NonNull private final NetworkRequestInfo mRequestInfo; @NonNull private final NetworkRequestInfo mRequestInfo; @NonNull private final String mCallingPackageName; @VisibleForTesting @VisibleForTesting ConnectivityDiagnosticsCallbackInfo( ConnectivityDiagnosticsCallbackInfo( @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri) { @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri, @NonNull String callingPackageName) { mCb = cb; mCb = cb; mRequestInfo = nri; mRequestInfo = nri; mCallingPackageName = callingPackageName; } } @Override @Override Loading @@ -7526,6 +7604,39 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } } /** * Class used for sending information from {@link * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it. */ private static class NetworkTestedResults { private final int mNetId; private final int mTestResult; private final long mTimestampMillis; @Nullable private final String mRedirectUrl; private NetworkTestedResults( int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) { mNetId = netId; mTestResult = testResult; mTimestampMillis = timestampMillis; mRedirectUrl = redirectUrl; } } /** * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link * ConnectivityDiagnosticsHandler}. */ private static class ConnectivityReportEvent { private final long mTimestampMillis; @NonNull private final NetworkAgentInfo mNai; private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai) { mTimestampMillis = timestampMillis; mNai = nai; } } private void handleRegisterConnectivityDiagnosticsCallback( private void handleRegisterConnectivityDiagnosticsCallback( @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { ensureRunningOnConnectivityServiceThread(); ensureRunningOnConnectivityServiceThread(); Loading Loading @@ -7573,13 +7684,80 @@ public class ConnectivityService extends IConnectivityManager.Stub cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); } } private void handleNetworkTestedWithExtras( @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { final NetworkAgentInfo nai = reportEvent.mNai; final ConnectivityReport report = new ConnectivityReport( reportEvent.mNai.network, reportEvent.mTimestampMillis, nai.linkProperties, nai.networkCapabilities, extras); final List<IConnectivityDiagnosticsCallback> results = getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { try { cb.onConnectivityReport(report); } catch (RemoteException ex) { loge("Error invoking onConnectivityReport", ex); } } } private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>(); for (Entry<IConnectivityDiagnosticsCallback, ConnectivityDiagnosticsCallbackInfo> entry : mConnectivityDiagnosticsCallbacks.entrySet()) { final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue(); final NetworkRequestInfo nri = cbInfo.mRequestInfo; if (nai.satisfies(nri.request)) { if (checkConnectivityDiagnosticsPermissions( nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { results.add(entry.getKey()); } } } return results; } @VisibleForTesting boolean checkConnectivityDiagnosticsPermissions( int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { if (checkNetworkStackPermission(callbackPid, callbackUid)) { return true; } if (!mLocationPermissionChecker.checkLocationPermission( callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { return false; } synchronized (mVpns) { if (getVpnIfOwner(callbackUid) != null) { return true; } } // Administrator UIDs also contains the Owner UID if (nai.networkCapabilities.getAdministratorUids().contains(callbackUid)) { return true; } return false; } @Override @Override public void registerConnectivityDiagnosticsCallback( public void registerConnectivityDiagnosticsCallback( @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) { @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request, @NonNull String callingPackageName) { if (request.legacyType != TYPE_NONE) { if (request.legacyType != TYPE_NONE) { throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." + " Please use NetworkCapabilities instead."); + " Please use NetworkCapabilities instead."); } } mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // and administrator uids to be safe. // and administrator uids to be safe. Loading @@ -7597,7 +7775,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // callback's binder death. // callback's binder death. final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId); final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId); final ConnectivityDiagnosticsCallbackInfo cbInfo = final ConnectivityDiagnosticsCallbackInfo cbInfo = new ConnectivityDiagnosticsCallbackInfo(callback, nri); new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName); mConnectivityDiagnosticsHandler.sendMessage( mConnectivityDiagnosticsHandler.sendMessage( mConnectivityDiagnosticsHandler.obtainMessage( mConnectivityDiagnosticsHandler.obtainMessage( Loading tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java +11 −4 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import android.content.Context; import android.content.Context; import android.os.PersistableBundle; import android.os.PersistableBundle; import androidx.test.InstrumentationRegistry; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; Loading @@ -58,21 +60,26 @@ public class ConnectivityDiagnosticsManagerTest { private static final Executor INLINE_EXECUTOR = x -> x.run(); private static final Executor INLINE_EXECUTOR = x -> x.run(); @Mock private Context mContext; @Mock private IConnectivityManager mService; @Mock private IConnectivityManager mService; @Mock private ConnectivityDiagnosticsCallback mCb; @Mock private ConnectivityDiagnosticsCallback mCb; private Context mContext; private ConnectivityDiagnosticsBinder mBinder; private ConnectivityDiagnosticsBinder mBinder; private ConnectivityDiagnosticsManager mManager; private ConnectivityDiagnosticsManager mManager; private String mPackageName; @Before @Before public void setUp() { public void setUp() { mContext = mock(Context.class); mContext = InstrumentationRegistry.getContext(); mService = mock(IConnectivityManager.class); mService = mock(IConnectivityManager.class); mCb = mock(ConnectivityDiagnosticsCallback.class); mCb = mock(ConnectivityDiagnosticsCallback.class); mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); mManager = new ConnectivityDiagnosticsManager(mContext, mService); mManager = new ConnectivityDiagnosticsManager(mContext, mService); mPackageName = mContext.getOpPackageName(); } } @After @After Loading Loading @@ -271,7 +278,7 @@ public class ConnectivityDiagnosticsManagerTest { mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService).registerConnectivityDiagnosticsCallback( verify(mService).registerConnectivityDiagnosticsCallback( any(ConnectivityDiagnosticsBinder.class), eq(request)); any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } } Loading Loading @@ -302,7 +309,7 @@ public class ConnectivityDiagnosticsManagerTest { // verify that re-registering is successful // verify that re-registering is successful mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService, times(2)).registerConnectivityDiagnosticsCallback( verify(mService, times(2)).registerConnectivityDiagnosticsCallback( any(ConnectivityDiagnosticsBinder.class), eq(request)); any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } } Loading Loading
core/java/android/net/ConnectivityDiagnosticsManager.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -676,7 +676,8 @@ public class ConnectivityDiagnosticsManager { } } try { try { mService.registerConnectivityDiagnosticsCallback(binder, request); mService.registerConnectivityDiagnosticsCallback( binder, request, mContext.getOpPackageName()); } catch (RemoteException exception) { } catch (RemoteException exception) { exception.rethrowFromSystemServer(); exception.rethrowFromSystemServer(); } } Loading
core/java/android/net/IConnectivityManager.aidl +1 −1 Original line number Original line Diff line number Diff line Loading @@ -222,7 +222,7 @@ interface IConnectivityManager boolean isCallerCurrentAlwaysOnVpnLockdownApp(); boolean isCallerCurrentAlwaysOnVpnLockdownApp(); void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, in NetworkRequest request); in NetworkRequest request, String callingPackageName); void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); IBinder startOrGetTestNetworkService(); IBinder startOrGetTestNetworkService(); Loading
core/java/android/net/NetworkCapabilities.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -858,8 +858,8 @@ public final class NetworkCapabilities implements Parcelable { * * * <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator. * <p>In general, user-supplied networks (such as WiFi networks) do not have an administrator. * * * <p>An app is granted owner privileges over Networks that it supplies. Owner privileges * <p>An app is granted owner privileges over Networks that it supplies. The owner UID MUST * implicitly include administrator privileges. * always be included in administratorUids. * * * @param administratorUids the UIDs to be set as administrators of this Network. * @param administratorUids the UIDs to be set as administrators of this Network. * @hide * @hide Loading
services/core/java/com/android/server/ConnectivityService.java +266 −88 Original line number Original line Diff line number Diff line Loading @@ -48,8 +48,11 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.IPPROTO_UDP; import static java.util.Map.Entry; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.app.BroadcastOptions; import android.app.NotificationManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.PendingIntent; Loading @@ -62,6 +65,7 @@ import android.content.res.Configuration; import android.database.ContentObserver; import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.CaptivePortal; import android.net.ConnectionInfo; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityManager; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; import android.net.IConnectivityDiagnosticsCallback; Loading Loading @@ -130,6 +134,7 @@ import android.os.Message; import android.os.Messenger; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.PowerManager; import android.os.PowerManager; import android.os.Process; import android.os.Process; import android.os.RemoteException; import android.os.RemoteException; Loading Loading @@ -170,6 +175,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.internal.util.MessageUtils; import com.android.internal.util.XmlUtils; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; import com.android.server.am.BatteryStatsService; Loading Loading @@ -492,9 +498,9 @@ public class ConnectivityService extends IConnectivityManager.Stub /** /** * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * been tested. * been tested. * obj = String representing URL that Internet probe was redirect to, if it was redirected. * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor. * arg1 = One of the NETWORK_TESTED_RESULT_* constants. * data = PersistableBundle of extras passed from NetworkMonitor. If {@link * arg2 = NetID. * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null. */ */ private static final int EVENT_NETWORK_TESTED = 41; private static final int EVENT_NETWORK_TESTED = 41; Loading Loading @@ -596,6 +602,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set<String> mWolSupportedInterfaces; private Set<String> mWolSupportedInterfaces; private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager; private final AppOpsManager mAppOpsManager; private final LocationPermissionChecker mLocationPermissionChecker; private KeepaliveTracker mKeepaliveTracker; private KeepaliveTracker mKeepaliveTracker; private NetworkNotificationManager mNotifier; private NetworkNotificationManager mNotifier; Loading Loading @@ -992,6 +1001,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetd = netd; mNetd = netd; mKeyStore = KeyStore.getInstance(); mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mLocationPermissionChecker = new LocationPermissionChecker(mContext); // To ensure uid rules are synchronized with Network Policy, register for // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService Loading Loading @@ -2101,6 +2112,12 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } } private boolean checkNetworkStackPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_STACK, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, Loading Loading @@ -2747,15 +2764,79 @@ public class ConnectivityService extends IConnectivityManager.Stub break; break; } } case EVENT_NETWORK_TESTED: { case EVENT_NETWORK_TESTED: { final NetworkTestedResults results = (NetworkTestedResults) msg.obj; final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(results.mNetId); if (nai == null) break; handleNetworkTested(nai, results.mTestResult, (results.mRedirectUrl == null) ? "" : results.mRedirectUrl); // Invoke ConnectivityReport generation for this Network test event. final Message m = mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, new ConnectivityReportEvent(results.mTimestampMillis, nai)); m.setData(msg.getData()); mConnectivityDiagnosticsHandler.sendMessage(m); break; } case EVENT_PROVISIONING_NOTIFICATION: { final int netId = msg.arg2; final boolean visible = toBool(msg.arg1); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.name()); nai.asyncChannel.sendMessage( NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT); teardownUnneededNetwork(nai); break; } updateCapabilities(oldScore, nai, nai.networkCapabilities); } if (!visible) { // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other // notifications belong to the same network may be cleared unexpectedly. mNotifier.clearNotification(netId, NotificationType.SIGN_IN); mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH); } else { if (nai == null) { loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } if (!nai.networkAgentConfig.provisioningNotificationDisabled) { mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, (PendingIntent) msg.obj, nai.networkAgentConfig.explicitlySelected); } } break; } case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; if (nai == null) break; updatePrivateDns(nai, (PrivateDnsConfig) msg.obj); break; } } return true; } private void handleNetworkTested( @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) { final boolean wasPartial = nai.partialConnectivity; final boolean wasPartial = nai.partialConnectivity; nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); final boolean partialConnectivityChanged = final boolean partialConnectivityChanged = (wasPartial != nai.partialConnectivity); (wasPartial != nai.partialConnectivity); final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean wasValidated = nai.lastValidated; final boolean wasValidated = nai.lastValidated; final boolean wasDefault = isDefaultNetwork(nai); final boolean wasDefault = isDefaultNetwork(nai); // Only show a connected notification if the network is pending validation // Only show a connected notification if the network is pending validation Loading @@ -2766,8 +2847,6 @@ public class ConnectivityService extends IConnectivityManager.Stub showNetworkNotification(nai, NotificationType.LOGGED_IN); showNetworkNotification(nai, NotificationType.LOGGED_IN); } } final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : ""; if (DBG) { if (DBG) { final String logMsg = !TextUtils.isEmpty(redirectUrl) final String logMsg = !TextUtils.isEmpty(redirectUrl) ? " with redirect to " + redirectUrl ? " with redirect to " + redirectUrl Loading Loading @@ -2829,54 +2908,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (wasValidated && !nai.lastValidated) { if (wasValidated && !nai.lastValidated) { handleNetworkUnvalidated(nai); handleNetworkUnvalidated(nai); } } break; } case EVENT_PROVISIONING_NOTIFICATION: { final int netId = msg.arg2; final boolean visible = toBool(msg.arg1); final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId); // If captive portal status has changed, update capabilities or disconnect. if (nai != null && (visible != nai.lastCaptivePortalDetected)) { final int oldScore = nai.getCurrentScore(); nai.lastCaptivePortalDetected = visible; nai.everCaptivePortalDetected |= visible; if (nai.lastCaptivePortalDetected && Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) { if (DBG) log("Avoiding captive portal network: " + nai.name()); nai.asyncChannel.sendMessage( NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT); teardownUnneededNetwork(nai); break; } updateCapabilities(oldScore, nai, nai.networkCapabilities); } if (!visible) { // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other // notifications belong to the same network may be cleared unexpectedly. mNotifier.clearNotification(netId, NotificationType.SIGN_IN); mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH); } else { if (nai == null) { loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } if (!nai.networkAgentConfig.provisioningNotificationDisabled) { mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, (PendingIntent) msg.obj, nai.networkAgentConfig.explicitlySelected); } } break; } case EVENT_PRIVATE_DNS_CONFIG_RESOLVED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; updatePrivateDns(nai, (PrivateDnsConfig) msg.obj); break; } } return true; } } private int getCaptivePortalMode() { private int getCaptivePortalMode() { Loading Loading @@ -2927,8 +2958,23 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override @Override public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED, notifyNetworkTestedWithExtras(testResult, redirectUrl, SystemClock.elapsedRealtime(), testResult, mNetId, redirectUrl)); PersistableBundle.EMPTY); } @Override public void notifyNetworkTestedWithExtras( int testResult, @Nullable String redirectUrl, long timestampMillis, @NonNull PersistableBundle extras) { final Message msg = mTrackerHandler.obtainMessage( EVENT_NETWORK_TESTED, new NetworkTestedResults( mNetId, testResult, timestampMillis, redirectUrl)); msg.setData(new Bundle(extras)); mTrackerHandler.sendMessage(msg); } } @Override @Override Loading Loading @@ -7373,7 +7419,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") @GuardedBy("mVpns") private Vpn getVpnIfOwner() { private Vpn getVpnIfOwner() { final int uid = Binder.getCallingUid(); return getVpnIfOwner(Binder.getCallingUid()); } @GuardedBy("mVpns") private Vpn getVpnIfOwner(int uid) { final int user = UserHandle.getUserId(uid); final int user = UserHandle.getUserId(uid); final Vpn vpn = mVpns.get(user); final Vpn vpn = mVpns.get(user); Loading Loading @@ -7485,6 +7535,17 @@ public class ConnectivityService extends IConnectivityManager.Stub */ */ private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; /** * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks * after processing {@link #EVENT_NETWORK_TESTED} events. * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from * NetworkMonitor. * data = PersistableBundle of extras passed from NetworkMonitor. * * <p>See {@link ConnectivityService#EVENT_NETWORK_TESTED}. */ private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; private ConnectivityDiagnosticsHandler(Looper looper) { private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); super(looper); } } Loading @@ -7502,6 +7563,19 @@ public class ConnectivityService extends IConnectivityManager.Stub (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); break; break; } } case EVENT_NETWORK_TESTED: { final ConnectivityReportEvent reportEvent = (ConnectivityReportEvent) msg.obj; // This is safe because {@link // NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} receives a // PersistableBundle and converts it to the Bundle in the incoming Message. If // {@link NetworkMonitorCallbacks#notifyNetworkTested} is called, msg.data will // not be set. This is also safe, as msg.getData() will return an empty Bundle. final PersistableBundle extras = new PersistableBundle(msg.getData()); handleNetworkTestedWithExtras(reportEvent, extras); break; } } } } } } } Loading @@ -7511,12 +7585,16 @@ public class ConnectivityService extends IConnectivityManager.Stub class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { @NonNull private final IConnectivityDiagnosticsCallback mCb; @NonNull private final IConnectivityDiagnosticsCallback mCb; @NonNull private final NetworkRequestInfo mRequestInfo; @NonNull private final NetworkRequestInfo mRequestInfo; @NonNull private final String mCallingPackageName; @VisibleForTesting @VisibleForTesting ConnectivityDiagnosticsCallbackInfo( ConnectivityDiagnosticsCallbackInfo( @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri) { @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri, @NonNull String callingPackageName) { mCb = cb; mCb = cb; mRequestInfo = nri; mRequestInfo = nri; mCallingPackageName = callingPackageName; } } @Override @Override Loading @@ -7526,6 +7604,39 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } } /** * Class used for sending information from {@link * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it. */ private static class NetworkTestedResults { private final int mNetId; private final int mTestResult; private final long mTimestampMillis; @Nullable private final String mRedirectUrl; private NetworkTestedResults( int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) { mNetId = netId; mTestResult = testResult; mTimestampMillis = timestampMillis; mRedirectUrl = redirectUrl; } } /** * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link * ConnectivityDiagnosticsHandler}. */ private static class ConnectivityReportEvent { private final long mTimestampMillis; @NonNull private final NetworkAgentInfo mNai; private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai) { mTimestampMillis = timestampMillis; mNai = nai; } } private void handleRegisterConnectivityDiagnosticsCallback( private void handleRegisterConnectivityDiagnosticsCallback( @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { ensureRunningOnConnectivityServiceThread(); ensureRunningOnConnectivityServiceThread(); Loading Loading @@ -7573,13 +7684,80 @@ public class ConnectivityService extends IConnectivityManager.Stub cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); } } private void handleNetworkTestedWithExtras( @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { final NetworkAgentInfo nai = reportEvent.mNai; final ConnectivityReport report = new ConnectivityReport( reportEvent.mNai.network, reportEvent.mTimestampMillis, nai.linkProperties, nai.networkCapabilities, extras); final List<IConnectivityDiagnosticsCallback> results = getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { try { cb.onConnectivityReport(report); } catch (RemoteException ex) { loge("Error invoking onConnectivityReport", ex); } } } private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>(); for (Entry<IConnectivityDiagnosticsCallback, ConnectivityDiagnosticsCallbackInfo> entry : mConnectivityDiagnosticsCallbacks.entrySet()) { final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue(); final NetworkRequestInfo nri = cbInfo.mRequestInfo; if (nai.satisfies(nri.request)) { if (checkConnectivityDiagnosticsPermissions( nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { results.add(entry.getKey()); } } } return results; } @VisibleForTesting boolean checkConnectivityDiagnosticsPermissions( int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { if (checkNetworkStackPermission(callbackPid, callbackUid)) { return true; } if (!mLocationPermissionChecker.checkLocationPermission( callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { return false; } synchronized (mVpns) { if (getVpnIfOwner(callbackUid) != null) { return true; } } // Administrator UIDs also contains the Owner UID if (nai.networkCapabilities.getAdministratorUids().contains(callbackUid)) { return true; } return false; } @Override @Override public void registerConnectivityDiagnosticsCallback( public void registerConnectivityDiagnosticsCallback( @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) { @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request, @NonNull String callingPackageName) { if (request.legacyType != TYPE_NONE) { if (request.legacyType != TYPE_NONE) { throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." + " Please use NetworkCapabilities instead."); + " Please use NetworkCapabilities instead."); } } mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // and administrator uids to be safe. // and administrator uids to be safe. Loading @@ -7597,7 +7775,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // callback's binder death. // callback's binder death. final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId); final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId); final ConnectivityDiagnosticsCallbackInfo cbInfo = final ConnectivityDiagnosticsCallbackInfo cbInfo = new ConnectivityDiagnosticsCallbackInfo(callback, nri); new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName); mConnectivityDiagnosticsHandler.sendMessage( mConnectivityDiagnosticsHandler.sendMessage( mConnectivityDiagnosticsHandler.obtainMessage( mConnectivityDiagnosticsHandler.obtainMessage( Loading
tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java +11 −4 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import android.content.Context; import android.content.Context; import android.os.PersistableBundle; import android.os.PersistableBundle; import androidx.test.InstrumentationRegistry; import org.junit.After; import org.junit.After; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; Loading @@ -58,21 +60,26 @@ public class ConnectivityDiagnosticsManagerTest { private static final Executor INLINE_EXECUTOR = x -> x.run(); private static final Executor INLINE_EXECUTOR = x -> x.run(); @Mock private Context mContext; @Mock private IConnectivityManager mService; @Mock private IConnectivityManager mService; @Mock private ConnectivityDiagnosticsCallback mCb; @Mock private ConnectivityDiagnosticsCallback mCb; private Context mContext; private ConnectivityDiagnosticsBinder mBinder; private ConnectivityDiagnosticsBinder mBinder; private ConnectivityDiagnosticsManager mManager; private ConnectivityDiagnosticsManager mManager; private String mPackageName; @Before @Before public void setUp() { public void setUp() { mContext = mock(Context.class); mContext = InstrumentationRegistry.getContext(); mService = mock(IConnectivityManager.class); mService = mock(IConnectivityManager.class); mCb = mock(ConnectivityDiagnosticsCallback.class); mCb = mock(ConnectivityDiagnosticsCallback.class); mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); mManager = new ConnectivityDiagnosticsManager(mContext, mService); mManager = new ConnectivityDiagnosticsManager(mContext, mService); mPackageName = mContext.getOpPackageName(); } } @After @After Loading Loading @@ -271,7 +278,7 @@ public class ConnectivityDiagnosticsManagerTest { mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService).registerConnectivityDiagnosticsCallback( verify(mService).registerConnectivityDiagnosticsCallback( any(ConnectivityDiagnosticsBinder.class), eq(request)); any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } } Loading Loading @@ -302,7 +309,7 @@ public class ConnectivityDiagnosticsManagerTest { // verify that re-registering is successful // verify that re-registering is successful mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService, times(2)).registerConnectivityDiagnosticsCallback( verify(mService, times(2)).registerConnectivityDiagnosticsCallback( any(ConnectivityDiagnosticsBinder.class), eq(request)); any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } } Loading