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

Commit e8b3081f authored by chelseahao's avatar chelseahao
Browse files

[Audiosharing] Display broadcast QR code.

Bug: 308368124
Test: Manual
Change-Id: I19ec1d15ab26e178b4bb1d9ea1d84dcce0dcc109
parent 56f5e53a
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2023 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.
  -->

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingLeft="25dp"
        android:paddingRight="25dp"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@android:id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="start"
            android:textSize="15sp"
            android:textColor="?android:attr/textColorPrimary"
            android:text="Scan this QR code with another device connected to LE audio headphones to start sharing audio"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical"
            android:paddingTop="70dp">

            <ImageView
                android:id="@+id/qrcode_view"
                android:layout_width="@dimen/qrcode_size"
                android:layout_height="@dimen/qrcode_size"
                android:src="@android:color/transparent"/>
        </LinearLayout>

    </LinearLayout>

</LinearLayout>
 No newline at end of file
+9 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.settings.connecteddevice.audiosharing;

import android.app.settings.SettingsEnums;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageButton;
@@ -23,6 +24,7 @@ import android.widget.ImageButton;
import androidx.preference.PreferenceViewHolder;

import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.widget.ValidatedEditTextPreference;

public class AudioSharingNamePreference extends ValidatedEditTextPreference {
@@ -60,5 +62,12 @@ public class AudioSharingNamePreference extends ValidatedEditTextPreference {
        super.onBindViewHolder(holder);
        final ImageButton shareButton = (ImageButton) holder.findViewById(R.id.button_icon);
        shareButton.setImageDrawable(getContext().getDrawable(R.drawable.ic_qrcode_24dp));
        shareButton.setOnClickListener(
                unused ->
                        new SubSettingLauncher(getContext())
                                .setTitleText("Audio sharing QR code")
                                .setDestination(AudioStreamsQrCodeFragment.class.getName())
                                .setSourceMetricsCategory(SettingsEnums.AUDIO_SHARING_SETTINGS)
                                .launch());
    }
}
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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;

import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.InstrumentedFragment;
import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt;
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.qrcode.QrCodeGenerator;

import com.google.zxing.WriterException;

import java.util.Optional;

public class AudioStreamsQrCodeFragment extends InstrumentedFragment {
    private static final String TAG = "AudioStreamsQrCodeFragment";

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

    @Override
    public final View onCreateView(
            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.xml.bluetooth_audio_streams_qr_code, container, false);
        getQrCodeBitmap().ifPresent(
                bm -> ((ImageView) view.requireViewById(R.id.qrcode_view)).setImageBitmap(bm));
        return view;
    }

    private Optional<Bitmap> getQrCodeBitmap() {
        String broadcastMetadata = getBroadcastMetadataQrCode();
        if (broadcastMetadata.isEmpty()) {
            Log.d(TAG, "onCreateView: broadcastMetadata is empty!");
            return Optional.empty();
        }

        try {
            int qrcodeSize = getContext().getResources().getDimensionPixelSize(R.dimen.qrcode_size);
            Bitmap bitmap = QrCodeGenerator.encodeQrCode(broadcastMetadata, qrcodeSize);
            return Optional.of(bitmap);
        } catch (WriterException e) {
            Log.d(TAG, "onCreateView: broadcastMetadata "
                    + broadcastMetadata
                    + " qrCode generation exception "
                    + e);
        }

        return Optional.empty();
    }

    private String getBroadcastMetadataQrCode() {
        LocalBluetoothLeBroadcast localBluetoothLeBroadcast =
                Utils.getLocalBtManager(getActivity())
                        .getProfileManager()
                        .getLeAudioBroadcastProfile();
        if (localBluetoothLeBroadcast == null) {
            Log.d(TAG, "getBroadcastMetadataQrCode: localBluetoothLeBroadcast is null!");
            return "";
        }

        BluetoothLeBroadcastMetadata metadata =
                localBluetoothLeBroadcast.getLatestBluetoothLeBroadcastMetadata();
        if (metadata == null) {
            Log.d(TAG, "getBroadcastMetadataQrCode: metadata is null!");
            return "";
        }

        return BluetoothLeBroadcastMetadataExt.INSTANCE.toQrCodeString(metadata);
    }
}