Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afedf526 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes I93fa880a,Ib036852a,Ic5ab3c04,I4452eacf am: 20909a93b0

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1462704

Change-Id: Idf6c5f0bd1f3297fef9ee326d3d55acf88d79870
parents c0a0d9d5 ba3049eb
Loading
Loading
Loading
Loading
+2 −124
Original line number Diff line number Diff line
@@ -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;
        }
    };
}
+64 −0
Original line number Diff line number Diff line
/*
 * 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();
                }
            };

}
+35 −30
Original line number Diff line number Diff line
@@ -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;
@@ -116,6 +117,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;
@@ -175,8 +177,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;
@@ -281,29 +287,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;
                    }
    @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() {
        // Wait for stable state if bluetooth is temporary state.
@@ -451,6 +441,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();
                }
            }
        }
    };
@@ -501,6 +500,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);

@@ -535,10 +536,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);
    }

    /**
@@ -1368,10 +1365,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);
    }

    /**
@@ -2214,6 +2213,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);
+143 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+2 −4
Original line number Diff line number Diff line
@@ -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());