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

Commit fdf0b689 authored by Betty Chang's avatar Betty Chang Committed by Automerger Merge Worker
Browse files

Merge "[LE] Broadcast API integration for MediaOutputBroadcastDialog" into tm-dev am: aaec02b8

parents d37fb538 aaec02b8
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
@@ -19,11 +19,19 @@
    android:layout_width="match_parent"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="?android:attr/dialogPreferredPadding"
    android:paddingLeft="?android:attr/dialogPreferredPadding"
    android:paddingRight="?android:attr/dialogPreferredPadding">
    android:paddingRight="?android:attr/dialogPreferredPadding"
    android:orientation="vertical">
    <EditText
    <EditText
        android:id="@+id/broadcast_edit_text"
        android:id="@+id/broadcast_edit_text"
        android:layout_width="match_parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="48dp"
        android:minHeight="48dp"
        android:textAlignment="viewStart"/>
        android:textAlignment="viewStart"/>
    <TextView
        android:id="@+id/broadcast_error_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        style="@style/TextAppearance.ErrorText"
        android:visibility="invisible"/>
</LinearLayout>
</LinearLayout>
 No newline at end of file
+5 −0
Original line number Original line Diff line number Diff line
@@ -2293,6 +2293,11 @@
    <string name="media_output_broadcast_starting">Starting&#8230;</string>
    <string name="media_output_broadcast_starting">Starting&#8230;</string>
    <!-- The button text when Broadcast start failed [CHAR LIMIT=60] -->
    <!-- The button text when Broadcast start failed [CHAR LIMIT=60] -->
    <string name="media_output_broadcast_start_failed">Can\u2019t broadcast</string>
    <string name="media_output_broadcast_start_failed">Can\u2019t broadcast</string>
    <!-- The error message when Broadcast name/code update failed [CHAR LIMIT=60] -->
    <string name="media_output_broadcast_update_error">Can\u2019t save. Try again.</string>
    <!-- The error message when Broadcast name/code update failed and can't change again[CHAR LIMIT=60] -->
    <string name="media_output_broadcast_last_update_error">Can\u2019t save.</string>



    <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]-->
    <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]-->
    <string name="build_number_clip_data_label">Build number</string>
    <string name="build_number_clip_data_label">Build number</string>
+83 −44
Original line number Original line Diff line number Diff line
@@ -59,11 +59,14 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
    private ImageView mBroadcastCodeEye;
    private ImageView mBroadcastCodeEye;
    private Boolean mIsPasswordHide = true;
    private Boolean mIsPasswordHide = true;
    private ImageView mBroadcastCodeEdit;
    private ImageView mBroadcastCodeEdit;
    private Button mStopButton;
    private AlertDialog mAlertDialog;
    private TextView mBroadcastErrorMessage;


    static final int METADATA_BROADCAST_NAME = 0;
    static final int METADATA_BROADCAST_NAME = 0;
    static final int METADATA_BROADCAST_CODE = 1;
    static final int METADATA_BROADCAST_CODE = 1;


    private static final int MAX_BROADCAST_INFO_UPDATE = 3;

    MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar,
    MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar,
            BroadcastSender broadcastSender, MediaOutputController mediaOutputController) {
            BroadcastSender broadcastSender, MediaOutputController mediaOutputController) {
        super(context, broadcastSender, mediaOutputController);
        super(context, broadcastSender, mediaOutputController);
@@ -118,14 +121,18 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
        return View.VISIBLE;
        return View.VISIBLE;
    }
    }


    // TODO(b/222674827): To get the information from BluetoothLeBroadcastMetadata(Broadcast code)
    @Override
    // and BluetoothLeAudioContentMetadata(Program info) when start Broadcast is successful.
    public void onStopButtonClick() {
    private String getBroadcastMetaDataInfo(int metaData) {
        mMediaOutputController.stopBluetoothLeBroadcast();
        switch (metaData) {
        dismiss();
    }

    private String getBroadcastMetadataInfo(int metadata) {
        switch (metadata) {
            case METADATA_BROADCAST_NAME:
            case METADATA_BROADCAST_NAME:
                return "";
                return mMediaOutputController.getBroadcastName();
            case METADATA_BROADCAST_CODE:
            case METADATA_BROADCAST_CODE:
                return "";
                return mMediaOutputController.getBroadcastCode();
            default:
            default:
                return "";
                return "";
        }
        }
@@ -164,13 +171,8 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
            launchBroadcastUpdatedDialog(true, mBroadcastCode.getText().toString());
            launchBroadcastUpdatedDialog(true, mBroadcastCode.getText().toString());
        });
        });


        mBroadcastName.setText(getBroadcastMetaDataInfo(METADATA_BROADCAST_NAME));
        mBroadcastName.setText(getBroadcastMetadataInfo(METADATA_BROADCAST_NAME));
        mBroadcastCode.setText(getBroadcastMetaDataInfo(METADATA_BROADCAST_CODE));
        mBroadcastCode.setText(getBroadcastMetadataInfo(METADATA_BROADCAST_CODE));

        mStopButton = getDialogView().requireViewById(R.id.stop);
        mStopButton.setOnClickListener(v -> {
            stopBroadcast();
        });
    }
    }


    private void inflateBroadcastInfoArea() {
    private void inflateBroadcastInfoArea() {
@@ -179,16 +181,16 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
    }
    }


    private void setQrCodeView() {
    private void setQrCodeView() {
        //get the MetaData, and convert to BT QR code format.
        //get the Metadata, and convert to BT QR code format.
        String broadcastMetaData = getBroadcastMetaData();
        String broadcastMetadata = getBroadcastMetadata();
        if (broadcastMetaData.isEmpty()) {
        if (broadcastMetadata.isEmpty()) {
            //TDOD(b/226708424) Error handling for unable to generate the QR code bitmap
            //TDOD(b/226708424) Error handling for unable to generate the QR code bitmap
            return;
            return;
        }
        }
        try {
        try {
            final int qrcodeSize = getContext().getResources().getDimensionPixelSize(
            final int qrcodeSize = getContext().getResources().getDimensionPixelSize(
                    R.dimen.media_output_qrcode_size);
                    R.dimen.media_output_qrcode_size);
            final Bitmap bmp = QrCodeGenerator.encodeQrCode(broadcastMetaData, qrcodeSize);
            final Bitmap bmp = QrCodeGenerator.encodeQrCode(broadcastMetadata, qrcodeSize);
            mBroadcastQrCodeView.setImageBitmap(bmp);
            mBroadcastQrCodeView.setImageBitmap(bmp);
        } catch (WriterException e) {
        } catch (WriterException e) {
            //TDOD(b/226708424) Error handling for unable to generate the QR code bitmap
            //TDOD(b/226708424) Error handling for unable to generate the QR code bitmap
@@ -203,50 +205,87 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
        mIsPasswordHide = !mIsPasswordHide;
        mIsPasswordHide = !mIsPasswordHide;
    }
    }


    private void launchBroadcastUpdatedDialog(boolean isPassword, String editString) {
    private void launchBroadcastUpdatedDialog(boolean isBroadcastCode, String editString) {
        final View layout = LayoutInflater.from(mContext).inflate(
        final View layout = LayoutInflater.from(mContext).inflate(
                R.layout.media_output_broadcast_update_dialog, null);
                R.layout.media_output_broadcast_update_dialog, null);
        final EditText editText = layout.requireViewById(R.id.broadcast_edit_text);
        final EditText editText = layout.requireViewById(R.id.broadcast_edit_text);
        editText.setText(editString);
        editText.setText(editString);
        final AlertDialog alertDialog = new Builder(mContext)
        mBroadcastErrorMessage = layout.requireViewById(R.id.broadcast_error_message);
                .setTitle(isPassword ? R.string.media_output_broadcast_code
        mAlertDialog = new Builder(mContext)
                .setTitle(isBroadcastCode ? R.string.media_output_broadcast_code
                    : R.string.media_output_broadcast_name)
                    : R.string.media_output_broadcast_name)
                .setView(layout)
                .setView(layout)
                .setNegativeButton(android.R.string.cancel, null)
                .setNegativeButton(android.R.string.cancel, null)
                .setPositiveButton(R.string.media_output_broadcast_dialog_save,
                .setPositiveButton(R.string.media_output_broadcast_dialog_save,
                        (d, w) -> {
                        (d, w) -> {
                            updateBroadcast(isPassword, editText.getText().toString());
                            updateBroadcastInfo(isBroadcastCode, editText.getText().toString());
                        })
                        })
                .create();
                .create();


        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
        SystemUIDialog.setShowForAllUsers(alertDialog, true);
        SystemUIDialog.setShowForAllUsers(mAlertDialog, true);
        SystemUIDialog.registerDismissListener(alertDialog);
        SystemUIDialog.registerDismissListener(mAlertDialog);
        alertDialog.show();
        mAlertDialog.show();
    }
    }


    /**
    private String getBroadcastMetadata() {
     * TODO(b/222674827): The method should be get the BluetoothLeBroadcastMetadata after
        return mMediaOutputController.getBroadcastMetadata();
     * starting the Broadcast session successfully. Then we will follow the BT QR code format
     * that convert BluetoothLeBroadcastMetadata object to String format.
     */
    private String getBroadcastMetaData() {
        return "TEST";
    }
    }


    /**
    private void updateBroadcastInfo(boolean isBroadcastCode, String updatedString) {
     * TODO(b/222676140): These method are about the LE Audio Broadcast API. The framework APIS
        Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
     * will be wrapped in SettingsLib. And the UI will be executed through it.
        if (positiveBtn != null) {
     */
            positiveBtn.setEnabled(false);
    private void updateBroadcast(boolean isPassword, String updatedString) {
        }


        if (isBroadcastCode) {
            handleBroadcastCodeUpdated(updatedString);
        } else {
            handleBroadcastNameUpdated(updatedString);
        }
    }
    }


    /**
    private void handleBroadcastNameUpdated(String name) {
     * TODO(b/222676140): These method are about the LE Audio Broadcast API. The framework APIS
        // TODO(b/230473995) Add the retry mechanism and error handling when update fails
     * will be wrapped in SettingsLib. And the UI will be executed through it.
        String currentName = mMediaOutputController.getBroadcastName();
     */
        int retryCount = MAX_BROADCAST_INFO_UPDATE;
    private void stopBroadcast() {
        mMediaOutputController.setBroadcastName(name);
        dismiss();
        if (!mMediaOutputController.updateBluetoothLeBroadcast()) {
            mMediaOutputController.setBroadcastName(currentName);
            handleLeUpdateBroadcastFailed(retryCount);
        }
    }

    private void handleBroadcastCodeUpdated(String newPassword) {
        // TODO(b/230473995) Add the retry mechanism and error handling when update fails
        String currentPassword = mMediaOutputController.getBroadcastCode();
        int retryCount = MAX_BROADCAST_INFO_UPDATE;
        if (!mMediaOutputController.stopBluetoothLeBroadcast()) {
            mMediaOutputController.setBroadcastCode(currentPassword);
            handleLeUpdateBroadcastFailed(retryCount);
            return;
        }

        mMediaOutputController.setBroadcastCode(newPassword);
        if (!mMediaOutputController.startBluetoothLeBroadcast()) {
            mMediaOutputController.setBroadcastCode(currentPassword);
            handleLeUpdateBroadcastFailed(retryCount);
            return;
        }

        mAlertDialog.dismiss();
    }

    private void handleLeUpdateBroadcastFailed(int retryCount) {
        final Button positiveBtn = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
        mBroadcastErrorMessage.setVisibility(View.VISIBLE);
        if (retryCount < MAX_BROADCAST_INFO_UPDATE) {
            if (positiveBtn != null) {
                positiveBtn.setEnabled(true);
            }
            mBroadcastErrorMessage.setText(R.string.media_output_broadcast_update_error);
        } else {
            mBroadcastErrorMessage.setText(R.string.media_output_broadcast_last_update_error);
        }
    }
    }
}
}
+62 −1
Original line number Original line Diff line number Diff line
@@ -63,7 +63,6 @@ import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.media.BluetoothMediaDevice;
import com.android.settingslib.media.InfoMediaManager;
import com.android.settingslib.media.InfoMediaManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.LocalMediaManager;
import com.android.settingslib.media.MediaDevice;
import com.android.settingslib.media.MediaDevice;
@@ -79,6 +78,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.phone.SystemUIDialog;


import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.List;
import java.util.List;
@@ -678,6 +678,56 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
        mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
        mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
    }
    }


    String getBroadcastName() {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "getBroadcastName: LE Audio Broadcast is null");
            return "";
        }
        return broadcast.getProgramInfo();
    }

    void setBroadcastName(String broadcastName) {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "setBroadcastName: LE Audio Broadcast is null");
            return;
        }
        broadcast.setProgramInfo(broadcastName);
    }

    String getBroadcastCode() {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "getBroadcastCode: LE Audio Broadcast is null");
            return "";
        }
        return new String(broadcast.getBroadcastCode(), StandardCharsets.UTF_8);
    }

    void setBroadcastCode(String broadcastCode) {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "setBroadcastCode: LE Audio Broadcast is null");
            return;
        }
        broadcast.setBroadcastCode(broadcastCode.getBytes(StandardCharsets.UTF_8));
    }

    String getBroadcastMetadata() {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "getBroadcastMetadata: LE Audio Broadcast is null");
            return "";
        }
        return broadcast.getLocalBluetoothLeBroadcastMetaData().convertToQrCodeString();
    }

    boolean isActiveRemoteDevice(@NonNull MediaDevice device) {
    boolean isActiveRemoteDevice(@NonNull MediaDevice device) {
        final List<String> features = device.getFeatures();
        final List<String> features = device.getFeatures();
        return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)
        return (features.contains(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)
@@ -723,6 +773,17 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
        return true;
        return true;
    }
    }


    boolean updateBluetoothLeBroadcast() {
        LocalBluetoothLeBroadcast broadcast =
                mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
        if (broadcast == null) {
            Log.d(TAG, "The broadcast profile is null");
            return false;
        }
        broadcast.updateBroadcast(getAppSourceName(), /*language*/ null);
        return true;
    }

    void registerLeBroadcastServiceCallBack(
    void registerLeBroadcastServiceCallBack(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull BluetoothLeBroadcast.Callback callback) {
            @NonNull BluetoothLeBroadcast.Callback callback) {