Merge "Context-aware Bluetooth airplane mode"
am: d3a0117720
Change-Id: Ia2e5afa286657e2700a4246ec5d73a5426945d4a
This commit is contained in:
@@ -5398,6 +5398,10 @@
|
|||||||
<!-- Description of media type: presentation file, such as PPT. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
|
<!-- Description of media type: presentation file, such as PPT. The 'extension' variable is the file name extension. [CHAR LIMIT=32] -->
|
||||||
<string name="mime_type_presentation_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> presentation</string>
|
<string name="mime_type_presentation_ext"><xliff:g id="extension" example="PDF">%1$s</xliff:g> presentation</string>
|
||||||
|
|
||||||
|
<!-- Strings for Bluetooth service -->
|
||||||
|
<!-- toast message informing user that Bluetooth stays on after airplane mode is turned on. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="bluetooth_airplane_mode_toast">Bluetooth will stay on during airplane mode</string>
|
||||||
|
|
||||||
<!-- Strings for car -->
|
<!-- Strings for car -->
|
||||||
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
|
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
|
||||||
<string name="car_loading_profile">Loading</string>
|
<string name="car_loading_profile">Loading</string>
|
||||||
|
|||||||
@@ -3803,6 +3803,9 @@
|
|||||||
<java-symbol type="string" name="mime_type_presentation" />
|
<java-symbol type="string" name="mime_type_presentation" />
|
||||||
<java-symbol type="string" name="mime_type_presentation_ext" />
|
<java-symbol type="string" name="mime_type_presentation_ext" />
|
||||||
|
|
||||||
|
<!-- For Bluetooth service -->
|
||||||
|
<java-symbol type="string" name="bluetooth_airplane_mode_toast" />
|
||||||
|
|
||||||
<!-- For high refresh rate displays -->
|
<!-- For high refresh rate displays -->
|
||||||
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
|
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
|
||||||
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
|
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
|
||||||
|
|||||||
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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.server;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothA2dp;
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothHearingAid;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.bluetooth.BluetoothProfile.ServiceListener;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BluetoothAirplaneModeListener handles system airplane mode change callback and checks
|
||||||
|
* whether we need to inform BluetoothManagerService on this change.
|
||||||
|
*
|
||||||
|
* The information of airplane mode turns on would not be passed to the BluetoothManagerService
|
||||||
|
* when Bluetooth is on and Bluetooth is in one of the following situations:
|
||||||
|
* 1. Bluetooth A2DP is connected.
|
||||||
|
* 2. Bluetooth Hearing Aid profile is connected.
|
||||||
|
*/
|
||||||
|
class BluetoothAirplaneModeListener {
|
||||||
|
private static final String TAG = "BluetoothAirplaneModeListener";
|
||||||
|
@VisibleForTesting static final String TOAST_COUNT = "bluetooth_airplane_toast_count";
|
||||||
|
|
||||||
|
private static final int MSG_AIRPLANE_MODE_CHANGED = 0;
|
||||||
|
|
||||||
|
@VisibleForTesting static final int MAX_TOAST_COUNT = 10; // 10 times
|
||||||
|
|
||||||
|
private final BluetoothManagerService mBluetoothManager;
|
||||||
|
private final BluetoothAirplaneModeHandler mHandler;
|
||||||
|
private AirplaneModeHelper mAirplaneHelper;
|
||||||
|
|
||||||
|
@VisibleForTesting int mToastCount = 0;
|
||||||
|
|
||||||
|
BluetoothAirplaneModeListener(BluetoothManagerService service, Looper looper, Context context) {
|
||||||
|
mBluetoothManager = service;
|
||||||
|
|
||||||
|
mHandler = new BluetoothAirplaneModeHandler(looper);
|
||||||
|
context.getContentResolver().registerContentObserver(
|
||||||
|
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
|
||||||
|
mAirplaneModeObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
|
||||||
|
@Override
|
||||||
|
public void onChange(boolean unused) {
|
||||||
|
// Post from system main thread to android_io thread.
|
||||||
|
Message msg = mHandler.obtainMessage(MSG_AIRPLANE_MODE_CHANGED);
|
||||||
|
mHandler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private class BluetoothAirplaneModeHandler extends Handler {
|
||||||
|
BluetoothAirplaneModeHandler(Looper looper) {
|
||||||
|
super(looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case MSG_AIRPLANE_MODE_CHANGED:
|
||||||
|
handleAirplaneModeChange();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Invalid message: " + msg.what);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call after boot complete
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
void start(AirplaneModeHelper helper) {
|
||||||
|
Log.i(TAG, "start");
|
||||||
|
mAirplaneHelper = helper;
|
||||||
|
mToastCount = mAirplaneHelper.getSettingsInt(TOAST_COUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean shouldPopToast() {
|
||||||
|
if (mToastCount >= MAX_TOAST_COUNT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mToastCount++;
|
||||||
|
mAirplaneHelper.setSettingsInt(TOAST_COUNT, mToastCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void handleAirplaneModeChange() {
|
||||||
|
if (shouldSkipAirplaneModeChange()) {
|
||||||
|
Log.i(TAG, "Ignore airplane mode change");
|
||||||
|
// We have to store Bluetooth state here, so if user turns off Bluetooth
|
||||||
|
// after airplane mode is turned on, we don't forget to turn on Bluetooth
|
||||||
|
// when airplane mode turns off.
|
||||||
|
mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
|
||||||
|
BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
|
||||||
|
if (shouldPopToast()) {
|
||||||
|
mAirplaneHelper.showToastMessage();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean shouldSkipAirplaneModeChange() {
|
||||||
|
if (mAirplaneHelper == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
|
||||||
|
|| !mAirplaneHelper.isA2dpOrHearingAidConnected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class that handles callout and callback methods without
|
||||||
|
* complex logic.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static class AirplaneModeHelper {
|
||||||
|
private volatile BluetoothA2dp mA2dp;
|
||||||
|
private volatile BluetoothHearingAid mHearingAid;
|
||||||
|
private final BluetoothAdapter mAdapter;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
AirplaneModeHelper(Context context) {
|
||||||
|
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
mContext = context;
|
||||||
|
|
||||||
|
mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
|
||||||
|
mAdapter.getProfileProxy(mContext, mProfileServiceListener,
|
||||||
|
BluetoothProfile.HEARING_AID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ServiceListener mProfileServiceListener = new ServiceListener() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
||||||
|
// Setup Bluetooth profile proxies
|
||||||
|
switch (profile) {
|
||||||
|
case BluetoothProfile.A2DP:
|
||||||
|
mA2dp = (BluetoothA2dp) proxy;
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.HEARING_AID:
|
||||||
|
mHearingAid = (BluetoothHearingAid) proxy;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(int profile) {
|
||||||
|
// Clear Bluetooth profile proxies
|
||||||
|
switch (profile) {
|
||||||
|
case BluetoothProfile.A2DP:
|
||||||
|
mA2dp = null;
|
||||||
|
break;
|
||||||
|
case BluetoothProfile.HEARING_AID:
|
||||||
|
mHearingAid = null;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public boolean isA2dpOrHearingAidConnected() {
|
||||||
|
return isA2dpConnected() || isHearingAidConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public boolean isBluetoothOn() {
|
||||||
|
final BluetoothAdapter adapter = mAdapter;
|
||||||
|
if (adapter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return adapter.getLeState() == BluetoothAdapter.STATE_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public boolean isAirplaneModeOn() {
|
||||||
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void onAirplaneModeChanged(BluetoothManagerService managerService) {
|
||||||
|
managerService.onAirplaneModeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public int getSettingsInt(String name) {
|
||||||
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setSettingsInt(String name, int value) {
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void showToastMessage() {
|
||||||
|
Resources r = mContext.getResources();
|
||||||
|
final CharSequence text = r.getString(
|
||||||
|
R.string.bluetooth_airplane_mode_toast, 0);
|
||||||
|
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isA2dpConnected() {
|
||||||
|
final BluetoothA2dp a2dp = mA2dp;
|
||||||
|
if (a2dp == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return a2dp.getConnectedDevices().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHearingAidConnected() {
|
||||||
|
final BluetoothHearingAid hearingAid = mHearingAid;
|
||||||
|
if (hearingAid == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hearingAid.getConnectedDevices().size() > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -68,6 +68,7 @@ import android.util.Slog;
|
|||||||
import android.util.StatsLog;
|
import android.util.StatsLog;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
import com.android.server.pm.UserRestrictionsUtils;
|
import com.android.server.pm.UserRestrictionsUtils;
|
||||||
|
|
||||||
@@ -138,7 +139,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
// Bluetooth persisted setting is on
|
// Bluetooth persisted setting is on
|
||||||
// but Airplane mode will affect Bluetooth state at start up
|
// but Airplane mode will affect Bluetooth state at start up
|
||||||
// and Airplane mode will have higher priority.
|
// and Airplane mode will have higher priority.
|
||||||
private static final int BLUETOOTH_ON_AIRPLANE = 2;
|
@VisibleForTesting
|
||||||
|
static final int BLUETOOTH_ON_AIRPLANE = 2;
|
||||||
|
|
||||||
private static final int SERVICE_IBLUETOOTH = 1;
|
private static final int SERVICE_IBLUETOOTH = 1;
|
||||||
private static final int SERVICE_IBLUETOOTHGATT = 2;
|
private static final int SERVICE_IBLUETOOTHGATT = 2;
|
||||||
@@ -159,6 +161,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
private boolean mBinding;
|
private boolean mBinding;
|
||||||
private boolean mUnbinding;
|
private boolean mUnbinding;
|
||||||
|
|
||||||
|
private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
|
||||||
|
|
||||||
// used inside handler thread
|
// used inside handler thread
|
||||||
private boolean mQuietEnable = false;
|
private boolean mQuietEnable = false;
|
||||||
private boolean mEnable;
|
private boolean mEnable;
|
||||||
@@ -257,9 +261,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) {
|
public void onAirplaneModeChanged() {
|
||||||
@Override
|
|
||||||
public void onChange(boolean unused) {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (isBluetoothPersistedStateOn()) {
|
if (isBluetoothPersistedStateOn()) {
|
||||||
if (isAirplaneModeOn()) {
|
if (isAirplaneModeOn()) {
|
||||||
@@ -318,7 +320,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
@@ -430,9 +431,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
|
Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
|
||||||
if (airplaneModeRadios == null || airplaneModeRadios.contains(
|
if (airplaneModeRadios == null || airplaneModeRadios.contains(
|
||||||
Settings.Global.RADIO_BLUETOOTH)) {
|
Settings.Global.RADIO_BLUETOOTH)) {
|
||||||
mContentResolver.registerContentObserver(
|
mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
|
||||||
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
|
this, IoThread.get().getLooper(), context);
|
||||||
mAirplaneModeObserver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int systemUiUid = -1;
|
int systemUiUid = -1;
|
||||||
@@ -478,6 +478,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
return state != BLUETOOTH_OFF;
|
return state != BLUETOOTH_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isBluetoothPersistedStateOnAirplane() {
|
||||||
|
if (!supportBluetoothPersistedState()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
|
||||||
|
if (DBG) {
|
||||||
|
Slog.d(TAG, "Bluetooth persisted state: " + state);
|
||||||
|
}
|
||||||
|
return state == BLUETOOTH_ON_AIRPLANE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
|
* Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
|
||||||
*/
|
*/
|
||||||
@@ -954,10 +965,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mReceiver) {
|
synchronized (mReceiver) {
|
||||||
|
if (!isBluetoothPersistedStateOnAirplane()) {
|
||||||
if (persist) {
|
if (persist) {
|
||||||
persistBluetoothSetting(BLUETOOTH_OFF);
|
persistBluetoothSetting(BLUETOOTH_OFF);
|
||||||
}
|
}
|
||||||
mEnableExternal = false;
|
mEnableExternal = false;
|
||||||
|
}
|
||||||
sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
|
sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
|
||||||
packageName);
|
packageName);
|
||||||
}
|
}
|
||||||
@@ -1185,6 +1198,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
|
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
|
||||||
mHandler.sendMessage(getMsg);
|
mHandler.sendMessage(getMsg);
|
||||||
}
|
}
|
||||||
|
if (mBluetoothAirplaneModeListener != null) {
|
||||||
|
mBluetoothAirplaneModeListener.start(
|
||||||
|
new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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.server;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.MediumTest;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.server.BluetoothAirplaneModeListener.AirplaneModeHelper;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
@MediumTest
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class BluetoothAirplaneModeListenerTest {
|
||||||
|
private Context mContext;
|
||||||
|
private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener;
|
||||||
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
|
private AirplaneModeHelper mHelper;
|
||||||
|
|
||||||
|
@Mock BluetoothManagerService mBluetoothManagerService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
mHelper = mock(AirplaneModeHelper.class);
|
||||||
|
when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT))
|
||||||
|
.thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT);
|
||||||
|
doNothing().when(mHelper).setSettingsInt(anyString(), anyInt());
|
||||||
|
doNothing().when(mHelper).showToastMessage();
|
||||||
|
doNothing().when(mHelper).onAirplaneModeChanged(any(BluetoothManagerService.class));
|
||||||
|
|
||||||
|
mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
|
||||||
|
mBluetoothManagerService, Looper.getMainLooper(), mContext);
|
||||||
|
mBluetoothAirplaneModeListener.start(mHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIgnoreOnAirplanModeChange() {
|
||||||
|
Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
|
||||||
|
|
||||||
|
when(mHelper.isBluetoothOn()).thenReturn(true);
|
||||||
|
Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
|
||||||
|
|
||||||
|
when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
|
||||||
|
Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
|
||||||
|
|
||||||
|
when(mHelper.isAirplaneModeOn()).thenReturn(true);
|
||||||
|
Assert.assertTrue(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleAirplaneModeChange_InvokeAirplaneModeChanged() {
|
||||||
|
mBluetoothAirplaneModeListener.handleAirplaneModeChange();
|
||||||
|
verify(mHelper).onAirplaneModeChanged(mBluetoothManagerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_NotPopToast() {
|
||||||
|
mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
|
||||||
|
when(mHelper.isBluetoothOn()).thenReturn(true);
|
||||||
|
when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
|
||||||
|
when(mHelper.isAirplaneModeOn()).thenReturn(true);
|
||||||
|
mBluetoothAirplaneModeListener.handleAirplaneModeChange();
|
||||||
|
|
||||||
|
verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
|
||||||
|
BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
|
||||||
|
verify(mHelper, times(0)).showToastMessage();
|
||||||
|
verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_PopToast() {
|
||||||
|
mBluetoothAirplaneModeListener.mToastCount = 0;
|
||||||
|
when(mHelper.isBluetoothOn()).thenReturn(true);
|
||||||
|
when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
|
||||||
|
when(mHelper.isAirplaneModeOn()).thenReturn(true);
|
||||||
|
mBluetoothAirplaneModeListener.handleAirplaneModeChange();
|
||||||
|
|
||||||
|
verify(mHelper).setSettingsInt(Settings.Global.BLUETOOTH_ON,
|
||||||
|
BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
|
||||||
|
verify(mHelper).showToastMessage();
|
||||||
|
verify(mHelper, times(0)).onAirplaneModeChanged(mBluetoothManagerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsPopToast_PopToast() {
|
||||||
|
mBluetoothAirplaneModeListener.mToastCount = 0;
|
||||||
|
Assert.assertTrue(mBluetoothAirplaneModeListener.shouldPopToast());
|
||||||
|
verify(mHelper).setSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsPopToast_NotPopToast() {
|
||||||
|
mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
|
||||||
|
Assert.assertFalse(mBluetoothAirplaneModeListener.shouldPopToast());
|
||||||
|
verify(mHelper, times(0)).setSettingsInt(anyString(), anyInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user