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

Commit ea1eaf74 authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Remove code duplications

Also prevent callback be called before SysMRP created

Test: pass MediaRouter cts
Change-Id: I0cde791fc73a33de5d42dcb6e550016644301ffd
parent e8d6f95b
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -166,6 +166,20 @@ class BluetoothRouteProvider {
        }
    }

    @Nullable
    MediaRoute2Info getSelectedRoute() {
        return (mSelectedRoute == null) ? null : mSelectedRoute.route;
    }

    @NonNull
    List<MediaRoute2Info> getTransferableRoutes() {
        List<MediaRoute2Info> routes = getAllBluetoothRoutes();
        if (mSelectedRoute != null) {
            routes.remove(mSelectedRoute.route);
        }
        return routes;
    }

    @NonNull
    List<MediaRoute2Info> getAllBluetoothRoutes() {
        ArrayList<MediaRoute2Info> routes = new ArrayList<>();
@@ -175,9 +189,12 @@ class BluetoothRouteProvider {
        return routes;
    }

    @Nullable
    String getSelectedRouteId() {
        return mSelectedRoute == null ? null : mSelectedRoute.route.getId();
    boolean setSelectedRouteVolume(int volume) {
        if (mSelectedRoute == null) return false;
        mSelectedRoute.route = new MediaRoute2Info.Builder(mSelectedRoute.route)
                .setVolume(volume)
                .build();
        return true;
    }

    private void notifyBluetoothRoutesUpdated() {
+59 −100
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.media;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -42,15 +41,13 @@ import android.text.TextUtils;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * Provides routes for local playbacks such as phone speaker, wired headset, or Bluetooth speakers.
 */
// TODO: check thread safety. We may need to use lock to protect variables.
class SystemMediaRoute2Provider extends MediaRoute2Provider {
    private static final String TAG = "MR2SystemProvider";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -68,19 +65,16 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
            SystemMediaRoute2Provider.class.getPackageName$(),
            SystemMediaRoute2Provider.class.getName());

    @GuardedBy("mLock")
    private String mSelectedRouteId;
    MediaRoute2Info mDefaultRoute;
    @NonNull List<MediaRoute2Info> mBluetoothRoutes = Collections.EMPTY_LIST;
    final AudioRoutesInfo mCurAudioRoutesInfo = new AudioRoutesInfo();

    final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
        @Override
        public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
            mHandler.post(new Runnable() {
                @Override public void run() {
                    updateAudioRoutes(newRoutes);
                }
            mHandler.post(() -> {
                updateDefaultRoute(newRoutes);
                notifyProviderState();
            });
        }
    };
@@ -97,11 +91,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioService = IAudioService.Stub.asInterface(
                ServiceManager.getService(Context.AUDIO_SERVICE));
        AudioRoutesInfo newAudioRoutes = null;
        try {
            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
        } catch (RemoteException e) {
        }
        updateDefaultRoute(newAudioRoutes);

        initializeDefaultRoute();
        mBtRouteProvider = BluetoothRouteProvider.getInstance(context, (routes) -> {
            mBluetoothRoutes = routes;
            publishRoutes();
            publishProviderState();

            boolean sessionInfoChanged;
            synchronized (mLock) {
@@ -111,7 +109,15 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
                notifySessionInfoUpdated();
            }
        });
        initializeSessionInfo();

        mHandler.post(() -> notifyProviderState());

        //TODO: clean up this
        // This is required because it is not instantiated in the main thread and
        // BluetoothRoutesUpdatedListener can be called before here
        synchronized (mLock) {
            updateSessionInfosIfNeededLocked();
        }

        mContext.registerReceiver(new VolumeChangeReceiver(),
                new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
@@ -164,53 +170,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
        // Do nothing since we don't support grouping volume yet.
    }

    private void initializeDefaultRoute() {
        mDefaultRoute = new MediaRoute2Info.Builder(
                DEFAULT_ROUTE_ID,
                mContext.getResources().getText(R.string.default_audio_route_name).toString())
                .setVolumeHandling(mAudioManager.isVolumeFixed()
                        ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
                        : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
                .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
                .addFeature(FEATURE_LIVE_AUDIO)
                .addFeature(FEATURE_LIVE_VIDEO)
                .build();

        AudioRoutesInfo newAudioRoutes = null;
        try {
            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
        } catch (RemoteException e) {
        }
        if (newAudioRoutes != null) {
            // This will select the active BT route if there is one and the current
            // selected route is the default system route, or if there is no selected
            // route yet.
            updateAudioRoutes(newAudioRoutes);
        }
    }

    private void initializeSessionInfo() {
        mBluetoothRoutes = mBtRouteProvider.getAllBluetoothRoutes();

        MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
        builder.addRoute(mDefaultRoute);
        for (MediaRoute2Info route : mBluetoothRoutes) {
            builder.addRoute(route);
        }
        setProviderState(builder.build());
        mHandler.post(() -> notifyProviderState());

        //TODO: clean up this
        // This is required because it is not instantiated in the main thread and
        // BluetoothRoutesUpdatedListener can be called before this function
        synchronized (mLock) {
            updateSessionInfosIfNeededLocked();
        }
    }

    private void updateAudioRoutes(AudioRoutesInfo newRoutes) {
    private void updateDefaultRoute(AudioRoutesInfo newRoutes) {
        int name = R.string.default_audio_route_name;
        if (newRoutes != null) {
            mCurAudioRoutesInfo.mainType = newRoutes.mainType;
            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0
                    || (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
@@ -222,7 +184,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
                name = com.android.internal.R.string.default_audio_route_name_usb;
            }

        }
        mDefaultRoute = new MediaRoute2Info.Builder(
                DEFAULT_ROUTE_ID, mContext.getResources().getText(name).toString())
                .setVolumeHandling(mAudioManager.isVolumeFixed()
@@ -232,9 +194,20 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
                .setVolume(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC))
                .addFeature(FEATURE_LIVE_AUDIO)
                .addFeature(FEATURE_LIVE_VIDEO)
                .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
                .build();
        updateProviderState();
    }

        publishRoutes();
    private void updateProviderState() {
        MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
        builder.addRoute(mDefaultRoute);
        if (mBtRouteProvider != null) {
            for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
                builder.addRoute(route);
            }
        }
        setProviderState(builder.build());
    }

    /**
@@ -246,20 +219,20 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
        RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
                SYSTEM_SESSION_ID, "" /* clientPackageName */)
                .setSystemSession(true);
        String activeBtDeviceAddress = mBtRouteProvider.getSelectedRouteId();
        mSelectedRouteId = TextUtils.isEmpty(activeBtDeviceAddress) ? mDefaultRoute.getId()
                : activeBtDeviceAddress;
        builder.addSelectedRoute(mSelectedRouteId);

        if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
        MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
        if (selectedRoute == null) {
            selectedRoute = mDefaultRoute;
        } else {
            builder.addTransferableRoute(mDefaultRoute.getId());
        }
        mSelectedRouteId = selectedRoute.getId();
        builder.addSelectedRoute(mSelectedRouteId);

        for (MediaRoute2Info route : mBluetoothRoutes) {
            if (!TextUtils.equals(mSelectedRouteId, route.getId())) {
        for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
            builder.addTransferableRoute(route.getId());
        }
        }


        RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build();
        if (Objects.equals(oldSessionInfo, newSessionInfo)) {
@@ -271,13 +244,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
        }
    }

    void publishRoutes() {
        MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
        builder.addRoute(mDefaultRoute);
        for (MediaRoute2Info route : mBluetoothRoutes) {
            builder.addRoute(route);
        }
        setAndNotifyProviderState(builder.build());
    void publishProviderState() {
        updateProviderState();
        notifyProviderState();
    }

    void notifySessionInfoUpdated() {
@@ -306,24 +275,14 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
                    AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);

            if (newVolume != oldVolume) {
                String activeBtDeviceAddress = mBtRouteProvider.getSelectedRouteId();
                if (!TextUtils.isEmpty(activeBtDeviceAddress)) {
                    for (int i = mBluetoothRoutes.size() - 1; i >= 0; i--) {
                        MediaRoute2Info route = mBluetoothRoutes.get(i);
                        if (TextUtils.equals(activeBtDeviceAddress, route.getId())) {
                            mBluetoothRoutes.set(i,
                                    new MediaRoute2Info.Builder(route)
                                            .setVolume(newVolume)
                                            .build());
                            break;
                        }
                    }
                } else {
                if (TextUtils.equals(mDefaultRoute.getId(), mSelectedRouteId)) {
                    mDefaultRoute = new MediaRoute2Info.Builder(mDefaultRoute)
                            .setVolume(newVolume)
                            .build();
                } else {
                    mBtRouteProvider.setSelectedRouteVolume(newVolume);
                }
                publishRoutes();
                publishProviderState();
            }
        }
    }