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

Commit 7bc4ea01 authored by chelseahao's avatar chelseahao Committed by Chelsea Hao
Browse files

[Audiosharing] Impl of two error dialogs.

Bug: 305620450
Test: manual
Change-Id: I5bd4a4b2ab54c382f325c7a6bb4a3029d47786e0
parent b34e6722
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ 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.
  -->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/dialog_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/broadcast_dialog_margin"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/dialog_icon"
                android:layout_width="36dp"
                android:layout_height="36dp"
                android:layout_marginTop="@dimen/broadcast_dialog_icon_margin_top"
                android:layout_marginBottom="@dimen/broadcast_dialog_title_img_margin_top"
                android:layout_gravity="center"
                android:src="@drawable/ic_bt_audio_sharing"/>

            <TextView
                style="@style/BroadcastDialogTitleStyle"
                android:id="@+id/dialog_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_gravity="center"/>

            <TextView
                style="@style/BroadcastDialogBodyStyle"
                android:id="@+id/dialog_subtitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_gravity="center"
                android:visibility="gone"/>

            <TextView
                style="@style/BroadcastDialogBodyStyle"
                android:id="@+id/dialog_subtitle_2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_gravity="center"
                android:visibility="gone"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/broadcast_dialog_margin"
            android:orientation="horizontal">
            <Button
                android:id="@+id/left_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="16dp"
                android:layout_weight="1"
                android:visibility="gone"/>
            <Button
                android:id="@+id/right_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:layout_marginRight="16dp"
                android:visibility="gone"/>
        </LinearLayout>

    </LinearLayout>
</FrameLayout>
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public class AudioStreamsDashboardFragment extends DashboardFragment {
        super.onAttach(context);
        use(AudioStreamsScanQrCodeController.class).setFragment(this);
        mAudioStreamsProgressCategoryController = use(AudioStreamsProgressCategoryController.class);
        mAudioStreamsProgressCategoryController.setFragment(this);
    }

    @Override
+151 −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.settings.connecteddevice.audiosharing.audiostreams;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;

import com.google.common.base.Strings;

import java.util.function.Consumer;

public class AudioStreamsDialogFragment extends InstrumentedDialogFragment {
    private static final String TAG = "AudioStreamsDialogFragment";
    private final DialogBuilder mDialogBuilder;

    AudioStreamsDialogFragment(DialogBuilder dialogBuilder) {
        mDialogBuilder = dialogBuilder;
    }

    @Override
    public int getMetricsCategory() {
        // TODO(chelseahao): update metrics id
        return 0;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return mDialogBuilder.build();
    }

    static void show(Fragment host, DialogBuilder dialogBuilder) {
        FragmentManager manager = host.getChildFragmentManager();
        (new AudioStreamsDialogFragment(dialogBuilder)).show(manager, TAG);
    }

    static class DialogBuilder {
        private final Context mContext;
        private final AlertDialog.Builder mBuilder;
        private String mTitle;
        private String mSubTitle1;
        private String mSubTitle2;
        private String mLeftButtonText;
        private String mRightButtonText;
        private Consumer<AlertDialog> mLeftButtonOnClickListener;
        private Consumer<AlertDialog> mRightButtonOnClickListener;

        DialogBuilder(Context context) {
            mContext = context;
            mBuilder = new AlertDialog.Builder(context);
        }

        DialogBuilder setTitle(String title) {
            mTitle = title;
            return this;
        }

        DialogBuilder setSubTitle1(String subTitle1) {
            mSubTitle1 = subTitle1;
            return this;
        }

        DialogBuilder setSubTitle2(String subTitle2) {
            mSubTitle2 = subTitle2;
            return this;
        }

        DialogBuilder setLeftButtonText(String text) {
            mLeftButtonText = text;
            return this;
        }

        DialogBuilder setLeftButtonOnClickListener(Consumer<AlertDialog> listener) {
            mLeftButtonOnClickListener = listener;
            return this;
        }

        DialogBuilder setRightButtonText(String text) {
            mRightButtonText = text;
            return this;
        }

        DialogBuilder setRightButtonOnClickListener(Consumer<AlertDialog> listener) {
            mRightButtonOnClickListener = listener;
            return this;
        }

        AlertDialog build() {
            View rootView =
                    LayoutInflater.from(mContext)
                            .inflate(R.xml.bluetooth_audio_streams_dialog, /* parent= */ null);

            AlertDialog dialog = mBuilder.setView(rootView).setCancelable(false).create();
            dialog.setCanceledOnTouchOutside(false);

            TextView title = rootView.requireViewById(R.id.dialog_title);
            title.setText(mTitle);

            if (!Strings.isNullOrEmpty(mSubTitle1)) {
                TextView subTitle1 = rootView.requireViewById(R.id.dialog_subtitle);
                subTitle1.setText(mSubTitle1);
                subTitle1.setVisibility(View.VISIBLE);
            }
            if (!Strings.isNullOrEmpty(mSubTitle2)) {
                TextView subTitle2 = rootView.requireViewById(R.id.dialog_subtitle_2);
                subTitle2.setText(mSubTitle2);
                subTitle2.setVisibility(View.VISIBLE);
            }
            if (!Strings.isNullOrEmpty(mLeftButtonText)) {
                Button leftButton = rootView.requireViewById(R.id.left_button);
                leftButton.setText(mLeftButtonText);
                leftButton.setVisibility(View.VISIBLE);
                leftButton.setOnClickListener(unused -> mLeftButtonOnClickListener.accept(dialog));
            }
            if (!Strings.isNullOrEmpty(mRightButtonText)) {
                Button rightButton = rootView.requireViewById(R.id.right_button);
                rightButton.setText(mRightButtonText);
                rightButton.setVisibility(View.VISIBLE);
                rightButton.setOnClickListener(
                        unused -> mRightButtonOnClickListener.accept(dialog));
            }

            return dialog;
        }
    }
}
+46 −7
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -92,6 +94,7 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
            new ConcurrentHashMap<>();
    private TimedSourceFromQrCode mTimedSourceFromQrCode;
    private AudioStreamsProgressCategoryPreference mCategoryPreference;
    private AudioStreamsDashboardFragment mFragment;

    public AudioStreamsProgressCategoryController(Context context, String preferenceKey) {
        super(context, preferenceKey);
@@ -135,10 +138,13 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
        mExecutor.execute(this::stopScanning);
    }

    void setFragment(AudioStreamsDashboardFragment fragment) {
        mFragment = fragment;
    }

    void setSourceFromQrCode(BluetoothLeBroadcastMetadata source) {
        mTimedSourceFromQrCode =
                new TimedSourceFromQrCode(
                        mContext, source, () -> handleSourceLost(source.getBroadcastId()));
                new TimedSourceFromQrCode(source, () -> handleSourceLost(source.getBroadcastId()));
    }

    void setScanning(boolean isScanning) {
@@ -324,6 +330,8 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
            startScanning();
        } else {
            stopScanning();
            ThreadUtils.postOnMainThread(
                    () -> AudioStreamsDialogFragment.show(mFragment, getNoLeDeviceDialog()));
        }
    }

@@ -463,15 +471,41 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
        alertDialog.show();
    }

    private static class TimedSourceFromQrCode {
    private AudioStreamsDialogFragment.DialogBuilder getNoLeDeviceDialog() {
        return new AudioStreamsDialogFragment.DialogBuilder(mContext)
                .setTitle("Connect compatible headphones")
                .setSubTitle1(
                        "To listen to an audio stream, first connect headphones that support LE"
                                + " Audio to this device. Learn more")
                .setLeftButtonText("Close")
                .setLeftButtonOnClickListener(AlertDialog::dismiss)
                .setRightButtonText("Connect a device")
                .setRightButtonOnClickListener(
                        unused ->
                                mContext.startActivity(
                                        new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)));
    }

    private AudioStreamsDialogFragment.DialogBuilder getBroadcastUnavailableDialog(
            String broadcastName) {
        return new AudioStreamsDialogFragment.DialogBuilder(mContext)
                .setTitle("Audio stream isn't available")
                .setSubTitle1(broadcastName)
                .setSubTitle2("This audio stream isn't playing anything right now")
                .setLeftButtonText("Close")
                .setLeftButtonOnClickListener(AlertDialog::dismiss)
                .setRightButtonText("Retry")
                // TODO(chelseahao): Add retry action
                .setRightButtonOnClickListener(AlertDialog::dismiss);
    }

    private class TimedSourceFromQrCode {
        private static final int WAIT_FOR_SYNC_TIMEOUT_MILLIS = 15000;
        private final CountDownTimer mTimer;
        private BluetoothLeBroadcastMetadata mSourceFromQrCode;

        private TimedSourceFromQrCode(
                Context context,
                BluetoothLeBroadcastMetadata sourceFromQrCode,
                Runnable timeoutAction) {
                BluetoothLeBroadcastMetadata sourceFromQrCode, Runnable timeoutAction) {
            mSourceFromQrCode = sourceFromQrCode;
            mTimer =
                    new CountDownTimer(WAIT_FOR_SYNC_TIMEOUT_MILLIS, 1000) {
@@ -481,7 +515,12 @@ public class AudioStreamsProgressCategoryController extends BasePreferenceContro
                        @Override
                        public void onFinish() {
                            timeoutAction.run();
                            AudioSharingUtils.toastMessage(context, "Audio steam isn't available");
                            ThreadUtils.postOnMainThread(
                                    () ->
                                            AudioStreamsDialogFragment.show(
                                                    mFragment,
                                                    getBroadcastUnavailableDialog(
                                                            sourceFromQrCode.getBroadcastName())));
                        }
                    };
        }