diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2020-10-16 18:39:47 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-10-16 18:39:47 +0000 |
commit | a2e91be0143ba90fd64a454741b41adda5640e8e (patch) | |
tree | e242d6868b92d556c97a6f80ce08a41097a19440 | |
parent | 2883f7ab9e740b5da3c872b9fe675691ddfc322d (diff) | |
parent | 21faba04a5889f5b7a87f7341b6211cfac6dcf1d (diff) |
Merge changes I93fa880a,Ib036852a,Ic5ab3c04,I4452eacf am: 20909a93b0 am: afedf5268f am: 6bdddb9eb8 am: 21faba04a5
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1462704
Change-Id: I426ed285d9c1db8a9240b53912831d64c43a7503
5 files changed, 246 insertions, 158 deletions
diff --git a/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java b/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java index 31cd5d519d..4d9680c785 100644 --- a/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java +++ b/service/java/com/android/server/bluetooth/BluetoothAirplaneModeListener.java @@ -16,22 +16,14 @@ 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; /** @@ -53,7 +45,7 @@ class BluetoothAirplaneModeListener { private final BluetoothManagerService mBluetoothManager; private final BluetoothAirplaneModeHandler mHandler; - private AirplaneModeHelper mAirplaneHelper; + private BluetoothModeChangeHelper mAirplaneHelper; @VisibleForTesting int mToastCount = 0; @@ -97,7 +89,7 @@ class BluetoothAirplaneModeListener { * Call after boot complete */ @VisibleForTesting - void start(AirplaneModeHelper helper) { + void start(BluetoothModeChangeHelper helper) { Log.i(TAG, "start"); mAirplaneHelper = helper; mToastCount = mAirplaneHelper.getSettingsInt(TOAST_COUNT); @@ -141,118 +133,4 @@ class BluetoothAirplaneModeListener { } 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; - } - }; } diff --git a/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java b/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java new file mode 100644 index 0000000000..2dcf82ff94 --- /dev/null +++ b/service/java/com/android/server/bluetooth/BluetoothDeviceConfigListener.java @@ -0,0 +1,64 @@ +/* + * Copyright 2020 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.provider.DeviceConfig; + +/** + * The BluetoothDeviceConfigListener handles system device config change callback and checks + * whether we need to inform BluetoothManagerService on this change. + * + * The information of device config change 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 BluetoothDeviceConfigListener { + private static final String TAG = "BluetoothDeviceConfigListener"; + + BluetoothManagerService mService; + + BluetoothDeviceConfigListener(BluetoothManagerService service) { + mService = service; + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_BLUETOOTH, + (Runnable r) -> r.run(), + mDeviceConfigChangedListener); + } + + private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener = + new DeviceConfig.OnPropertiesChangedListener() { + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { + if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { + return; + } + boolean foundInit = false; + for (String name : properties.getKeyset()) { + if (name.startsWith("INIT_")) { + foundInit = true; + break; + } + } + if (!foundInit) { + return; + } + mService.onInitFlagsChanged(); + } + }; + +} diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 011231c016..f6a29aa917 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -23,7 +23,9 @@ import android.Manifest; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.IBluetooth; @@ -63,7 +65,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; -import android.provider.DeviceConfig; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; @@ -118,6 +119,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Delay for retrying enable and disable in msec private static final int ENABLE_DISABLE_DELAY_MS = 300; private static final int DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS = 300; + private static final int DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS = 86400; private static final int MESSAGE_ENABLE = 1; private static final int MESSAGE_DISABLE = 2; @@ -178,8 +180,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private int mWaitForEnableRetry; private int mWaitForDisableRetry; + private BluetoothModeChangeHelper mBluetoothModeChangeHelper; + private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; + private BluetoothDeviceConfigListener mBluetoothDeviceConfigListener; + // used inside handler thread private boolean mQuietEnable = false; private boolean mEnable; @@ -284,29 +290,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; - private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener = - new DeviceConfig.OnPropertiesChangedListener() { - @Override - public void onPropertiesChanged(DeviceConfig.Properties properties) { - if (!properties.getNamespace().equals(DeviceConfig.NAMESPACE_BLUETOOTH)) { - return; - } - boolean foundInit = false; - for (String name : properties.getKeyset()) { - if (name.startsWith("INIT_")) { - foundInit = true; - break; - } - } - if (!foundInit) { - return; - } - mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); - mHandler.sendEmptyMessageDelayed( - MESSAGE_INIT_FLAGS_CHANGED, - DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); - } - }; + @VisibleForTesting + public void onInitFlagsChanged() { + mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_BEFORE_RESTART_DUE_TO_INIT_FLAGS_CHANGED_MS); + } public boolean onFactoryReset() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, @@ -457,6 +447,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessage(msg); } } + } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action) + || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)) { + final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, + BluetoothProfile.STATE_CONNECTED); + if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED) + && state == BluetoothProfile.STATE_DISCONNECTED + && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + onInitFlagsChanged(); + } } } }; @@ -508,6 +507,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); filter.addAction(Intent.ACTION_SETTING_RESTORED); + filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); @@ -542,10 +543,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Unable to resolve SystemUI's UID."); } mSystemUiUid = systemUiUid; - DeviceConfig.addOnPropertiesChangedListener( - DeviceConfig.NAMESPACE_BLUETOOTH, - (Runnable r) -> r.run(), - mDeviceConfigChangedListener); } /** @@ -1383,10 +1380,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); } + + mBluetoothModeChangeHelper = new BluetoothModeChangeHelper(mContext); if (mBluetoothAirplaneModeListener != null) { - mBluetoothAirplaneModeListener.start( - new BluetoothAirplaneModeListener.AirplaneModeHelper(mContext)); + mBluetoothAirplaneModeListener.start(mBluetoothModeChangeHelper); } + mBluetoothDeviceConfigListener = new BluetoothDeviceConfigListener(this); } /** @@ -2229,6 +2228,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED"); } mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED); + if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) { + mHandler.sendEmptyMessageDelayed( + MESSAGE_INIT_FLAGS_CHANGED, + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS); + break; + } if (mBluetooth != null && isEnabled()) { restartForReason( BluetoothProtoEnums.ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED); diff --git a/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java b/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java new file mode 100644 index 0000000000..242fa848c2 --- /dev/null +++ b/service/java/com/android/server/bluetooth/BluetoothModeChangeHelper.java @@ -0,0 +1,143 @@ +/* + * Copyright 2020 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.provider.Settings; +import android.widget.Toast; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; + +/** + * Helper class that handles callout and callback methods without + * complex logic. + */ +public class BluetoothModeChangeHelper { + private volatile BluetoothA2dp mA2dp; + private volatile BluetoothHearingAid mHearingAid; + private final BluetoothAdapter mAdapter; + private final Context mContext; + + BluetoothModeChangeHelper(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; + } +} diff --git a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java index 968a402ff3..3ace3f4c79 100644 --- a/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java +++ b/service/tests/src/com/android/server/BluetoothAirplaneModeListenerTest.java @@ -27,8 +27,6 @@ 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; @@ -41,7 +39,7 @@ public class BluetoothAirplaneModeListenerTest { private Context mContext; private BluetoothAirplaneModeListener mBluetoothAirplaneModeListener; private BluetoothAdapter mBluetoothAdapter; - private AirplaneModeHelper mHelper; + private BluetoothModeChangeHelper mHelper; @Mock BluetoothManagerService mBluetoothManagerService; @@ -49,7 +47,7 @@ public class BluetoothAirplaneModeListenerTest { public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); - mHelper = mock(AirplaneModeHelper.class); + mHelper = mock(BluetoothModeChangeHelper.class); when(mHelper.getSettingsInt(BluetoothAirplaneModeListener.TOAST_COUNT)) .thenReturn(BluetoothAirplaneModeListener.MAX_TOAST_COUNT); doNothing().when(mHelper).setSettingsInt(anyString(), anyInt()); |