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

Commit d7ff18da authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Restore the selected route when an app starts to make sound" into oc-dr1-dev

parents b978569f 972f27b9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,4 +21,5 @@ package android.media;
 */
oneway interface IMediaRouterClient {
    void onStateChanged();
    void onRestoreRoute();
}
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ interface IMediaRouterService {
    void unregisterClient(IMediaRouterClient client);

    MediaRouterClientState getState(IMediaRouterClient client);
    boolean isPlaybackActive(IMediaRouterClient client);

    void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
    void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
+57 −18
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ public class MediaRouter {
        RouteInfo mBluetoothA2dpRoute;

        RouteInfo mSelectedRoute;
        RouteInfo mSystemAudioRoute;

        final boolean mCanConfigureWifiDisplays;
        boolean mActivelyScanningWifiDisplays;
@@ -149,6 +150,7 @@ public class MediaRouter {
            }

            addRouteStatic(mDefaultAudioVideo);
            mSystemAudioRoute = mDefaultAudioVideo;

            // This will select the active wifi display route if there is one.
            updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus());
@@ -197,8 +199,8 @@ public class MediaRouter {
                } else {
                    name = com.android.internal.R.string.default_audio_route_name;
                }
                sStatic.mDefaultAudioVideo.mNameResId = name;
                dispatchRouteChanged(sStatic.mDefaultAudioVideo);
                mDefaultAudioVideo.mNameResId = name;
                dispatchRouteChanged(mDefaultAudioVideo);
                updated = true;
            }

@@ -207,22 +209,28 @@ public class MediaRouter {
            if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) {
                mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
                if (mCurAudioRoutesInfo.bluetoothName != null) {
                    if (sStatic.mBluetoothA2dpRoute == null) {
                        final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
                    if (mBluetoothA2dpRoute == null) {
                        // BT connected
                        final RouteInfo info = new RouteInfo(mSystemCategory);
                        info.mName = mCurAudioRoutesInfo.bluetoothName;
                        info.mDescription = sStatic.mResources.getText(
                        info.mDescription = mResources.getText(
                                com.android.internal.R.string.bluetooth_a2dp_audio_route_name);
                        info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
                        info.mDeviceType = RouteInfo.DEVICE_TYPE_BLUETOOTH;
                        sStatic.mBluetoothA2dpRoute = info;
                        addRouteStatic(sStatic.mBluetoothA2dpRoute);
                        mBluetoothA2dpRoute = info;
                        addRouteStatic(mBluetoothA2dpRoute);
                        mSystemAudioRoute = mBluetoothA2dpRoute;
                        selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
                    } else {
                        sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName;
                        dispatchRouteChanged(sStatic.mBluetoothA2dpRoute);
                        mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName;
                        dispatchRouteChanged(mBluetoothA2dpRoute);
                    }
                } else if (sStatic.mBluetoothA2dpRoute != null) {
                    removeRouteStatic(sStatic.mBluetoothA2dpRoute);
                    sStatic.mBluetoothA2dpRoute = null;
                } else if (mBluetoothA2dpRoute != null) {
                    // BT disconnected
                    removeRouteStatic(mBluetoothA2dpRoute);
                    mBluetoothA2dpRoute = null;
                    mSystemAudioRoute = mDefaultAudioVideo;
                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false);
                }
                updated = true;
            }
@@ -230,11 +238,13 @@ public class MediaRouter {
            if (mBluetoothA2dpRoute != null) {
                final boolean a2dpEnabled = isBluetoothA2dpOn();
                if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
                    // A2DP off
                    mSystemAudioRoute = mDefaultAudioVideo;
                    updated = true;
                } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
                        a2dpEnabled) {
                    selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false);
                    // A2DP on or BT connected
                    mSystemAudioRoute = mBluetoothA2dpRoute;
                    updated = true;
                }
            }
@@ -471,7 +481,7 @@ public class MediaRouter {
        }

        RouteInfo makeGlobalRoute(MediaRouterClientState.RouteInfo globalRoute) {
            RouteInfo route = new RouteInfo(sStatic.mSystemCategory);
            RouteInfo route = new RouteInfo(mSystemCategory);
            route.mGlobalRouteId = globalRoute.id;
            route.mName = globalRoute.name;
            route.mDescription = globalRoute.description;
@@ -567,6 +577,17 @@ public class MediaRouter {
            return null;
        }

        boolean isPlaybackActive() {
            if (mClient != null) {
                try {
                    return mMediaRouterService.isPlaybackActive(mClient);
                } catch (RemoteException ex) {
                    Log.e(TAG, "Unable to retrieve playback active state.", ex);
                }
            }
            return false;
        }

        final class Client extends IMediaRouterClient.Stub {
            @Override
            public void onStateChanged() {
@@ -579,6 +600,19 @@ public class MediaRouter {
                    }
                });
            }

            @Override
            public void onRestoreRoute() {
                if ((mSelectedRoute != mDefaultAudioVideo && mSelectedRoute != mBluetoothA2dpRoute)
                        || mSelectedRoute == mSystemAudioRoute) {
                    return;
                }
                try {
                    sStatic.mAudioService.setBluetoothA2dpOn(mSelectedRoute == mBluetoothA2dpRoute);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error changing Bluetooth A2DP state", e);
                }
            }
        }
    }

@@ -909,7 +943,12 @@ public class MediaRouter {
        Log.v(TAG, "Selecting route: " + route);
        assert(route != null);
        final RouteInfo oldRoute = sStatic.mSelectedRoute;
        if (oldRoute == route) return;
        boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo
                || oldRoute == sStatic.mBluetoothA2dpRoute);
        if (oldRoute == route
                && (!wasDefaultOrBluetoothRoute || oldRoute == sStatic.mSystemAudioRoute)) {
            return;
        }
        if (!route.matchesTypes(types)) {
            Log.w(TAG, "selectRoute ignored; cannot select route with supported types " +
                    typesToString(route.getSupportedTypes()) + " into route types " +
@@ -918,8 +957,8 @@ public class MediaRouter {
        }

        final RouteInfo btRoute = sStatic.mBluetoothA2dpRoute;
        if (btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 &&
                (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
        if (sStatic.isPlaybackActive() && btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0
                && (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
            try {
                sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute);
                // TODO: Remove the following logging when no longer needed.
+104 −20
Original line number Diff line number Diff line
@@ -31,17 +31,22 @@ import android.util.SparseArray;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Monitors changes in audio playback and notify the newly started audio playback through the
 * {@link OnAudioPlaybackStartedListener}.
 * Monitors changes in audio playback, and notify the newly started audio playback through the
 * {@link OnAudioPlaybackStartedListener} and the activeness change through the
 * {@link OnAudioPlaybackActiveStateListener}.
 */
class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
    private static boolean DEBUG = MediaSessionService.DEBUG;
    private static String TAG = "AudioPlaybackMonitor";

    private static AudioPlaybackMonitor sInstance;

    /**
     * Called when audio playback is started for a given UID.
     */
@@ -49,22 +54,36 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
        void onAudioPlaybackStarted(int uid);
    }

    /**
     * Called when audio player state is changed.
     */
    interface OnAudioPlayerActiveStateChangedListener {
        void onAudioPlayerActiveStateChanged(int uid, boolean active);
    }

    private final Object mLock = new Object();
    private final Context mContext;
    private final OnAudioPlaybackStartedListener mListener;

    private Set<Integer> mActiveAudioPlaybackPlayerInterfaceIds = new HashSet<>();
    private Set<Integer> mActiveAudioPlaybackClientUids = new HashSet<>();
    private final List<OnAudioPlaybackStartedListener> mAudioPlaybackStartedListeners
            = new ArrayList<>();
    private final List<OnAudioPlayerActiveStateChangedListener>
            mAudioPlayerActiveStateChangedListeners = new ArrayList<>();
    private final Map<Integer, Integer> mAudioPlaybackStates = new HashMap<>();
    private final Set<Integer> mActiveAudioPlaybackClientUids = new HashSet<>();

    // Sorted array of UIDs that had active audio playback. (i.e. playing an audio/video)
    // The UID whose audio playback becomes active at the last comes first.
    // TODO(b/35278867): Find and use unique identifier for apps because apps may share the UID.
    private final IntArray mSortedAudioPlaybackClientUids = new IntArray();

    AudioPlaybackMonitor(Context context, IAudioService audioService,
            OnAudioPlaybackStartedListener listener) {
    static AudioPlaybackMonitor getInstance(Context context, IAudioService audioService) {
        if (sInstance == null) {
            sInstance = new AudioPlaybackMonitor(context, audioService);
        }
        return sInstance;
    }

    private AudioPlaybackMonitor(Context context, IAudioService audioService) {
        mContext = context;
        mListener = listener;
        try {
            audioService.registerPlaybackCallback(this);
        } catch (RemoteException e) {
@@ -84,9 +103,12 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
    public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
        final long token = Binder.clearCallingIdentity();
        try {
            Set<Integer> newActiveAudioPlaybackPlayerInterfaceIds = new HashSet<>();
            List<Integer> newActiveAudioPlaybackClientUids = new ArrayList<>();
            List<OnAudioPlayerActiveStateChangedListener> audioPlayerActiveStateChangedListeners;
            List<OnAudioPlaybackStartedListener> audioPlaybackStartedListeners;
            synchronized (mLock) {
                // Update mActiveAudioPlaybackClientUids and mSortedAudioPlaybackClientUids,
                // and find newly activated audio playbacks.
                mActiveAudioPlaybackClientUids.clear();
                for (AudioPlaybackConfiguration config : configs) {
                    // Ignore inactive (i.e. not playing) or PLAYER_TYPE_JAM_SOUNDPOOL
@@ -94,16 +116,14 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
                    // playback.
                    // Note that we shouldn't ignore PLAYER_TYPE_UNKNOWN because it might be OEM
                    // specific audio/video players.
                    if (!config.isActive()
                            || config.getPlayerType()
                    if (!config.isActive() || config.getPlayerType()
                            == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
                        continue;
                    }
                    mActiveAudioPlaybackClientUids.add(config.getClientUid());

                    newActiveAudioPlaybackPlayerInterfaceIds.add(config.getPlayerInterfaceId());
                    if (!mActiveAudioPlaybackPlayerInterfaceIds.contains(
                            config.getPlayerInterfaceId())) {
                    mActiveAudioPlaybackClientUids.add(config.getClientUid());
                    Integer oldState = mAudioPlaybackStates.get(config.getPlayerInterfaceId());
                    if (!isActiveState(oldState)) {
                        if (DEBUG) {
                            Log.d(TAG, "Found a new active media playback. " +
                                    AudioPlaybackConfiguration.toLogFriendlyString(config));
@@ -120,17 +140,76 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
                        mSortedAudioPlaybackClientUids.add(0, config.getClientUid());
                    }
                }
                mActiveAudioPlaybackPlayerInterfaceIds.clear();
                mActiveAudioPlaybackPlayerInterfaceIds = newActiveAudioPlaybackPlayerInterfaceIds;
                audioPlayerActiveStateChangedListeners = new ArrayList<>(
                        mAudioPlayerActiveStateChangedListeners);
                audioPlaybackStartedListeners = new ArrayList<>(mAudioPlaybackStartedListeners);
            }
            // Notify the change of audio playback states.
            for (AudioPlaybackConfiguration config : configs) {
                boolean wasActive = isActiveState(
                        mAudioPlaybackStates.get(config.getPlayerInterfaceId()));
                boolean isActive = config.isActive();
                if (wasActive != isActive) {
                    for (OnAudioPlayerActiveStateChangedListener listener
                            : audioPlayerActiveStateChangedListeners) {
                        listener.onAudioPlayerActiveStateChanged(config.getClientUid(),
                                isActive);
                    }
                }
            }
            // Notify the start of audio playback
            for (int uid : newActiveAudioPlaybackClientUids) {
                mListener.onAudioPlaybackStarted(uid);
                for (OnAudioPlaybackStartedListener listener : audioPlaybackStartedListeners) {
                    listener.onAudioPlaybackStarted(uid);
                }
            }
            mAudioPlaybackStates.clear();
            for (AudioPlaybackConfiguration config : configs) {
                mAudioPlaybackStates.put(config.getPlayerInterfaceId(), config.getPlayerState());
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    /**
     * Registers OnAudioPlaybackStartedListener.
     */
    public void registerOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) {
        synchronized (mLock) {
            mAudioPlaybackStartedListeners.add(listener);
        }
    }

    /**
     * Unregisters OnAudioPlaybackStartedListener.
     */
    public void unregisterOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) {
        synchronized (mLock) {
            mAudioPlaybackStartedListeners.remove(listener);
        }
    }

    /**
     * Registers OnAudioPlayerActiveStateChangedListener.
     */
    public void registerOnAudioPlayerActiveStateChangedListener(
            OnAudioPlayerActiveStateChangedListener listener) {
        synchronized (mLock) {
            mAudioPlayerActiveStateChangedListeners.add(listener);
        }
    }

    /**
     * Unregisters OnAudioPlayerActiveStateChangedListener.
     */
    public void unregisterOnAudioPlayerActiveStateChangedListener(
            OnAudioPlayerActiveStateChangedListener listener) {
        synchronized (mLock) {
            mAudioPlayerActiveStateChangedListeners.remove(listener);
        }
    }

    /**
     * Returns the sorted list of UIDs that have had active audio playback. (i.e. playing an
     * audio/video) The UID whose audio playback becomes active at the last comes first.
@@ -167,7 +246,8 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
                if (mSortedAudioPlaybackClientUids.get(i) == mediaButtonSessionUid) {
                    break;
                }
                if (userId == UserHandle.getUserId(mSortedAudioPlaybackClientUids.get(i))) {
                int uid = mSortedAudioPlaybackClientUids.get(i);
                if (userId == UserHandle.getUserId(uid) && !isPlaybackActive(uid)) {
                    // Clean up unnecessary UIDs.
                    // It doesn't need to be managed profile aware because it's just to prevent
                    // the list from increasing indefinitely. The media button session updating
@@ -198,4 +278,8 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub {
            }
        }
    }

    private boolean isActiveState(Integer state) {
        return state != null && state.equals(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
    }
}
+113 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.media;

import com.android.internal.util.DumpUtils;
import com.android.server.Watchdog;
import com.android.server.media.AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener;

import android.Manifest;
import android.app.ActivityManager;
@@ -26,7 +27,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
import android.media.IMediaRouterClient;
import android.media.IMediaRouterService;
import android.media.MediaRouter;
@@ -39,9 +43,12 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -89,10 +96,54 @@ public final class MediaRouterService extends IMediaRouterService.Stub
    private final ArrayMap<IBinder, ClientRecord> mAllClientRecords =
            new ArrayMap<IBinder, ClientRecord>();
    private int mCurrentUserId = -1;
    private boolean mHasBluetoothRoute = false;
    private final IAudioService mAudioService;
    private final AudioPlaybackMonitor mAudioPlaybackMonitor;

    public MediaRouterService(Context context) {
        mContext = context;
        Watchdog.getInstance().addMonitor(this);

        mAudioService = IAudioService.Stub.asInterface(
                ServiceManager.getService(Context.AUDIO_SERVICE));

        mAudioPlaybackMonitor = AudioPlaybackMonitor.getInstance(context, mAudioService);
        mAudioPlaybackMonitor.registerOnAudioPlayerActiveStateChangedListener(
                new AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener() {
            @Override
            public void onAudioPlayerActiveStateChanged(int uid, boolean active) {
                if (active) {
                    restoreRoute(uid);
                } else {
                    IntArray sortedAudioPlaybackClientUids =
                            mAudioPlaybackMonitor.getSortedAudioPlaybackClientUids();
                    boolean restored = false;
                    for (int i = 0; i < sortedAudioPlaybackClientUids.size(); i++) {
                        if (mAudioPlaybackMonitor.isPlaybackActive(
                                sortedAudioPlaybackClientUids.get(i))) {
                            restoreRoute(sortedAudioPlaybackClientUids.get(i));
                            restored = true;
                            break;
                        }
                    }
                    if (!restored) {
                        restoreBluetoothA2dp();
                    }
                }
            }
        });
        AudioRoutesInfo audioRoutes = null;
        try {
            audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() {
                @Override
                public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
                    mHasBluetoothRoute = newRoutes.bluetoothName != null;
                }
            });
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in the audio service.");
        }
        mHasBluetoothRoute = (audioRoutes != null && audioRoutes.bluetoothName != null);
    }

    public void systemRunning() {
@@ -135,7 +186,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                registerClientLocked(client, pid, packageName, resolvedUserId, trusted);
                registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
@@ -176,6 +227,23 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        }
    }

    // Binder call
    @Override
    public boolean isPlaybackActive(IMediaRouterClient client) {
        if (client == null) {
            throw new IllegalArgumentException("client must not be null");
        }

        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                return isPlaybackActiveLocked(client);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    // Binder call
    @Override
    public void setDiscoveryRequest(IMediaRouterClient client,
@@ -276,6 +344,36 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        }
    }

    void restoreBluetoothA2dp() {
        try {
            mAudioService.setBluetoothA2dpOn(mHasBluetoothRoute);
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn.");
        }
    }

    void restoreRoute(int uid) {
        ClientRecord clientRecord = null;
        UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid));
        if (userRecord.mClientRecords != null) {
            for (ClientRecord cr : userRecord.mClientRecords) {
                if (validatePackageName(uid, cr.mPackageName)) {
                    clientRecord = cr;
                    break;
                }
            }
        }
        if (clientRecord != null) {
            try {
                clientRecord.mClient.onRestoreRoute();
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to call onRestoreRoute. Client probably died.");
            }
        } else {
            restoreBluetoothA2dp();
        }
    }

    void switchUser() {
        synchronized (mLock) {
            int userId = ActivityManager.getCurrentUser();
@@ -304,7 +402,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
    }

    private void registerClientLocked(IMediaRouterClient client,
            int pid, String packageName, int userId, boolean trusted) {
            int uid, int pid, String packageName, int userId, boolean trusted) {
        final IBinder binder = client.asBinder();
        ClientRecord clientRecord = mAllClientRecords.get(binder);
        if (clientRecord == null) {
@@ -314,7 +412,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
                userRecord = new UserRecord(userId);
                newUser = true;
            }
            clientRecord = new ClientRecord(userRecord, client, pid, packageName, trusted);
            clientRecord = new ClientRecord(userRecord, client, uid, pid, packageName, trusted);
            try {
                binder.linkToDeath(clientRecord, 0);
            } catch (RemoteException ex) {
@@ -350,6 +448,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        return null;
    }

    private boolean isPlaybackActiveLocked(IMediaRouterClient client) {
        ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
        if (clientRecord != null) {
            return mAudioPlaybackMonitor.isPlaybackActive(clientRecord.mUid);
        }
        return false;
    }

    private void setDiscoveryRequestLocked(IMediaRouterClient client,
            int routeTypes, boolean activeScan) {
        final IBinder binder = client.asBinder();
@@ -489,6 +595,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
    final class ClientRecord implements DeathRecipient {
        public final UserRecord mUserRecord;
        public final IMediaRouterClient mClient;
        public final int mUid;
        public final int mPid;
        public final String mPackageName;
        public final boolean mTrusted;
@@ -498,9 +605,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
        public String mSelectedRouteId;

        public ClientRecord(UserRecord userRecord, IMediaRouterClient client,
                int pid, String packageName, boolean trusted) {
                int uid, int pid, String packageName, boolean trusted) {
            mUserRecord = userRecord;
            mClient = client;
            mUid = uid;
            mPid = pid;
            mPackageName = packageName;
            mTrusted = trusted;
@@ -997,7 +1105,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
                    try {
                        mTempClients.get(i).onStateChanged();
                    } catch (RemoteException ex) {
                        // ignore errors, client probably died
                        Slog.w(TAG, "Failed to call onStateChanged. Client probably died.");
                    }
                }
            } finally {
Loading