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

Commit 52bf6e55 authored by jasonwshsu's avatar jasonwshsu
Browse files

Implement Hearing Devices Quick Settings Tile (2/n)

This patch provides
* dialog setup and show when clicking on the hearing device tile

Bug: 291423171
Bug: 319197158
Test: atest HearingDevicesTileTest HearingDevicesDialogDelegateTest
Flag: ACONFIG com.android.systemui.hearing_aids_qs_tile_dialog DEVELOPMENT
Change-Id: I8c9ff2935527df54c48fb1161dc86ae24e88d97b
parent cd64cbea
Loading
Loading
Loading
Loading
+57 −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.
 */

package com.android.systemui.accessibility.hearingaid;

import com.android.systemui.statusbar.phone.SystemUIDialog;

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

/**
 * Dialog for showing hearing devices controls.
 */
public class HearingDevicesDialogDelegate implements SystemUIDialog.Delegate{

    private final SystemUIDialog.Factory mSystemUIDialogFactory;

    private SystemUIDialog mDialog;

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

    @AssistedInject
    public HearingDevicesDialogDelegate(
            SystemUIDialog.Factory systemUIDialogFactory) {
        mSystemUIDialogFactory = systemUIDialogFactory;
    }

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

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

        return dialog;
    }
}
+79 −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.
 */

package com.android.systemui.accessibility.hearingaid;

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

import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.animation.DialogCuj;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.phone.SystemUIDialog;

import javax.inject.Inject;

/**
 * Factory to create {@link HearingDevicesDialogDelegate} objects and manage its lifecycle.
 */
@SysUISingleton
public class HearingDevicesDialogManager {

    private static final boolean DEBUG = true;
    private static final String TAG = "HearingDevicesDialogManager";
    private static final String INTERACTION_JANK_TAG = "hearing_devices_tile";
    private SystemUIDialog mDialog;
    private final DialogTransitionAnimator mDialogTransitionAnimator;
    private final HearingDevicesDialogDelegate.Factory mDialogFactory;

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

    /**
     * Shows the dialog.
     *
     * @param view The view from which the dialog is shown.
     */
    public void showDialog(View view) {
        if (mDialog != null) {
            if (DEBUG) {
                Log.d(TAG, "HearingDevicesDialog already showing. Destroy it first.");
            }
            destroyDialog();
        }
        mDialog = mDialogFactory.create().createDialog();

        if (view != null) {
            mDialogTransitionAnimator.showFromView(mDialog, view,
                    new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
                            INTERACTION_JANK_TAG),
                    true);
        } else {
            mDialog.show();
        }
    }

    private void destroyDialog() {
        mDialog.dismiss();
        mDialog = null;
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import androidx.annotation.Nullable;

import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Flags;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -45,6 +46,8 @@ public class HearingDevicesTile extends QSTileImpl<State> {

    public static final String TILE_SPEC = "hearing_devices";

    private final HearingDevicesDialogManager mDialogManager;

    @Inject
    public HearingDevicesTile(
            QSHost host,
@@ -55,10 +58,12 @@ public class HearingDevicesTile extends QSTileImpl<State> {
            MetricsLogger metricsLogger,
            StatusBarStateController statusBarStateController,
            ActivityStarter activityStarter,
            QSLogger qsLogger
            QSLogger qsLogger,
            HearingDevicesDialogManager hearingDevicesDialogManager
    ) {
        super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                statusBarStateController, activityStarter, qsLogger);
        mDialogManager = hearingDevicesDialogManager;
    }

    @Override
@@ -68,7 +73,7 @@ public class HearingDevicesTile extends QSTileImpl<State> {

    @Override
    protected void handleClick(@Nullable View view) {

        mUiHandler.post(() -> mDialogManager.showDialog(view));
    }

    @Override
+86 −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.
 */

package com.android.systemui.accessibility.hearingaid;

import static com.android.systemui.statusbar.phone.SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.model.SysUiState;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

/** Tests for {@link HearingDevicesDialogDelegate}. */
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
public class HearingDevicesDialogDelegateTest extends SysuiTestCase {
    @Rule
    public MockitoRule mockito = MockitoJUnit.rule();

    @Mock
    private SystemUIDialog.Factory mSystemUIDialogFactory;
    @Mock
    private SystemUIDialogManager mSystemUIDialogManager;
    @Mock
    private SysUiState mSysUiState;
    @Mock
    private DialogTransitionAnimator mDialogTransitionAnimator;
    private SystemUIDialog mDialog;
    private HearingDevicesDialogDelegate mDialogDelegate;

    @Before
    public void setUp() {
        mDialogDelegate = new HearingDevicesDialogDelegate(mSystemUIDialogFactory);
        mDialog = new SystemUIDialog(
                mContext,
                0,
                DEFAULT_DISMISS_ON_DEVICE_LOCK,
                mSystemUIDialogManager,
                mSysUiState,
                getFakeBroadcastDispatcher(),
                mDialogTransitionAnimator,
                mDialogDelegate
        );

        when(mSystemUIDialogFactory.create(any(SystemUIDialog.Delegate.class)))
                .thenReturn(mDialog);
    }

    @Test
    public void createDialog_dialogShown() {
        assertThat(mDialogDelegate.createDialog()).isEqualTo(mDialog);
    }
}
+17 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Intent;
import android.os.Handler;
@@ -29,12 +30,14 @@ import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;

import androidx.test.filters.SmallTest;

import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.hearingaid.HearingDevicesDialogManager;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -73,6 +76,8 @@ public class HearingDevicesTileTest extends SysuiTestCase {
    private ActivityStarter mActivityStarter;
    @Mock
    private QSLogger mQSLogger;
    @Mock
    HearingDevicesDialogManager mHearingDevicesDialogManager;

    private TestableLooper mTestableLooper;
    private HearingDevicesTile mTile;
@@ -80,6 +85,7 @@ public class HearingDevicesTileTest extends SysuiTestCase {
    @Before
    public void setUp() throws Exception {
        mTestableLooper = TestableLooper.get(this);
        when(mHost.getContext()).thenReturn(mContext);

        mTile = new HearingDevicesTile(
                mHost,
@@ -90,7 +96,8 @@ public class HearingDevicesTileTest extends SysuiTestCase {
                mMetricsLogger,
                mStatusBarStateController,
                mActivityStarter,
                mQSLogger);
                mQSLogger,
                mHearingDevicesDialogManager);

        mTile.initialize();
        mTestableLooper.processAllMessages();
@@ -125,4 +132,13 @@ public class HearingDevicesTileTest extends SysuiTestCase {
        assertThat(IntentCaptor.getValue().getAction()).isEqualTo(
                Settings.ACTION_HEARING_DEVICES_SETTINGS);
    }

    @Test
    public void handleClick_dialogShown() {
        View view = new View(mContext);
        mTile.handleClick(view);
        mTestableLooper.processAllMessages();

        verify(mHearingDevicesDialogManager).showDialog(view);
    }
}