170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell/*
270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * Copyright (C) 2012 The Android Open Source Project
370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell *
470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * you may not use this file except in compliance with the License.
670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * You may obtain a copy of the License at
770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell *
870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell *
1070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * Unless required by applicable law or agreed to in writing, software
1170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
1270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * See the License for the specific language governing permissions and
1470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * limitations under the License.
1570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell */
1670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
1770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellpackage com.android.internal.app;
1870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
1970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport com.android.internal.R;
2070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
2170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.app.Activity;
22d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport android.app.Dialog;
2370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.app.DialogFragment;
2470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.app.MediaRouteActionProvider;
2570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.app.MediaRouteButton;
2670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.content.Context;
27d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport android.graphics.drawable.Drawable;
28705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powellimport android.hardware.display.DisplayManager;
2970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.media.MediaRouter;
3070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.media.MediaRouter.RouteCategory;
3170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.media.MediaRouter.RouteGroup;
3270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.media.MediaRouter.RouteInfo;
3370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.os.Bundle;
3470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.text.TextUtils;
354599696591f745b3a546197d2ba7e5cfc5562484Adam Powellimport android.view.KeyEvent;
3670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.view.LayoutInflater;
3770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.view.View;
3870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.view.ViewGroup;
3970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.widget.AdapterView;
4070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.widget.BaseAdapter;
41b5e2af5919351486a385effe77409d2a91ae9c19Adam Powellimport android.widget.CheckBox;
42b5e2af5919351486a385effe77409d2a91ae9c19Adam Powellimport android.widget.Checkable;
43d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport android.widget.ImageButton;
44d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport android.widget.ImageView;
4570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.widget.ListView;
464599696591f745b3a546197d2ba7e5cfc5562484Adam Powellimport android.widget.SeekBar;
4770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.widget.TextView;
4870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
4970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport java.util.ArrayList;
50d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport java.util.Collections;
51d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powellimport java.util.Comparator;
52b5e2af5919351486a385effe77409d2a91ae9c19Adam Powellimport java.util.List;
5370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
5470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell/**
5570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * This class implements the route chooser dialog for {@link MediaRouter}.
5670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell *
5770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * @see MediaRouteButton
5870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell * @see MediaRouteActionProvider
5970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell */
6070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellpublic class MediaRouteChooserDialogFragment extends DialogFragment {
6170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private static final String TAG = "MediaRouteChooserDialogFragment";
6270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public static final String FRAGMENT_TAG = "android:MediaRouteChooserDialogFragment";
6370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
64d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    private static final int[] ITEM_LAYOUTS = new int[] {
65d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        R.layout.media_route_list_item_top_header,
66d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        R.layout.media_route_list_item_section_header,
67b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        R.layout.media_route_list_item,
68d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        R.layout.media_route_list_item_checkable,
69d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        R.layout.media_route_list_item_collapse_group
70d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    };
71d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
7270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    MediaRouter mRouter;
73705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell    DisplayManager mDisplayService;
7470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private int mRouteTypes;
7570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
76d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    private LayoutInflater mInflater;
7770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private LauncherListener mLauncherListener;
7870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private View.OnClickListener mExtendedSettingsListener;
7970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private RouteAdapter mAdapter;
8070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    private ListView mListView;
814599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    private SeekBar mVolumeSlider;
824599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    private ImageView mVolumeIcon;
8370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
840d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell    final RouteComparator mComparator = new RouteComparator();
854599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    final MediaRouterCallback mCallback = new MediaRouterCallback();
868e37a85bf3dc39519942698dc90a3951306b934bAdam Powell    private boolean mIgnoreSliderVolumeChanges;
878e37a85bf3dc39519942698dc90a3951306b934bAdam Powell    private boolean mIgnoreCallbackVolumeChanges;
88d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
8970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public MediaRouteChooserDialogFragment() {
9070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        setStyle(STYLE_NO_TITLE, R.style.Theme_DeviceDefault_Dialog);
9170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
9270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
9370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void setLauncherListener(LauncherListener listener) {
9470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mLauncherListener = listener;
9570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
9670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
9770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    @Override
9870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void onAttach(Activity activity) {
9970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        super.onAttach(activity);
10070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
101705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        mDisplayService = (DisplayManager) activity.getSystemService(Context.DISPLAY_SERVICE);
10270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
10370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
10470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    @Override
10570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void onDetach() {
10670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        super.onDetach();
10770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mLauncherListener != null) {
10870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mLauncherListener.onDetached(this);
10970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
11070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mAdapter != null) {
11170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mAdapter = null;
11270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
113d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        mInflater = null;
1144599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        mRouter.removeCallback(mCallback);
11570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mRouter = null;
11670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
11770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
11870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void setExtendedSettingsClickListener(View.OnClickListener listener) {
11970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mExtendedSettingsListener = listener;
12070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
12170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
12270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public void setRouteTypes(int types) {
12370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mRouteTypes = types;
124705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        if ((mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0 && mDisplayService == null) {
125705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            final Context activity = getActivity();
126705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            if (activity != null) {
127705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                mDisplayService = (DisplayManager) activity.getSystemService(
128705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                        Context.DISPLAY_SERVICE);
129705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            }
130705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        } else {
131705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            mDisplayService = null;
132705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        }
13370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
13470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
1354599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    void updateVolume() {
1361b4ea7eff50545f4673ca01b664e5edccc784688Adam Powell        if (mRouter == null) return;
1371b4ea7eff50545f4673ca01b664e5edccc784688Adam Powell
1384599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
1398e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        mVolumeIcon.setImageResource(
1408e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                selectedRoute.getPlaybackType() == RouteInfo.PLAYBACK_TYPE_LOCAL ?
1414599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                R.drawable.ic_audio_vol : R.drawable.ic_media_route_on_holo_dark);
1424599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
1438e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        mIgnoreSliderVolumeChanges = true;
1444599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
1458e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) {
1468e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            // Disable the slider and show it at max volume.
1478e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setMax(1);
1488e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setProgress(1);
1498e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setEnabled(false);
1508e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        } else {
1518e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setEnabled(true);
1528e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setMax(selectedRoute.getVolumeMax());
1538e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mVolumeSlider.setProgress(selectedRoute.getVolume());
1544599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
1558e37a85bf3dc39519942698dc90a3951306b934bAdam Powell
1568e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        mIgnoreSliderVolumeChanges = false;
1574599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    }
1584599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
1594599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    void changeVolume(int newValue) {
1608e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        if (mIgnoreSliderVolumeChanges) return;
1614599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
1628e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
1638e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
1644dd21c8e77c0d369ee835f50cba1701e76aa18c4Adam Powell            final int maxVolume = selectedRoute.getVolumeMax();
1654599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            newValue = Math.max(0, Math.min(newValue, maxVolume));
1668e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            selectedRoute.requestSetVolume(newValue);
1674599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
1684599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    }
1694599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
17070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    @Override
17170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    public View onCreateView(LayoutInflater inflater, ViewGroup container,
17270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            Bundle savedInstanceState) {
173d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        mInflater = inflater;
17470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final View layout = inflater.inflate(R.layout.media_route_chooser_layout, container, false);
1754599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
1764599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        mVolumeIcon = (ImageView) layout.findViewById(R.id.volume_icon);
1774599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        mVolumeSlider = (SeekBar) layout.findViewById(R.id.volume_slider);
1784599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        updateVolume();
1794599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        mVolumeSlider.setOnSeekBarChangeListener(new VolumeSliderChangeListener());
18070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
18170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        if (mExtendedSettingsListener != null) {
1824599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            final View extendedSettingsButton = layout.findViewById(R.id.extended_settings);
18370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            extendedSettingsButton.setVisibility(View.VISIBLE);
18470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            extendedSettingsButton.setOnClickListener(mExtendedSettingsListener);
18570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
18670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
18770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        final ListView list = (ListView) layout.findViewById(R.id.list);
188d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        list.setItemsCanFocus(true);
189d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        list.setAdapter(mAdapter = new RouteAdapter());
19070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        list.setOnItemClickListener(mAdapter);
19170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
19270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        mListView = list;
1934599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        mRouter.addCallback(mRouteTypes, mCallback);
19470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
195b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        mAdapter.scrollToSelectedItem();
196d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
197b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        return layout;
198d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    }
199d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
200d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    @Override
201d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    public Dialog onCreateDialog(Bundle savedInstanceState) {
202d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        return new RouteChooserDialog(getActivity(), getTheme());
203d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    }
204d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
205d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    @Override
206d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    public void onResume() {
207d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        super.onResume();
208705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        if (mDisplayService != null) {
209705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            mDisplayService.scanWifiDisplays();
210705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell        }
211d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    }
212d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
213d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    private static class ViewHolder {
214d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public TextView text1;
215d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public TextView text2;
216d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public ImageView icon;
217d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public ImageButton expandGroupButton;
218d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public RouteAdapter.ExpandGroupListener expandGroupListener;
219d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public int position;
220b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        public CheckBox check;
221d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    }
22270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
2230d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell    private class RouteAdapter extends BaseAdapter implements ListView.OnItemClickListener {
22470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        private static final int VIEW_TOP_HEADER = 0;
22570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        private static final int VIEW_SECTION_HEADER = 1;
22670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        private static final int VIEW_ROUTE = 2;
227b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private static final int VIEW_GROUPING_ROUTE = 3;
228b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private static final int VIEW_GROUPING_DONE = 4;
22970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
230b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private int mSelectedItemPosition = -1;
23170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        private final ArrayList<Object> mItems = new ArrayList<Object>();
23270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
233b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private RouteCategory mCategoryEditingGroups;
234b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private RouteGroup mEditingGroup;
235b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
236b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        // Temporary lists for manipulation
237b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private final ArrayList<RouteInfo> mCatRouteList = new ArrayList<RouteInfo>();
238b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private final ArrayList<RouteInfo> mSortRouteList = new ArrayList<RouteInfo>();
239b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
240b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        private boolean mIgnoreUpdates;
241b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
242d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        RouteAdapter() {
24370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            update();
24470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
24570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
24670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        void update() {
247b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            /*
248b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * This is kind of wacky, but our data sets are going to be
249b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * fairly small on average. Ideally we should be able to do some of this stuff
250b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * in-place instead.
251b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             *
252b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * Basic idea: each entry in mItems represents an item in the list for quick access.
253b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * Entries can be a RouteCategory (section header), a RouteInfo with a category of
254b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * mCategoryEditingGroups (a flattened RouteInfo pulled out of its group, allowing
255b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             * the user to change the group),
256b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell             */
257b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (mIgnoreUpdates) return;
258b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
25970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            mItems.clear();
26070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
26170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
262b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mSelectedItemPosition = -1;
26370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
264b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            List<RouteInfo> routes;
26570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            final int catCount = mRouter.getCategoryCount();
26670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            for (int i = 0; i < catCount; i++) {
26770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                final RouteCategory cat = mRouter.getCategoryAt(i);
268b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                routes = cat.getRoutes(mCatRouteList);
26970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
270705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                if (!cat.isSystem()) {
271705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                    mItems.add(cat);
272705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                }
27370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
274b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (cat == mCategoryEditingGroups) {
275b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    addGroupEditingCategoryRoutes(routes);
276b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                } else {
277b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    addSelectableRoutes(selectedRoute, routes);
27870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                }
279b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
280b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                routes.clear();
28170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
28270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
28370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            notifyDataSetChanged();
284b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (mListView != null && mSelectedItemPosition >= 0) {
28570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                mListView.setItemChecked(mSelectedItemPosition, true);
28670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
28770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
28870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
289b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        void scrollToEditingGroup() {
290b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (mCategoryEditingGroups == null || mListView == null) return;
291b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
292b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            int pos = 0;
293b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            int bound = 0;
294b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            final int itemCount = mItems.size();
295b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            for (int i = 0; i < itemCount; i++) {
296b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final Object item = mItems.get(i);
297b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (item != null && item == mCategoryEditingGroups) {
298b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    bound = i;
299b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
300b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (item == null) {
301b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    pos = i;
302b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    break; // this is always below the category header; we can stop here.
303b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
304b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            }
305b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
306b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mListView.smoothScrollToPosition(pos, bound);
307b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
308b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
309b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        void scrollToSelectedItem() {
310b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (mListView == null || mSelectedItemPosition < 0) return;
311b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
312b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mListView.smoothScrollToPosition(mSelectedItemPosition);
313b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
314b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
315b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        void addSelectableRoutes(RouteInfo selectedRoute, List<RouteInfo> from) {
316b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            final int routeCount = from.size();
317b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            for (int j = 0; j < routeCount; j++) {
318b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteInfo info = from.get(j);
319b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (info == selectedRoute) {
320b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    mSelectedItemPosition = mItems.size();
321b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
322b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                mItems.add(info);
323b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            }
324b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
325b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
326b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        void addGroupEditingCategoryRoutes(List<RouteInfo> from) {
327b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            // Unpack groups and flatten for presentation
328b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            // mSortRouteList will always be empty here.
329b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            final int topCount = from.size();
330b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            for (int i = 0; i < topCount; i++) {
331b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteInfo route = from.get(i);
332b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteGroup group = route.getGroup();
333b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (group == route) {
334b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    // This is a group, unpack it.
335b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    final int groupCount = group.getRouteCount();
336b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    for (int j = 0; j < groupCount; j++) {
337b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        final RouteInfo innerRoute = group.getRouteAt(j);
338b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        mSortRouteList.add(innerRoute);
339b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    }
340b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                } else {
341b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    mSortRouteList.add(route);
342b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
343b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            }
344b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            // Sort by name. This will keep the route positions relatively stable even though they
345b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            // will be repeatedly added and removed.
346b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            Collections.sort(mSortRouteList, mComparator);
347b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
348b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mItems.addAll(mSortRouteList);
349b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mSortRouteList.clear();
350b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
351b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mItems.add(null); // Sentinel reserving space for the "done" button.
352b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
353b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
35470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
35570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public int getCount() {
35670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return mItems.size();
35770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
35870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
35970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
36070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public int getViewTypeCount() {
361b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            return 5;
36270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
36370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
36470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
36570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public int getItemViewType(int position) {
36670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            final Object item = getItem(position);
36770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            if (item instanceof RouteCategory) {
36870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                return position == 0 ? VIEW_TOP_HEADER : VIEW_SECTION_HEADER;
369b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            } else if (item == null) {
370b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                return VIEW_GROUPING_DONE;
37170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            } else {
372b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteInfo info = (RouteInfo) item;
373b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (info.getCategory() == mCategoryEditingGroups) {
374b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    return VIEW_GROUPING_ROUTE;
375b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
37670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                return VIEW_ROUTE;
37770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
37870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
37970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
38070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
38170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public boolean areAllItemsEnabled() {
38270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return false;
38370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
38470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
38570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
38670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public boolean isEnabled(int position) {
387b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            switch (getItemViewType(position)) {
388b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_ROUTE:
389705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell                    return ((RouteInfo) mItems.get(position)).isEnabled();
390b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_GROUPING_ROUTE:
391b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_GROUPING_DONE:
392b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    return true;
393b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                default:
394b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    return false;
395b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            }
39670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
39770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
39870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
39970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public Object getItem(int position) {
40070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return mItems.get(position);
40170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
40270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
40370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
40470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public long getItemId(int position) {
40570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return position;
40670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
40770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
40870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
40970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public View getView(int position, View convertView, ViewGroup parent) {
41070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            final int viewType = getItemViewType(position);
41170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
41270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            ViewHolder holder;
41370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            if (convertView == null) {
41470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                convertView = mInflater.inflate(ITEM_LAYOUTS[viewType], parent, false);
41570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder = new ViewHolder();
416d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                holder.position = position;
41770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder.text1 = (TextView) convertView.findViewById(R.id.text1);
41870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder.text2 = (TextView) convertView.findViewById(R.id.text2);
419d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                holder.icon = (ImageView) convertView.findViewById(R.id.icon);
420b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                holder.check = (CheckBox) convertView.findViewById(R.id.check);
421d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                holder.expandGroupButton = (ImageButton) convertView.findViewById(
422d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                        R.id.expand_button);
423d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                if (holder.expandGroupButton != null) {
424d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                    holder.expandGroupListener = new ExpandGroupListener();
425d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                    holder.expandGroupButton.setOnClickListener(holder.expandGroupListener);
426d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                }
427d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
428d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                final View fview = convertView;
429d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                final ListView list = (ListView) parent;
430d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                final ViewHolder fholder = holder;
431d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                convertView.setOnClickListener(new View.OnClickListener() {
432d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                    @Override public void onClick(View v) {
433d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                        list.performItemClick(fview, fholder.position, 0);
434d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                    }
435d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                });
43670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                convertView.setTag(holder);
43770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            } else {
43870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder = (ViewHolder) convertView.getTag();
439d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                holder.position = position;
44070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
44170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
442b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            switch (viewType) {
443b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_ROUTE:
444b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_GROUPING_ROUTE:
445b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    bindItemView(position, holder);
446b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    break;
447b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_SECTION_HEADER:
448b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                case VIEW_TOP_HEADER:
449b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    bindHeaderView(position, holder);
450b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    break;
45170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
45270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
453b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            convertView.setActivated(position == mSelectedItemPosition);
454705ab808cf023e0cc38c2ba7cdb9571942cdc04fAdam Powell            convertView.setEnabled(isEnabled(position));
455b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
45670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            return convertView;
45770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
45870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
45970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        void bindItemView(int position, ViewHolder holder) {
46070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            RouteInfo info = (RouteInfo) mItems.get(position);
4610d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell            holder.text1.setText(info.getName(getActivity()));
46270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            final CharSequence status = info.getStatus();
46370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            if (TextUtils.isEmpty(status)) {
46470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder.text2.setVisibility(View.GONE);
46570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            } else {
46670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder.text2.setVisibility(View.VISIBLE);
46770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                holder.text2.setText(status);
46870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
469d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            Drawable icon = info.getIconDrawable();
470d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            if (icon != null) {
471d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                // Make sure we have a fresh drawable where it doesn't matter if we mutate it
472d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                icon = icon.getConstantState().newDrawable(getResources());
473d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            }
474d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            holder.icon.setImageDrawable(icon);
475d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            holder.icon.setVisibility(icon != null ? View.VISIBLE : View.GONE);
476d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
477d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            RouteCategory cat = info.getCategory();
478d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            boolean canGroup = false;
479b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (cat == mCategoryEditingGroups) {
480b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                RouteGroup group = info.getGroup();
481b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                holder.check.setEnabled(group.getRouteCount() > 1);
482b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                holder.check.setChecked(group == mEditingGroup);
483b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            } else {
484b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (cat.isGroupable()) {
485b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    final RouteGroup group = (RouteGroup) info;
486b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    canGroup = group.getRouteCount() > 1 ||
487b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                            getItemViewType(position - 1) == VIEW_ROUTE ||
488b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                            (position < getCount() - 1 &&
489b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                                    getItemViewType(position + 1) == VIEW_ROUTE);
490b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
491b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            }
492b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
493b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (holder.expandGroupButton != null) {
494b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                holder.expandGroupButton.setVisibility(canGroup ? View.VISIBLE : View.GONE);
495b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                holder.expandGroupListener.position = position;
496d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            }
49770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
49870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
49970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        void bindHeaderView(int position, ViewHolder holder) {
50070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            RouteCategory cat = (RouteCategory) mItems.get(position);
5010d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell            holder.text1.setText(cat.getName(getActivity()));
50270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
50370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
50470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        @Override
50570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
506b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            final int type = getItemViewType(position);
507b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (type == VIEW_SECTION_HEADER || type == VIEW_TOP_HEADER) {
50870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell                return;
509b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            } else if (type == VIEW_GROUPING_DONE) {
510b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                finishGrouping();
511b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                return;
512b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            } else {
513b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final Object item = getItem(position);
514b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (!(item instanceof RouteInfo)) {
515b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    // Oops. Stale event running around? Skip it.
516b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    return;
517b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
518b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
519b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteInfo route = (RouteInfo) item;
520b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                if (type == VIEW_ROUTE) {
521b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    mRouter.selectRouteInt(mRouteTypes, route);
522b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    dismiss();
523b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                } else if (type == VIEW_GROUPING_ROUTE) {
524b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    final Checkable c = (Checkable) view;
525b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    final boolean wasChecked = c.isChecked();
526b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
527b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    mIgnoreUpdates = true;
528b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    RouteGroup oldGroup = route.getGroup();
529b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    if (!wasChecked && oldGroup != mEditingGroup) {
530b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        // Assumption: in a groupable category oldGroup will never be null.
531b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        if (mRouter.getSelectedRoute(mRouteTypes) == oldGroup) {
532b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                            // Old group was selected but is now empty. Select the group
533b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                            // we're manipulating since that's where the last route went.
534b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                            mRouter.selectRouteInt(mRouteTypes, mEditingGroup);
535b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        }
536b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        oldGroup.removeRoute(route);
537b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        mEditingGroup.addRoute(route);
538b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        c.setChecked(true);
539b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    } else if (wasChecked && mEditingGroup.getRouteCount() > 1) {
540b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        mEditingGroup.removeRoute(route);
541b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
542b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        // In a groupable category this will add
543b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        // the route into its own new group.
544b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                        mRouter.addRouteInt(route);
545b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    }
546b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    mIgnoreUpdates = false;
547b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                    update();
548b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                }
54970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell            }
550b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
551b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
552b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        boolean isGrouping() {
553b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            return mCategoryEditingGroups != null;
554b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        }
555b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell
556b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell        void finishGrouping() {
557b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mCategoryEditingGroups = null;
558b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            mEditingGroup = null;
559b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            getDialog().setCanceledOnTouchOutside(true);
560b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            update();
561b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            scrollToSelectedItem();
56270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
56370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
564d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        class ExpandGroupListener implements View.OnClickListener {
565d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            int position;
566d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
567d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            @Override
568d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            public void onClick(View v) {
569d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                // Assumption: this is only available for the user to click if we're presenting
570d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                // a groupable category, where every top-level route in the category is a group.
571b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                final RouteGroup group = (RouteGroup) getItem(position);
572b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                mEditingGroup = group;
573b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                mCategoryEditingGroups = group.getCategory();
574b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                getDialog().setCanceledOnTouchOutside(false);
575b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                mRouter.selectRouteInt(mRouteTypes, mEditingGroup);
576b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                update();
577b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                scrollToEditingGroup();
578d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            }
579d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        }
5804599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    }
5810d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
5824599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    class MediaRouterCallback extends MediaRouter.Callback {
5834599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
5844599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
5854599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
5864599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            updateVolume();
5874599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
5880d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
5894599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
5904599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
5914599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
5924599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
5930d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
5944599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
5954599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteAdded(MediaRouter router, RouteInfo info) {
5964599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
5974599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
5980d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
5994599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6004599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteRemoved(MediaRouter router, RouteInfo info) {
6014599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            if (info == mAdapter.mEditingGroup) {
6024599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                mAdapter.finishGrouping();
6030d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell            }
6044599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
6054599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6060d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
6074599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6084599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteChanged(MediaRouter router, RouteInfo info) {
6094599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.notifyDataSetChanged();
6104599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6110d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
6124599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6134599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteGrouped(MediaRouter router, RouteInfo info,
6144599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                RouteGroup group, int index) {
6154599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
6164599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6170d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell
6184599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6194599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
6204599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            mAdapter.update();
6210d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell        }
6228e37a85bf3dc39519942698dc90a3951306b934bAdam Powell
6238e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        @Override
6248e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        public void onRouteVolumeChanged(MediaRouter router, RouteInfo info) {
6258e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            if (!mIgnoreCallbackVolumeChanges) {
6268e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                updateVolume();
6278e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            }
6288e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        }
62970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
63070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell
6310d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell    class RouteComparator implements Comparator<RouteInfo> {
632d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        @Override
633d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public int compare(RouteInfo lhs, RouteInfo rhs) {
6340d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell            return lhs.getName(getActivity()).toString()
6350d03c042f90bf62d5bad7c64e77028a5f9f8fae0Adam Powell                    .compareTo(rhs.getName(getActivity()).toString());
636d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        }
637d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    }
638d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
639d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell    class RouteChooserDialog extends Dialog {
640d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public RouteChooserDialog(Context context, int theme) {
641d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            super(context, theme);
642d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        }
643d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell
644d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        @Override
645d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell        public void onBackPressed() {
646b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell            if (mAdapter != null && mAdapter.isGrouping()) {
647b5e2af5919351486a385effe77409d2a91ae9c19Adam Powell                mAdapter.finishGrouping();
648d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            } else {
649d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell                super.onBackPressed();
650d6d0bddee363e0c7fe61f63bd9d9864a71d887d6Adam Powell            }
65170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell        }
6524599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6534599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public boolean onKeyDown(int keyCode, KeyEvent event) {
6544599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) {
6558e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(-1);
6564599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                return true;
6574599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) {
6588e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1);
6594599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                return true;
6604599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            } else {
6614599696591f745b3a546197d2ba7e5cfc5562484Adam Powell                return super.onKeyDown(keyCode, event);
6624599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            }
6634599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6648e37a85bf3dc39519942698dc90a3951306b934bAdam Powell
6658e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        public boolean onKeyUp(int keyCode, KeyEvent event) {
6668e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) {
6678e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                return true;
6688e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) {
6698e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                return true;
6708e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            } else {
6718e37a85bf3dc39519942698dc90a3951306b934bAdam Powell                return super.onKeyUp(keyCode, event);
6728e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            }
6738e37a85bf3dc39519942698dc90a3951306b934bAdam Powell        }
6744599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    }
6754599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6764599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    /**
6774599696591f745b3a546197d2ba7e5cfc5562484Adam Powell     * Implemented by the MediaRouteButton that launched this dialog
6784599696591f745b3a546197d2ba7e5cfc5562484Adam Powell     */
6794599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    public interface LauncherListener {
6804599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onDetached(MediaRouteChooserDialogFragment detachedFragment);
6814599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    }
6824599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6834599696591f745b3a546197d2ba7e5cfc5562484Adam Powell    class VolumeSliderChangeListener implements SeekBar.OnSeekBarChangeListener {
6844599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6854599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6864599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
6874599696591f745b3a546197d2ba7e5cfc5562484Adam Powell            changeVolume(progress);
6884599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6894599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6904599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6914599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onStartTrackingTouch(SeekBar seekBar) {
6928e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mIgnoreCallbackVolumeChanges = true;
6934599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
6944599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
6954599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        @Override
6964599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        public void onStopTrackingTouch(SeekBar seekBar) {
6978e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            mIgnoreCallbackVolumeChanges = false;
6988e37a85bf3dc39519942698dc90a3951306b934bAdam Powell            updateVolume();
6994599696591f745b3a546197d2ba7e5cfc5562484Adam Powell        }
7004599696591f745b3a546197d2ba7e5cfc5562484Adam Powell
70170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell    }
70270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell}
703