From 0c4c806bcd0990fce252a6c6f0a413faf8e197f3 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 24 Sep 2018 13:04:47 -0700 Subject: WifiNetworkFactory: Implement |acceptRequest| The wifi network factory will accept network requests for the following cases: a) Request is for a generic wifi network (legacy mechanism). b) Specific Request from a foreground app. c) Specific Request from a foreground service when we're not already processing another specific request from a foreground app. Also, modified the |needNetworkFor| & |releaseNetworkFor| to store & clear the active network request. Further processing in these methods will be added in further CL. Also, added MatchAllNetworkSpecifier in the capabilities used by WifiNetworkFactory. Bug: 113878056 Test: Unit tests Change-Id: I69a206cffe4e8b6387d2df71526142f89b95c767 --- .../com/android/server/wifi/ClientModeImpl.java | 9 +- .../java/com/android/server/wifi/WifiInjector.java | 4 +- .../android/server/wifi/WifiNetworkFactory.java | 150 +++++++++++++++++++-- 3 files changed, 146 insertions(+), 17 deletions(-) (limited to 'service') diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index d79d37806..ce71f36db 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -38,6 +38,7 @@ import android.net.IpConfiguration; import android.net.KeepalivePacketData; import android.net.LinkProperties; import android.net.MacAddress; +import android.net.MatchAllNetworkSpecifier; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkCapabilities; @@ -807,15 +808,18 @@ public class ClientModeImpl extends StateMachine { // TODO - needs to be a bit more dynamic mDfltNetworkCapabilities = new NetworkCapabilities(mNetworkCapabilitiesFilter); + NetworkCapabilities factoryNetworkCapabilities = + new NetworkCapabilities(mNetworkCapabilitiesFilter); + factoryNetworkCapabilities.setNetworkSpecifier(new MatchAllNetworkSpecifier()); // Make the network factories. mNetworkFactory = mWifiInjector.makeWifiNetworkFactory( - mNetworkCapabilitiesFilter, mWifiConnectivityManager); + factoryNetworkCapabilities, mWifiConnectivityManager); // We can't filter untrusted network in the capabilities filter because a trusted // network would still satisfy a request that accepts untrusted ones. // We need a second network factory for untrusted network requests because we need a // different score filter for these requests. mUntrustedNetworkFactory = mWifiInjector.makeUntrustedWifiNetworkFactory( - mNetworkCapabilitiesFilter, mWifiConnectivityManager); + factoryNetworkCapabilities, mWifiConnectivityManager); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); @@ -1077,6 +1081,7 @@ public class ClientModeImpl extends StateMachine { mWifiConfigManager.enableVerboseLogging(verbose); mSupplicantStateTracker.enableVerboseLogging(verbose); mPasspointManager.enableVerboseLogging(verbose); + mNetworkFactory.enableVerboseLogging(verbose); } private static final String SYSTEM_PROPERTY_LOG_CONTROL_WIFIHAL = "log.tag.WifiHAL"; diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 9c2bf2c80..2da06fd4b 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -546,7 +546,9 @@ public class WifiInjector { public WifiNetworkFactory makeWifiNetworkFactory( NetworkCapabilities nc, WifiConnectivityManager wifiConnectivityManager) { return new WifiNetworkFactory( - mWifiCoreHandlerThread.getLooper(), mContext, nc, wifiConnectivityManager); + mWifiCoreHandlerThread.getLooper(), mContext, nc, + (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE), + wifiConnectivityManager); } /** diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 489601d0d..830ca6557 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -16,10 +16,13 @@ package com.android.server.wifi; +import android.app.ActivityManager; import android.content.Context; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkRequest; +import android.net.NetworkSpecifier; +import android.net.wifi.WifiNetworkSpecifier; import android.os.Looper; import android.util.Log; @@ -32,47 +35,166 @@ import java.io.PrintWriter; public class WifiNetworkFactory extends NetworkFactory { private static final String TAG = "WifiNetworkFactory"; private static final int SCORE_FILTER = 60; - private final WifiConnectivityManager mWifiConnectivityManager; - private int mConnectionReqCount = 0; + private final Context mContext; + private final ActivityManager mActivityManager; + + private int mGenericConnectionReqCount = 0; + NetworkRequest mActiveSpecificNetworkRequest; + // Verbose logging flag. + private boolean mVerboseLoggingEnabled = false; - public WifiNetworkFactory(Looper l, Context c, NetworkCapabilities f, + public WifiNetworkFactory(Looper looper, Context context, NetworkCapabilities nc, + ActivityManager activityManager, WifiConnectivityManager connectivityManager) { - super(l, c, TAG, f); + super(looper, context, TAG, nc); + mContext = context; + mActivityManager = activityManager; mWifiConnectivityManager = connectivityManager; setScoreFilter(SCORE_FILTER); } + /** + * Enable verbose logging. + */ + public void enableVerboseLogging(int verbose) { + mVerboseLoggingEnabled = (verbose > 0); + } + + @Override + public boolean acceptRequest(NetworkRequest networkRequest, int score) { + NetworkSpecifier ns = networkRequest.networkCapabilities.getNetworkSpecifier(); + // Generic wifi request. Always accept. + if (ns == null) { + // Generic wifi request. Always accept. + } else { + // Invalid network specifier. + if (!(ns instanceof WifiNetworkSpecifier)) { + Log.e(TAG, "Invalid network specifier mentioned. Rejecting"); + return false; + } + + WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns; + // Only allow specific wifi network request from foreground app/service. + if (!isRequestFromForegroundAppOrService(wns.requestorUid)) { + Log.e(TAG, "Request not from foreground app or service." + + " Rejecting request from " + wns.requestorUid); + return false; + } + // If there is a pending request, only proceed if the new request is from a foreground + // app. + if (mActiveSpecificNetworkRequest != null + && !isRequestFromForegroundApp(wns.requestorUid)) { + WifiNetworkSpecifier aWns = + (WifiNetworkSpecifier) mActiveSpecificNetworkRequest + .networkCapabilities + .getNetworkSpecifier(); + if (isRequestFromForegroundApp(aWns.requestorUid)) { + Log.e(TAG, "Already processing active request from a foreground app " + + aWns.requestorUid + ". Rejecting request from " + wns.requestorUid); + return false; + } + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Accepted network request with specifier from fg " + + (isRequestFromForegroundApp(wns.requestorUid) ? "app" : "service")); + } + } + if (mVerboseLoggingEnabled) { + Log.v(TAG, "Accepted network request " + networkRequest); + } + return true; + } + @Override protected void needNetworkFor(NetworkRequest networkRequest, int score) { - if (++mConnectionReqCount == 1) { - mWifiConnectivityManager.setTrustedConnectionAllowed(true); + NetworkSpecifier ns = networkRequest.networkCapabilities.getNetworkSpecifier(); + if (ns == null) { + // Generic wifi request. Turn on auto-join if necessary. + if (++mGenericConnectionReqCount == 1) { + mWifiConnectivityManager.setTrustedConnectionAllowed(true); + } + } else { + // Invalid network specifier. + if (!(ns instanceof WifiNetworkSpecifier)) { + Log.e(TAG, "Invalid network specifier mentioned. Rejecting"); + return; + } + // Store the active network request. + mActiveSpecificNetworkRequest = new NetworkRequest(networkRequest); + // TODO (b/113878056): Complete handling. } } @Override protected void releaseNetworkFor(NetworkRequest networkRequest) { - if (mConnectionReqCount == 0) { - Log.e(TAG, "No valid network request to release"); - return; - } - if (--mConnectionReqCount == 0) { - mWifiConnectivityManager.setTrustedConnectionAllowed(false); + NetworkSpecifier ns = networkRequest.networkCapabilities.getNetworkSpecifier(); + if (ns == null) { + // Generic wifi request. Turn off auto-join if necessary. + if (mGenericConnectionReqCount == 0) { + Log.e(TAG, "No valid network request to release"); + return; + } + if (--mGenericConnectionReqCount == 0) { + mWifiConnectivityManager.setTrustedConnectionAllowed(false); + } + } else { + // Invalid network specifier. + if (!(ns instanceof WifiNetworkSpecifier)) { + Log.e(TAG, "Invalid network specifier mentioned. Ingoring"); + return; + } + if (!mActiveSpecificNetworkRequest.equals(networkRequest)) { + Log.e(TAG, "Network specifier does not match the active request. Ignoring"); + return; + } + // Release the active network request. + mActiveSpecificNetworkRequest = null; + // TODO (b/113878056): Complete handling. } } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { super.dump(fd, pw, args); - pw.println(TAG + ": mConnectionReqCount " + mConnectionReqCount); + pw.println(TAG + ": mGenericConnectionReqCount " + mGenericConnectionReqCount); + pw.println(TAG + ": mActiveSpecificNetworkRequest " + mActiveSpecificNetworkRequest); } /** * Check if there is at-least one connection request. */ public boolean hasConnectionRequests() { - return mConnectionReqCount > 0; + return mGenericConnectionReqCount > 0 || mActiveSpecificNetworkRequest != null; + } + + /** + * Check if the request comes from foreground app/service. + */ + private boolean isRequestFromForegroundAppOrService(int requestorUid) { + try { + String requestorPackageName = mContext.getPackageManager().getNameForUid(requestorUid); + return mActivityManager.getPackageImportance(requestorPackageName) + <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; + } catch (SecurityException e) { + Log.e(TAG, "Failed to check the app state", e); + return false; + } + } + + /** + * Check if the request comes from foreground app. + */ + private boolean isRequestFromForegroundApp(int requestorUid) { + try { + String requestorPackageName = mContext.getPackageManager().getNameForUid(requestorUid); + return mActivityManager.getPackageImportance(requestorPackageName) + <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; + } catch (SecurityException e) { + Log.e(TAG, "Failed to check the app state", e); + return false; + } } } -- cgit v1.2.3