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

Commit 96681b8f authored by Sungsoo's avatar Sungsoo Committed by android-build-merger
Browse files

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

am: d7ff18da

Change-Id: I52a17de61821c72e97336eb66f34a56444e13894
parents 60ebd524 d7ff18da
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