summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java74
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java54
4 files changed, 120 insertions, 18 deletions
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 001e09406e3a..42f80109e045 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.os.UserManager;
import android.service.quicksettings.Tile;
+import android.util.Log;
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -200,6 +201,14 @@ public class HotspotTile extends QSTileImpl<BooleanState> {
mCallbackInfo.numConnectedDevices = numDevices;
refreshState(mCallbackInfo);
}
+
+ @Override
+ public void onHotspotAvailabilityChanged(boolean available) {
+ if (!available) {
+ Log.d(TAG, "Tile removed. Hotspot no longer available");
+ mHost.removeTile(getTileSpec());
+ }
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 830b50e35490..8231f8b3a09b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -30,5 +30,6 @@ public interface HotspotController extends CallbackController<Callback>, Dumpabl
interface Callback {
void onHotspotChanged(boolean enabled, int numDevices);
+ default void onHotspotAvailabilityChanged(boolean available) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index df9c3f4d6e26..d0904049d85a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy;
import android.app.ActivityManager;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.TetheringManager;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -26,6 +27,8 @@ import android.os.HandlerExecutor;
import android.os.UserManager;
import android.util.Log;
+import com.android.internal.util.ConcurrentUtils;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import java.io.FileDescriptor;
@@ -46,36 +49,63 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
- private final ConnectivityManager mConnectivityManager;
+ private final TetheringManager mTetheringManager;
private final WifiManager mWifiManager;
private final Handler mMainHandler;
private final Context mContext;
private int mHotspotState;
private volatile int mNumConnectedDevices;
+ private volatile boolean mIsTetheringSupported;
+ private volatile boolean mHasTetherableWifiRegexs;
private boolean mWaitingForTerminalState;
+ private TetheringManager.TetheringEventCallback mTetheringCallback =
+ new TetheringManager.TetheringEventCallback() {
+ @Override
+ public void onTetheringSupported(boolean supported) {
+ super.onTetheringSupported(supported);
+ if (mIsTetheringSupported != supported) {
+ mIsTetheringSupported = supported;
+ fireHotspotAvailabilityChanged();
+ }
+ }
+
+ @Override
+ public void onTetherableInterfaceRegexpsChanged(
+ TetheringManager.TetheringInterfaceRegexps reg) {
+ super.onTetherableInterfaceRegexpsChanged(reg);
+ final boolean newValue = reg.getTetherableWifiRegexs().size() != 0;
+ if (mHasTetherableWifiRegexs != newValue) {
+ mHasTetherableWifiRegexs = newValue;
+ fireHotspotAvailabilityChanged();
+ }
+ }
+ };
+
/**
* Controller used to retrieve information related to a hotspot.
*/
@Inject
- public HotspotControllerImpl(Context context, @Main Handler mainHandler) {
+ public HotspotControllerImpl(Context context, @Main Handler mainHandler,
+ @Background Handler backgroundHandler) {
mContext = context;
- mConnectivityManager =
- (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mTetheringManager = context.getSystemService(TetheringManager.class);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mMainHandler = mainHandler;
+ mTetheringManager.registerTetheringEventCallback(
+ new HandlerExecutor(backgroundHandler), mTetheringCallback);
}
@Override
public boolean isHotspotSupported() {
- return mConnectivityManager.isTetheringSupported()
- && mConnectivityManager.getTetherableWifiRegexs().length != 0
+ return mIsTetheringSupported && mHasTetherableWifiRegexs
&& UserManager.get(mContext).isUserAdmin(ActivityManager.getCurrentUser());
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("HotspotController state:");
+ pw.print(" available="); pw.println(isHotspotSupported());
pw.print(" mHotspotState="); pw.println(stateToString(mHotspotState));
pw.print(" mNumConnectedDevices="); pw.println(mNumConnectedDevices);
pw.print(" mWaitingForTerminalState="); pw.println(mWaitingForTerminalState);
@@ -152,17 +182,18 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
if (enabled) {
mWaitingForTerminalState = true;
if (DEBUG) Log.d(TAG, "Starting tethering");
- mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI, false,
- new ConnectivityManager.OnStartTetheringCallback() {
+ mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI,
+ ConcurrentUtils.DIRECT_EXECUTOR,
+ new TetheringManager.StartTetheringCallback() {
@Override
- public void onTetheringFailed() {
+ public void onTetheringFailed(final int result) {
if (DEBUG) Log.d(TAG, "onTetheringFailed");
maybeResetSoftApState();
fireHotspotChangedCallback();
}
});
} else {
- mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
}
}
@@ -177,10 +208,25 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
* (as it can be blocked).
*/
private void fireHotspotChangedCallback() {
+ List<Callback> list;
synchronized (mCallbacks) {
- for (Callback callback : mCallbacks) {
- callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices);
- }
+ list = new ArrayList<>(mCallbacks);
+ }
+ for (Callback callback : list) {
+ callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices);
+ }
+ }
+
+ /**
+ * Sends a hotspot available changed callback.
+ */
+ private void fireHotspotAvailabilityChanged() {
+ List<Callback> list;
+ synchronized (mCallbacks) {
+ list = new ArrayList<>(mCallbacks);
+ }
+ for (Callback callback : list) {
+ callback.onHotspotAvailabilityChanged(isHotspotSupported());
}
}
@@ -206,7 +252,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
switch (mHotspotState) {
case WifiManager.WIFI_AP_STATE_FAILED:
// TODO(b/110697252): must be called to reset soft ap state after failure
- mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
// Fall through
case WifiManager.WIFI_AP_STATE_ENABLED:
case WifiManager.WIFI_AP_STATE_DISABLED:
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
index 631c580a490d..cd91f22bb753 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -24,10 +26,12 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-import android.net.ConnectivityManager;
+import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
+import android.os.UserManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -38,11 +42,14 @@ import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.concurrent.Executor;
@SmallTest
@@ -51,13 +58,19 @@ import java.util.concurrent.Executor;
public class HotspotControllerImplTest extends SysuiTestCase {
@Mock
- private ConnectivityManager mConnectivityManager;
+ private TetheringManager mTetheringManager;
@Mock
private WifiManager mWifiManager;
@Mock
+ private UserManager mUserManager;
+ @Mock
private HotspotController.Callback mCallback1;
@Mock
private HotspotController.Callback mCallback2;
+ @Mock
+ private TetheringManager.TetheringInterfaceRegexps mTetheringInterfaceRegexps;
+ @Captor
+ private ArgumentCaptor<TetheringManager.TetheringEventCallback> mTetheringCallbackCaptor;
private HotspotControllerImpl mController;
private TestableLooper mLooper;
@@ -66,8 +79,13 @@ public class HotspotControllerImplTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mLooper = TestableLooper.get(this);
- mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
mContext.addMockSystemService(WifiManager.class, mWifiManager);
+ mContext.addMockSystemService(TetheringManager.class, mTetheringManager);
+ mContext.addMockSystemService(UserManager.class, mUserManager);
+
+ when(mUserManager.isUserAdmin(anyInt())).thenReturn(true);
+ when(mTetheringInterfaceRegexps.getTetherableWifiRegexs()).thenReturn(
+ Collections.singletonList("test"));
doAnswer((InvocationOnMock invocation) -> {
((WifiManager.SoftApCallback) invocation.getArgument(1))
@@ -76,7 +94,11 @@ public class HotspotControllerImplTest extends SysuiTestCase {
}).when(mWifiManager).registerSoftApCallback(any(Executor.class),
any(WifiManager.SoftApCallback.class));
- mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper()));
+ Handler handler = new Handler(mLooper.getLooper());
+
+ mController = new HotspotControllerImpl(mContext, handler, handler);
+ verify(mTetheringManager)
+ .registerTetheringEventCallback(any(), mTetheringCallbackCaptor.capture());
}
@Test
@@ -117,4 +139,28 @@ public class HotspotControllerImplTest extends SysuiTestCase {
verify(mWifiManager, never()).unregisterSoftApCallback(any());
}
+ @Test
+ public void testDefault_hotspotNotSupported() {
+ assertFalse(mController.isHotspotSupported());
+ }
+
+ @Test
+ public void testHotspotSupported_rightConditions() {
+ mTetheringCallbackCaptor.getValue().onTetheringSupported(true);
+ mTetheringCallbackCaptor.getValue()
+ .onTetherableInterfaceRegexpsChanged(mTetheringInterfaceRegexps);
+
+ assertTrue(mController.isHotspotSupported());
+ }
+
+ @Test
+ public void testHotspotSupported_callbackCalledOnChange() {
+ mController.addCallback(mCallback1);
+ mTetheringCallbackCaptor.getValue().onTetheringSupported(true);
+ mTetheringCallbackCaptor.getValue()
+ .onTetherableInterfaceRegexpsChanged(mTetheringInterfaceRegexps);
+
+ verify(mCallback1).onHotspotAvailabilityChanged(true);
+ }
+
}