1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.policy; 18 19 import android.app.ActivityManager; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentName; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.net.ConnectivityManager; 27 import android.net.wifi.WifiManager; 28 import android.os.SystemProperties; 29 import android.os.UserHandle; 30 import android.provider.Settings; 31 import android.util.Log; 32 33 import java.util.ArrayList; 34 35 public class HotspotControllerImpl implements HotspotController { 36 37 private static final String TAG = "HotspotController"; 38 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 39 // Keep these in sync with Settings TetherService.java 40 public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType"; 41 public static final String EXTRA_SET_ALARM = "extraSetAlarm"; 42 public static final String EXTRA_RUN_PROVISION = "extraRunProvision"; 43 public static final String EXTRA_ENABLE_WIFI_TETHER = "extraEnableWifiTether"; 44 // Keep this in sync with Settings TetherSettings.java 45 public static final int WIFI_TETHERING = 0; 46 47 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 48 private final Receiver mReceiver = new Receiver(); 49 private final Context mContext; 50 private final WifiManager mWifiManager; 51 private final ConnectivityManager mConnectivityManager; 52 53 public HotspotControllerImpl(Context context) { 54 mContext = context; 55 mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 56 mConnectivityManager = (ConnectivityManager) 57 mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 58 } 59 60 public void addCallback(Callback callback) { 61 if (callback == null || mCallbacks.contains(callback)) return; 62 if (DEBUG) Log.d(TAG, "addCallback " + callback); 63 mCallbacks.add(callback); 64 mReceiver.setListening(!mCallbacks.isEmpty()); 65 } 66 67 public void removeCallback(Callback callback) { 68 if (callback == null) return; 69 if (DEBUG) Log.d(TAG, "removeCallback " + callback); 70 mCallbacks.remove(callback); 71 mReceiver.setListening(!mCallbacks.isEmpty()); 72 } 73 74 @Override 75 public boolean isHotspotEnabled() { 76 return mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED; 77 } 78 79 @Override 80 public boolean isHotspotSupported() { 81 final boolean isSecondaryUser = ActivityManager.getCurrentUser() != UserHandle.USER_OWNER; 82 return !isSecondaryUser && mConnectivityManager.isTetheringSupported(); 83 } 84 85 @Override 86 public boolean isProvisioningNeeded() { 87 // Keep in sync with other usage of config_mobile_hotspot_provision_app. 88 // TetherSettings#isProvisioningNeeded and 89 // ConnectivityManager#enforceTetherChangePermission 90 String[] provisionApp = mContext.getResources().getStringArray( 91 com.android.internal.R.array.config_mobile_hotspot_provision_app); 92 if (SystemProperties.getBoolean("net.tethering.noprovisioning", false) 93 || provisionApp == null) { 94 return false; 95 } 96 return (provisionApp.length == 2); 97 } 98 99 @Override 100 public void setHotspotEnabled(boolean enabled) { 101 final ContentResolver cr = mContext.getContentResolver(); 102 // Call provisioning app which is called when enabling Tethering from Settings 103 if (enabled) { 104 if (isProvisioningNeeded()) { 105 String tetherEnable = mContext.getResources().getString( 106 com.android.internal.R.string.config_wifi_tether_enable); 107 Intent intent = new Intent(); 108 intent.putExtra(EXTRA_ADD_TETHER_TYPE, WIFI_TETHERING); 109 intent.putExtra(EXTRA_SET_ALARM, true); 110 intent.putExtra(EXTRA_RUN_PROVISION, true); 111 intent.putExtra(EXTRA_ENABLE_WIFI_TETHER, true); 112 intent.setComponent(ComponentName.unflattenFromString(tetherEnable)); 113 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 114 } else { 115 int wifiState = mWifiManager.getWifiState(); 116 if ((wifiState == WifiManager.WIFI_STATE_ENABLING) || 117 (wifiState == WifiManager.WIFI_STATE_ENABLED)) { 118 mWifiManager.setWifiEnabled(false); 119 Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1); 120 } 121 mWifiManager.setWifiApEnabled(null, true); 122 } 123 } else { 124 mWifiManager.setWifiApEnabled(null, false); 125 if (Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0) == 1) { 126 mWifiManager.setWifiEnabled(true); 127 Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0); 128 } 129 } 130 } 131 132 private void fireCallback(boolean isEnabled) { 133 for (Callback callback : mCallbacks) { 134 callback.onHotspotChanged(isEnabled); 135 } 136 } 137 138 private final class Receiver extends BroadcastReceiver { 139 private boolean mRegistered; 140 141 public void setListening(boolean listening) { 142 if (listening && !mRegistered) { 143 if (DEBUG) Log.d(TAG, "Registering receiver"); 144 final IntentFilter filter = new IntentFilter(); 145 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 146 mContext.registerReceiver(this, filter); 147 mRegistered = true; 148 } else if (!listening && mRegistered) { 149 if (DEBUG) Log.d(TAG, "Unregistering receiver"); 150 mContext.unregisterReceiver(this); 151 mRegistered = false; 152 } 153 } 154 155 @Override 156 public void onReceive(Context context, Intent intent) { 157 if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction()); 158 fireCallback(isHotspotEnabled()); 159 } 160 } 161 } 162