1531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti/* 2531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * Copyright (C) 2016 The Android Open Source Project 3531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 4531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License"); 5531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * you may not use this file except in compliance with the License. 6531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * You may obtain a copy of the License at 7531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 8531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * http://www.apache.org/licenses/LICENSE-2.0 9531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 10531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software 11531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS, 12531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * See the License for the specific language governing permissions and 14531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * limitations under the License. 15531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti */ 16531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 17531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittipackage com.android.server.net; 18531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 19531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.content.Context; 20531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.net.ConnectivityManager; 21531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.net.ConnectivityManager.NetworkCallback; 22531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.net.Network; 23531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.net.NetworkRequest; 24531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport android.util.Log; 25531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 26531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport com.android.internal.annotations.GuardedBy; 27531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittiimport com.android.internal.annotations.VisibleForTesting; 28531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 29531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti/** 30531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * A class that pins a process to the first network that satisfies a particular NetworkRequest. 31531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 32531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork() 33531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be 34531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * able to use that network because it's the system default. 35531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 36531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves, 37531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * we try not to set the default network unless they have already done so, and we try not to 38531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * clear the default network unless we set it ourselves. 39531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 40531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * This should maintain behaviour that's compatible with L, which would pin the whole system to 41531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * any wifi network that was created via enableNetwork(..., true) until that network 42531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * disconnected. 43531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 44531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * Note that while this hack allows network traffic to flow, it is quite limited. For example: 45531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 46531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 1. setProcessDefaultNetwork only affects this process, so: 47531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * - Any subprocesses spawned by this process will not be pinned to Wi-Fi. 48531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work 49531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * either, because other apps on the device will not be pinned. 50531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 2. The behaviour of other APIs is not modified. For example: 51531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * - getActiveNetworkInfo will return the system default network, not Wi-Fi. 52531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI. 53531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they 54531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * will be surprised as well. 55531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 56531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * This class is a per-process singleton because the process default network is a per-process 57531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * singleton. 58531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti * 59531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti */ 60531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colittipublic class NetworkPinner extends NetworkCallback { 61531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 62531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti private static final String TAG = NetworkPinner.class.getSimpleName(); 63531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 64531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @VisibleForTesting 65531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti protected static final Object sLock = new Object(); 66531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 67531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @GuardedBy("sLock") 68531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti private static ConnectivityManager sCM; 69531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @GuardedBy("sLock") 70531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti private static Callback sCallback; 71531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @VisibleForTesting 72531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @GuardedBy("sLock") 73531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti protected static Network sNetwork; 74531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 75531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti private static void maybeInitConnectivityManager(Context context) { 76531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is 77531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti // registered? Can we fix this by starting ConnectivityService before WifiService? 78531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (sCM == null) { 79531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti // Getting a ConnectivityManager does not leak the calling context, because it stores 80531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti // the application context and not the calling context. 81531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 82531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (sCM == null) { 83531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti throw new IllegalStateException("Bad luck, ConnectivityService not started."); 84531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 85531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 86531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 87531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 88531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti private static class Callback extends NetworkCallback { 89531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @Override 90531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti public void onAvailable(Network network) { 91531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti synchronized(sLock) { 92531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (this != sCallback) return; 93531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 94531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (sCM.getBoundNetworkForProcess() == null && sNetwork == null) { 95531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCM.bindProcessToNetwork(network); 96531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sNetwork = network; 97531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti Log.d(TAG, "Wifi alternate reality enabled on network " + network); 98531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 99531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sLock.notify(); 100531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 101531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 102531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 103531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti @Override 104531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti public void onLost(Network network) { 105531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti synchronized (sLock) { 106531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (this != sCallback) return; 107531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 108531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (network.equals(sNetwork) && network.equals(sCM.getBoundNetworkForProcess())) { 109531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti unpin(); 110531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti Log.d(TAG, "Wifi alternate reality disabled on network " + network); 111531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 112531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sLock.notify(); 113531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 114531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 115531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 116531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 117531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti public static void pin(Context context, NetworkRequest request) { 118531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti synchronized (sLock) { 119531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (sCallback == null) { 120531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti maybeInitConnectivityManager(context); 121531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCallback = new Callback(); 122531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti try { 123531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCM.registerNetworkCallback(request, sCallback); 124531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } catch (SecurityException e) { 125531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti Log.d(TAG, "Failed to register network callback", e); 126531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCallback = null; 127531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 128531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 129531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 130531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 131531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti 132531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti public static void unpin() { 133531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti synchronized (sLock) { 134531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti if (sCallback != null) { 135531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti try { 136531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCM.bindProcessToNetwork(null); 137531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCM.unregisterNetworkCallback(sCallback); 138531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } catch (SecurityException e) { 139531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti Log.d(TAG, "Failed to unregister network callback", e); 140531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 141531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sCallback = null; 142531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti sNetwork = null; 143531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 144531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 145531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti } 146531a34430072b9296aaeb47d9e7d04326a93fee4Lorenzo Colitti} 147