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

Commit 2912f2d5 authored by William Escande's avatar William Escande
Browse files

SystemServer: AutoOn: Add system API

Bug: 316946334
Bug: 323060869
Test: m Bluetooth
Test: atest CtsBluetoothTestCases
Test: atest ServiceBluetoothRoboTests
Change-Id: I0d8c37a9b3684a0b2c45111ddb8b0738a9682792
parent 5e82dc9f
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ package android.bluetooth {
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.os.Bundle getPreferredAudioProfiles(@NonNull android.bluetooth.BluetoothDevice);
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<java.lang.Integer> getSupportedProfiles();
    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.os.ParcelUuid> getUuidsList();
    method @FlaggedApi("com.android.bluetooth.flags.auto_on_feature") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isAutoOnEnabled();
    method @FlaggedApi("com.android.bluetooth.flags.auto_on_feature") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isAutoOnSupported();
    method public boolean isBleScanAlwaysAvailable();
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int isDistanceMeasurementSupported();
    method public boolean isLeEnabled();
@@ -88,6 +90,7 @@ package android.bluetooth {
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void requestControllerActivityEnergyInfo(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback);
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothSocket retrieveConnectedRfcommSocket(@NonNull java.util.UUID);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
    method @FlaggedApi("com.android.bluetooth.flags.auto_on_feature") @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setAutoOnEnabled(boolean);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int setBluetoothHciSnoopLoggingMode(int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setDiscoverableTimeout(@NonNull java.time.Duration);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setPreferredAudioProfiles(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.os.Bundle);
+56 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.bluetooth.BluetoothUtils.getSyncTimeout;
import static java.util.Objects.requireNonNull;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -69,6 +70,7 @@ import android.sysprop.BluetoothProperties;
import android.util.Log;
import android.util.Pair;

import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
import com.android.modules.expresslog.Counter;
import com.android.modules.utils.SynchronousResultReceiver;
@@ -5796,6 +5798,60 @@ public final class BluetoothAdapter {
        return BT_SNOOP_LOG_MODE_DISABLED;
    }

    /**
     * Returns true if the auto on feature is supported on the device
     *
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_AUTO_ON_FEATURE)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public boolean isAutoOnSupported() {
        try {
            return mManagerService.isAutoOnSupported();
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return false;
    }

    /**
     * Get the value of the automatic restart of the Bluetooth stack for the current user
     *
     * @return true if the auto on feature is enabled for the current user
     * @throws IllegalStateException if feature is not supported
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_AUTO_ON_FEATURE)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public boolean isAutoOnEnabled() {
        try {
            return mManagerService.isAutoOnEnabled();
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return false;
    }

    /**
     * Set the value of the automatic restart of the Bluetooth stack for the current user
     *
     * @param status true if the feature is enabled
     * @throws IllegalStateException if feature is not supported
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_AUTO_ON_FEATURE)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public void setAutoOnEnabled(boolean status) {
        try {
            mManagerService.setAutoOnEnabled(status);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(
+1 −0
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ android_robolectric_test {

    static_libs: [
        "androidx.test.core",
        "kotlin-test",
        "kotlinx_coroutines",
        "kotlinx_coroutines_test",
        "mockito-robolectric-prebuilt",
+8 −0
Original line number Diff line number Diff line
@@ -63,4 +63,12 @@ interface IBluetoothManager
    int setBtHciSnoopLogMode(int mode);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")
    int getBtHciSnoopLogMode();

    // AutoOnFeature
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")
    boolean isAutoOnSupported();
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")
    boolean isAutoOnEnabled();
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")
    void setAutoOnEnabled(boolean status);
}
+32 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Handler
import android.os.Looper
import android.provider.Settings
import androidx.annotation.VisibleForTesting
import com.android.modules.expresslog.Counter
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.temporal.ChronoUnit
@@ -61,11 +62,38 @@ public fun notifyBluetoothOn(resolver: ContentResolver) {
    timer = null

    if (!isFeatureSupportedForUser(resolver)) {
        Log.i(TAG, "Feature was set to its default value")
        setFeatureEnabledForUserUnchecked(resolver)
        val defaultFeatureValue = true
        Log.i(TAG, "Feature was set to its default value ${defaultFeatureValue}")
        setFeatureEnabledForUserUnchecked(resolver, defaultFeatureValue)
    }
}

public fun isUserSupported(resolver: ContentResolver) = isFeatureSupportedForUser(resolver)

public fun isUserEnabled(context: Context): Boolean {
    if (!isUserSupported(context.contentResolver)) {
        throw IllegalStateException("AutoOnFeature not supported for user: ${context.getUser()}")
    }
    return isFeatureEnabledForUser(context.contentResolver)
}

public fun setUserEnabled(
    looper: Looper,
    context: Context,
    state: BluetoothAdapterState,
    status: Boolean,
    callback_on: () -> Unit,
) {
    if (!isUserSupported(context.contentResolver)) {
        throw IllegalStateException("AutoOnFeature not supported for user: ${context.getUser()}")
    }
    setFeatureEnabledForUserUnchecked(context.contentResolver, status)
    Counter.logIncrement(
        if (status) "bluetooth.value_auto_on_enabled" else "bluetooth.value_auto_on_disabled"
    )
    resetAutoOnTimerForUser(looper, context, state, callback_on)
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////// PRIVATE METHODS /////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -148,6 +176,6 @@ private fun isFeatureSupportedForUser(resolver: ContentResolver): Boolean {
 *
 * @return whether the auto on feature is enabled for this user
 */
private fun setFeatureEnabledForUserUnchecked(resolver: ContentResolver) {
    Settings.Secure.putInt(resolver, USER_SETTINGS_KEY, 1)
private fun setFeatureEnabledForUserUnchecked(resolver: ContentResolver, status: Boolean) {
    Settings.Secure.putInt(resolver, USER_SETTINGS_KEY, if (status) 1 else 0)
}
Loading