summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/AndroidManifest.xml7
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml14
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml10
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java)5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java108
10 files changed, 212 insertions, 40 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index deff19c..686f865 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -155,6 +155,13 @@
</intent-filter>
</receiver>
+ <receiver android:name=".qs.tiles.HotspotTile$APChangedReceiver"
+ androidprv:primaryUserOnly="true">
+ <intent-filter>
+ <action android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+ </intent-filter>
+ </receiver>
+
<activity android:name=".usb.UsbStorageActivity"
android:label="@*android:string/usb_storage_activity_title"
android:excludeFromRecents="true">
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
index 7a62212..0a00d14 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_off.xml
@@ -15,16 +15,14 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android" >
<size
- android:width="64dp"
- android:height="64dp"/>
+ android:width="64.0dp"
+ android:height="64.0dp"/>
<viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
<path
- android:fill="#00000000"
- android:stroke="#CCCCCC"
- android:strokeWidth="1.0"
- android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
+ android:fill="#4DFFFFFF"
+ android:pathData="M35.099998,28.500000c0.600000,-1.400000 0.900000,-2.900000 0.900000,-4.500000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-1.600000,0.000000 -3.100000,0.300000 -4.500000,0.900000l3.200000,3.200000c0.400000,-0.100000 0.800000,-0.100000 1.200000,-0.100000c4.400000,0.000000 8.000000,3.600000 8.000000,8.000000c0.000000,0.400000 0.000000,0.800000 -0.100000,1.300000L35.099998,28.500000zM24.000000,8.000000c8.800000,0.000000 16.000000,7.200000 16.000000,16.000000c0.000000,2.700000 -0.700000,5.200000 -1.900000,7.500000l2.900000,2.900000c1.900000,-3.000000 3.000000,-6.600000 3.000000,-10.400000c0.000000,-11.000000 -9.000000,-20.000000 -20.000000,-20.000000c-3.800000,0.000000 -7.400000,1.100000 -10.400000,2.900000l2.900000,2.900000C18.700001,8.700000 21.299999,8.000000 24.000000,8.000000zM6.500000,5.000000L4.000000,7.500000l4.200000,4.200000C5.600000,15.100000 4.000000,19.400000 4.000000,24.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-3.500000 1.100000,-6.800000 3.100000,-9.400000l2.900000,2.900000C12.700000,19.400000 12.000000,21.600000 12.000000,24.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-1.300000 0.300000,-2.500000 0.900000,-3.600000l3.200000,3.200000c0.000000,0.100000 0.000000,0.300000 0.000000,0.400000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c0.100000,0.000000 0.300000,0.000000 0.400000,0.000000l0.000000,0.000000l0.000000,0.000000l15.000000,15.000000l2.500000,-2.500000L8.500000,7.000000L6.500000,5.000000z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
index 3ccdd81..01cb0ab 100644
--- a/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_hotspot_on.xml
@@ -15,14 +15,14 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android" >
<size
- android:width="64dp"
- android:height="64dp"/>
+ android:width="64.0dp"
+ android:height="64.0dp"/>
<viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
<path
android:fill="#FFFFFFFF"
- android:pathData="M12.0,11.0c-1.1,0.0 -2.0,0.9 -2.0,2.0c0.0,1.1 0.9,2.0 2.0,2.0c1.1,0.0 2.0,-0.9 2.0,-2.0C14.0,11.9 13.1,11.0 12.0,11.0zM18.0,13.0c0.0,-3.3 -2.7,-6.0 -6.0,-6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,2.2 1.2,4.1 3.0,5.2l1.0,-1.7c-1.2,-0.7 -2.0,-2.0 -2.0,-3.4c0.0,-2.2 1.8,-4.0 4.0,-4.0s4.0,1.8 4.0,4.0c0.0,1.5 -0.8,2.8 -2.0,3.4l1.0,1.7C16.8,17.1 18.0,15.2 18.0,13.0zM12.0,3.0C6.5,3.0 2.0,7.5 2.0,13.0c0.0,3.7 2.0,6.9 5.0,8.6l1.0,-1.7c-2.4,-1.4 -4.0,-4.0 -4.0,-6.9c0.0,-4.4 3.6,-8.0 8.0,-8.0s8.0,3.6 8.0,8.0c0.0,3.0 -1.6,5.5 -4.0,6.9l1.0,1.7c3.0,-1.7 5.0,-5.0 5.0,-8.6C22.0,7.5 17.5,3.0 12.0,3.0z"/>
+ android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
</vector>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 94fcc23..8b11ef1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -164,5 +164,8 @@
<!-- Volume: time to delay dismissing the volume panel after a click is performed -->
<integer name="volume_panel_dismiss_delay">200</integer>
+
+ <!-- Hotspot tile: number of days to show after feature is used. -->
+ <integer name="days_to_show_hotspot">30</integer>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index d70da2a..93766af 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -35,7 +35,7 @@ import com.android.systemui.statusbar.policy.Listenable;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.VolumeComponent;
@@ -251,7 +251,7 @@ public abstract class QSTile<TState extends State> implements Listenable {
RotationLockController getRotationLockController();
NetworkController getNetworkController();
ZenModeController getZenModeController();
- TetheringController getTetheringController();
+ HotspotController getHotspotController();
CastController getCastController();
FlashlightController getFlashlightController();
KeyguardMonitor getKeyguardMonitor();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index f2ba558..35dfdda 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,45 +16,98 @@
package com.android.systemui.qs.tiles;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
/** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTile<QSTile.State> {
- private static final Intent TETHER_SETTINGS = new Intent()
- .setClassName("com.android.settings", "com.android.settings.TetherSettings");
+public class HotspotTile extends QSTile<QSTile.BooleanState> {
+ private static final String KEY_LAST_USED_DATE = "lastUsedDate";
+ private static final long MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
- // TODO: implement. see com.android.settings.TetherSettings
-
- private final TetheringController mController;
+ private final HotspotController mController;
+ private final KeyguardMonitor mKeyguard;
+ private final Callback mCallback = new Callback();
+ private final long mTimeToShowTile;
public HotspotTile(Host host) {
super(host);
- mController = host.getTetheringController();
+ mController = host.getHotspotController();
+ mKeyguard = host.getKeyguardMonitor();
+
+ mTimeToShowTile = MILLIS_PER_DAY
+ * mContext.getResources().getInteger(R.integer.days_to_show_hotspot);
}
@Override
- protected State newTileState() {
- return new State();
+ protected BooleanState newTileState() {
+ return new BooleanState();
}
@Override
public void setListening(boolean listening) {
-
+ if (listening) {
+ mController.addCallback(mCallback);
+ mKeyguard.addCallback(mCallback);
+ } else {
+ mController.removeCallback(mCallback);
+ mKeyguard.removeCallback(mCallback);
+ }
}
@Override
protected void handleClick() {
- mHost.startSettingsActivity(TETHER_SETTINGS);
+ final boolean isEnabled = (Boolean) mState.value;
+ mController.setHotspotEnabled(!isEnabled);
}
@Override
- protected void handleUpdateState(State state, Object arg) {
- state.visible = mController != null;
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing())
+ && mController.isHotspotSupported() && isHotspotRecentlyUsed();
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
- state.iconId = R.drawable.ic_qs_hotspot_off;
+
+ state.value = mController.isHotspotEnabled();
+ state.iconId = state.visible && state.value ? R.drawable.ic_qs_hotspot_on
+ : R.drawable.ic_qs_hotspot_off;
+ }
+
+ private boolean isHotspotRecentlyUsed() {
+ long lastDay = getSharedPrefs(mContext).getLong(KEY_LAST_USED_DATE, 0);
+ return (System.currentTimeMillis() - lastDay) < mTimeToShowTile;
+ }
+
+ private static SharedPreferences getSharedPrefs(Context context) {
+ return context.getSharedPreferences(context.getPackageName(), 0);
+ }
+
+ private final class Callback implements HotspotController.Callback, KeyguardMonitor.Callback {
+ @Override
+ public void onHotspotChanged(boolean enabled) {
+ refreshState();
+ }
+
+ @Override
+ public void onKeyguardChanged() {
+ refreshState();
+ }
+ };
+
+ /**
+ * This will catch broadcasts for changes in hotspot state so we can show
+ * the hotspot tile for a number of days after use.
+ */
+ public static class APChangedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ long currentTime = System.currentTimeMillis();
+ getSharedPrefs(context).edit().putLong(KEY_LAST_USED_DATE, currentTime).commit();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2f96e3e..a5dee6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -28,7 +28,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
@@ -132,6 +131,7 @@ import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.HotspotControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -205,6 +205,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
BatteryController mBatteryController;
LocationControllerImpl mLocationController;
NetworkControllerImpl mNetworkController;
+ HotspotControllerImpl mHotspotController;
RotationLockControllerImpl mRotationLockController;
UserInfoController mUserInfoController;
ZenModeController mZenModeController;
@@ -705,6 +706,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mLocationController = new LocationControllerImpl(mContext); // will post a notification
mBatteryController = new BatteryController(mContext);
mNetworkController = new NetworkControllerImpl(mContext);
+ mHotspotController = new HotspotControllerImpl(mContext);
mBluetoothController = new BluetoothControllerImpl(mContext);
if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
mRotationLockController = new RotationLockControllerImpl(mContext);
@@ -758,7 +760,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mQSPanel != null) {
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
- mNetworkController, mZenModeController, null /*tethering*/,
+ mNetworkController, mZenModeController, mHotspotController,
mCastController, mFlashlightController,
mUserSwitcherController, mKeyguardMonitor);
mQSPanel.setHost(qsh);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 378b531..c2fd24c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -40,7 +40,7 @@ import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -57,7 +57,7 @@ public class QSTileHost implements QSTile.Host {
private final RotationLockController mRotation;
private final NetworkController mNetwork;
private final ZenModeController mZen;
- private final TetheringController mTethering;
+ private final HotspotController mHotspot;
private final CastController mCast;
private final Looper mLooper;
private final CurrentUserTracker mUserTracker;
@@ -69,7 +69,7 @@ public class QSTileHost implements QSTile.Host {
public QSTileHost(Context context, PhoneStatusBar statusBar,
BluetoothController bluetooth, LocationController location,
RotationLockController rotation, NetworkController network,
- ZenModeController zen, TetheringController tethering,
+ ZenModeController zen, HotspotController hotspot,
CastController cast, FlashlightController flashlight,
UserSwitcherController userSwitcher, KeyguardMonitor keyguard) {
mContext = context;
@@ -79,7 +79,7 @@ public class QSTileHost implements QSTile.Host {
mRotation = rotation;
mNetwork = network;
mZen = zen;
- mTethering = tethering;
+ mHotspot = hotspot;
mCast = cast;
mFlashlight = flashlight;
mUserSwitcherController = userSwitcher;
@@ -167,8 +167,8 @@ public class QSTileHost implements QSTile.Host {
}
@Override
- public TetheringController getTetheringController() {
- return mTethering;
+ public HotspotController getHotspotController() {
+ return mHotspot;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 143ebaa..7ca91a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TetheringController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -16,13 +16,14 @@
package com.android.systemui.statusbar.policy;
-public interface TetheringController {
+public interface HotspotController {
void addCallback(Callback callback);
void removeCallback(Callback callback);
boolean isHotspotEnabled();
boolean isHotspotSupported();
+ void setHotspotEnabled(boolean enabled);
public interface Callback {
- void onHotspotChanged(boolean hotspot);
+ void onHotspotChanged(boolean enabled);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
new file mode 100644
index 0000000..eea8396
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import java.util.ArrayList;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class HotspotControllerImpl implements HotspotController {
+
+ private static final String TAG = "HotspotController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+ private final Receiver mReceiver = new Receiver();
+ private final Context mContext;
+ private final WifiManager mWifiManager;
+ private final ConnectivityManager mConnectivityManager;
+
+ public HotspotControllerImpl(Context context) {
+ mContext = context;
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ mConnectivityManager = (ConnectivityManager)
+ mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ public void addCallback(Callback callback) {
+ if (callback == null || mCallbacks.contains(callback)) return;
+ if (DEBUG) Log.d(TAG, "addCallback " + callback);
+ mCallbacks.add(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ public void removeCallback(Callback callback) {
+ if (callback == null) return;
+ if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+ mCallbacks.remove(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ @Override
+ public boolean isHotspotEnabled() {
+ return mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED;
+ }
+
+ @Override
+ public boolean isHotspotSupported() {
+ final boolean isSecondaryUser = ActivityManager.getCurrentUser() != UserHandle.USER_OWNER;
+ return !isSecondaryUser && mConnectivityManager.isTetheringSupported();
+ }
+
+ @Override
+ public void setHotspotEnabled(boolean enabled) {
+ mWifiManager.setWifiApEnabled(null, enabled);
+ }
+
+ private void fireCallback(boolean isEnabled) {
+ for (Callback callback : mCallbacks) {
+ callback.onHotspotChanged(isEnabled);
+ }
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ private boolean mRegistered;
+
+ public void setListening(boolean listening) {
+ if (listening && !mRegistered) {
+ if (DEBUG) Log.d(TAG, "Registering receiver");
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ mContext.registerReceiver(this, filter);
+ mRegistered = true;
+ } else if (!listening && mRegistered) {
+ if (DEBUG) Log.d(TAG, "Unregistering receiver");
+ mContext.unregisterReceiver(this);
+ mRegistered = false;
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+ fireCallback(isHotspotEnabled());
+ }
+ }
+}