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

Commit 430f6999 authored by jasonwshsu's avatar jasonwshsu
Browse files

Implement Hearing Devices Quick Settings Tile (3/n)

This patch provides
* Manager to control when to show pair new device dialog
* Click on pair new device button to launch hearing device pairing page
* Add intent to open hearing device pairing page

Bug: 291423171
Bug: 319197158
Test: atest HearingDevicesDialogDelegateTest HearingDevicesDialogManagerTest
Flag: ACONFIG com.android.systemui.hearing_aids_qs_tile_dialog DEVELOPMENT
Change-Id: I17ab63942d5d98e59a46986137caeb7c0f8c4ed8
parent 52bf6e55
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1260,6 +1260,22 @@ public final class Settings {
    public static final String ACTION_BLUETOOTH_PAIRING_SETTINGS =
            "android.settings.BLUETOOTH_PAIRING_SETTINGS";
    /**
     * Activity Action: Show settings to allow pairing hearing devices.
     * <p>
     * In some cases, a matching Activity may not exist, so ensure you
     * safeguard against this.
     * <p>
     * Input: Nothing.
     * <p>
     * Output: Nothing.
     *
     * @hide
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_HEARING_DEVICE_PAIRING_SETTINGS =
            "android.settings.HEARING_DEVICES_PAIRING_SETTINGS";
    /**
     * Activity Action: Show settings to configure input methods, in particular
     * allowing the user to enable input methods.
+48 −0
Original line number Diff line number Diff line
<!--
    Copyright (C) 2024 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.
-->

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root"
    style="@style/Widget.SliceView.Panel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <Button
        android:id="@+id/pair_new_device_button"
        style="@style/BluetoothTileDialog.Device"
        android:paddingEnd="0dp"
        android:paddingStart="20dp"
        android:background="@drawable/bluetooth_tile_dialog_bg_off"
        android:layout_width="0dp"
        android:layout_height="64dp"
        android:contentDescription="@string/accessibility_hearing_device_pair_new_device"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:drawableStart="@drawable/ic_add"
        android:drawablePadding="20dp"
        android:drawableTint="?android:attr/textColorPrimary"
        android:text="@string/quick_settings_pair_hearing_devices"
        android:textSize="14sp"
        android:textAppearance="@style/TextAppearance.Dialog.Title"
        android:textDirection="locale"
        android:textAlignment="viewStart"
        android:maxLines="1"
        android:ellipsize="end" />

</androidx.constraintlayout.widget.ConstraintLayout>
 No newline at end of file
+7 −0
Original line number Diff line number Diff line
@@ -899,8 +899,15 @@
    <!-- QuickSettings: Contrast tile description: high [CHAR LIMIT=NONE] -->
    <string name="quick_settings_contrast_high">High</string>

    <!-- Hearing devices -->
    <!-- QuickSettings: Hearing devices [CHAR LIMIT=NONE] -->
    <string name="quick_settings_hearing_devices_label">Hearing devices</string>
    <!-- QuickSettings: Quick Settings Hearing devices dialog title [CHAR LIMIT=30] -->
    <string name="quick_settings_hearing_devices_dialog_title">Hearing devices</string>
    <!-- QuickSettings: Hearing devices dialog pair new device [CHAR LIMIT=NONE]-->
    <string name="quick_settings_pair_hearing_devices">Pair new device</string>
    <!-- QuickSettings: Content description of the hearing devices dialog pair new device [CHAR LIMIT=NONE] -->
    <string name="accessibility_hearing_device_pair_new_device">Click to pair new device</string>

    <!--- Title of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=150] -->
    <string name="sensor_privacy_start_use_mic_dialog_title">Unblock device microphone?</string>
+70 −6
Original line number Diff line number Diff line
@@ -16,8 +16,25 @@

package com.android.systemui.accessibility.hearingaid;

import static android.view.View.GONE;
import static android.view.View.VISIBLE;

import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View.Visibility;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;

import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;

@@ -27,31 +44,78 @@ import dagger.assisted.AssistedInject;
public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate {

    private final SystemUIDialog.Factory mSystemUIDialogFactory;
    private final DialogTransitionAnimator mDialogTransitionAnimator;
    private final ActivityStarter mActivityStarter;
    private final boolean mShowPairNewDevice;

    private SystemUIDialog mDialog;
    private Button mPairButton;

    /** Factory to create a {@link HearingDevicesDialogDelegate} dialog instance. */
    @AssistedFactory
    public interface Factory {
        /** Create a {@link HearingDevicesDialogDelegate} instance */
        HearingDevicesDialogDelegate create();
        HearingDevicesDialogDelegate create(
                boolean showPairNewDevice);
    }

    @AssistedInject
    public HearingDevicesDialogDelegate(
            SystemUIDialog.Factory systemUIDialogFactory) {
            @Assisted boolean showPairNewDevice,
            SystemUIDialog.Factory systemUIDialogFactory,
            ActivityStarter activityStarter,
            DialogTransitionAnimator dialogTransitionAnimator) {
        mShowPairNewDevice = showPairNewDevice;
        mSystemUIDialogFactory = systemUIDialogFactory;
        mActivityStarter = activityStarter;
        mDialogTransitionAnimator = dialogTransitionAnimator;
    }

    @Override
    public SystemUIDialog createDialog() {
        SystemUIDialog dialog = mSystemUIDialogFactory.create(this);
        dismissDialogIfExists();
        mDialog = dialog;

        return dialog;
    }

    @Override
    public void beforeCreate(@NonNull SystemUIDialog dialog, @Nullable Bundle savedInstanceState) {
        dialog.setTitle(R.string.quick_settings_hearing_devices_dialog_title);
        dialog.setView(LayoutInflater.from(dialog.getContext()).inflate(
                R.layout.hearing_devices_tile_dialog, null));
        dialog.setPositiveButton(
                R.string.quick_settings_done,
                /* onClick = */ null,
                /* dismissOnClick = */ true
        );
    }

    @Override
    public void onCreate(@NonNull SystemUIDialog dialog, @Nullable Bundle savedInstanceState) {
        mPairButton = dialog.requireViewById(R.id.pair_new_device_button);

        setupPairNewDeviceButton(dialog, mShowPairNewDevice ? VISIBLE : GONE);
    }

    private void setupPairNewDeviceButton(SystemUIDialog dialog, @Visibility int visibility) {
        if (visibility == VISIBLE) {
            mPairButton.setOnClickListener(v -> {
                dismissDialogIfExists();
                final Intent intent = new Intent(Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                mActivityStarter.postStartActivityDismissingKeyguard(intent, /* delay= */ 0,
                        mDialogTransitionAnimator.createActivityTransitionController(dialog));
            });
        } else {
            mPairButton.setVisibility(GONE);
        }
    }

    private void dismissDialogIfExists() {
        if (mDialog != null) {
            mDialog.dismiss();
        }
        mDialog = dialog;

        return dialog;
    }
}
+24 −4
Original line number Diff line number Diff line
@@ -16,10 +16,14 @@

package com.android.systemui.accessibility.hearingaid;

import android.bluetooth.BluetoothDevice;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

import com.android.internal.jank.InteractionJankMonitor;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.dagger.SysUISingleton;
@@ -39,13 +43,16 @@ public class HearingDevicesDialogManager {
    private SystemUIDialog mDialog;
    private final DialogTransitionAnimator mDialogTransitionAnimator;
    private final HearingDevicesDialogDelegate.Factory mDialogFactory;
    private final LocalBluetoothManager mLocalBluetoothManager;

    @Inject
    public HearingDevicesDialogManager(
            DialogTransitionAnimator dialogTransitionAnimator,
            HearingDevicesDialogDelegate.Factory dialogFactory) {
            HearingDevicesDialogDelegate.Factory dialogFactory,
            @Nullable LocalBluetoothManager localBluetoothManager) {
        mDialogTransitionAnimator = dialogTransitionAnimator;
        mDialogFactory = dialogFactory;
        mLocalBluetoothManager = localBluetoothManager;
    }

    /**
@@ -60,13 +67,13 @@ public class HearingDevicesDialogManager {
            }
            destroyDialog();
        }
        mDialog = mDialogFactory.create().createDialog();

        mDialog = mDialogFactory.create(!isAnyBondedHearingDevice()).createDialog();

        if (view != null) {
            mDialogTransitionAnimator.showFromView(mDialog, view,
                    new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
                            INTERACTION_JANK_TAG),
                    true);
                            INTERACTION_JANK_TAG), /* animateBackgroundBoundsChange= */ true);
        } else {
            mDialog.show();
        }
@@ -76,4 +83,17 @@ public class HearingDevicesDialogManager {
        mDialog.dismiss();
        mDialog = null;
    }

    private boolean isAnyBondedHearingDevice() {
        if (mLocalBluetoothManager == null) {
            return false;
        }
        if (!mLocalBluetoothManager.getBluetoothAdapter().isEnabled()) {
            return false;
        }

        return mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy().stream()
                .anyMatch(device -> device.isHearingAidDevice()
                        && device.getBondState() != BluetoothDevice.BOND_NONE);
    }
}
Loading