Home | History | Annotate | Download | only in policy
      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