165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.accounts.Account;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.accounts.AccountManager;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.bluetooth.BluetoothAdapter;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.bluetooth.BluetoothDevice;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.ComponentName;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.TypedArray;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.XmlResourceParser;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.media.tv.TvInputInfo;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.media.tv.TvInputManager;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Handler;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.preference.PreferenceActivity;
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v17.leanback.widget.ArrayObjectAdapter;
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v17.leanback.widget.HeaderItem;
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v17.leanback.widget.ObjectAdapter;
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.support.v17.leanback.widget.ListRow;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.AttributeSet;
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log;
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.TypedValue;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Xml;
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.internal.util.XmlUtils;
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.accessories.AccessoryUtils;
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.accessories.BluetoothAccessoryActivity;
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.accounts.AccountImageUriGetter;
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.accounts.AccountSettingsActivity;
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.accounts.AuthenticatorHelper;
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.connectivity.ConnectivityStatusIconUriGetter;
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.connectivity.ConnectivityStatusTextGetter;
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.connectivity.WifiNetworksActivity;
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.device.sound.SoundActivity;
530898ab0f3d589be95488997e7ec1a8cc2a06b399Tim Kilbournimport com.android.tv.settings.users.RestrictedProfileActivity;
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.UriUtils;
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport org.xmlpull.v1.XmlPullParser;
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport org.xmlpull.v1.XmlPullParserException;
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.io.IOException;
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.HashSet;
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Set;
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Gets the list of browse headers and browse items.
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class BrowseInfo extends BrowseInfoBase {
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String TAG = "CanvasSettings.BrowseInfo";
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final boolean DEBUG = false;
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_ACCESSORY_ADDRESS = "accessory_address";
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_ACCESSORY_NAME = "accessory_name";
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final String EXTRA_ACCESSORY_ICON_ID = "accessory_icon_res";
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ETHERNET_PREFERENCE_KEY = "ethernet";
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    interface XmlReaderListener {
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        void handleRequestedNode(Context context, XmlResourceParser parser, AttributeSet attrs)
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throws org.xmlpull.v1.XmlPullParserException, IOException;
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    static class SoundActivityImageUriGetter implements MenuItem.UriGetter {
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final Context mContext;
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        SoundActivityImageUriGetter(Context context) {
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mContext = context;
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public String getUri() {
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return UriUtils.getAndroidResourceUri(mContext.getResources(),
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    SoundActivity.getIconResource(mContext.getContentResolver()));
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    static class XmlReader {
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final Context mContext;
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final int mXmlResource;
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final String mRootNodeName;
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final String mNodeNameRequested;
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final XmlReaderListener mListener;
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        XmlReader(Context context, int xmlResource, String rootNodeName, String nodeNameRequested,
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                XmlReaderListener listener) {
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mContext = context;
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mXmlResource = xmlResource;
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRootNodeName = rootNodeName;
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mNodeNameRequested = nodeNameRequested;
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mListener = listener;
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        void read() {
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            XmlResourceParser parser = null;
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            try {
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                parser = mContext.getResources().getXml(mXmlResource);
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                AttributeSet attrs = Xml.asAttributeSet(parser);
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int type;
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        && type != XmlPullParser.START_TAG) {
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    // Parse next until start tag is found
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String nodeName = parser.getName();
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (!mRootNodeName.equals(nodeName)) {
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    throw new RuntimeException("XML document must start with <" + mRootNodeName
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            + "> tag; found" + nodeName + " at " + parser.getPositionDescription());
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Bundle curBundle = null;
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                final int outerDepth = parser.getDepth();
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        continue;
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    nodeName = parser.getName();
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (mNodeNameRequested.equals(nodeName)) {
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        mListener.handleRequestedNode(mContext, parser, attrs);
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    } else {
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        XmlUtils.skipCurrentTag(parser);
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } catch (XmlPullParserException e) {
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throw new RuntimeException("Error parsing headers", e);
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } catch (IOException e) {
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throw new RuntimeException("Error parsing headers", e);
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } finally {
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (parser != null)
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    parser.close();
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String PREF_KEY_ADD_ACCESSORY = "add_accessory";
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String PREF_KEY_WIFI = "wifi";
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String PREF_KEY_DEVELOPER = "developer";
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String PREF_KEY_INPUTS = "inputs";
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Context mContext;
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final AuthenticatorHelper mAuthenticatorHelper;
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mNextItemId;
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mAccountHeaderId;
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final BluetoothAdapter mBtAdapter;
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Set<BluetoothDevice> mConnectedDevices;
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Object mGuard = new Object();
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final boolean mAllowMultipleAccounts;
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private MenuItem mWifiItem = null;
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private ArrayObjectAdapter mWifiRow = null;
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Handler mHandler = new Handler();
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private PreferenceUtils mPreferenceUtils;
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private boolean mDeveloperEnabled;
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private boolean mInputSettingNeeded;
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private final Runnable refreshWifiCardRunnable = new Runnable() {
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void run() {
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            refreshWifiCard();
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    };
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    BrowseInfo(Context context) {
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mContext = context;
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mAuthenticatorHelper = new AuthenticatorHelper();
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mAuthenticatorHelper.updateAuthDescriptions(context);
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mAuthenticatorHelper.onAccountsUpdated(context, null);
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mBtAdapter = BluetoothAdapter.getDefaultAdapter();
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mConnectedDevices = new HashSet<BluetoothDevice>();
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mNextItemId = 0;
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mAllowMultipleAccounts =
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                context.getResources().getBoolean(R.bool.multiple_accounts_enabled);
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mPreferenceUtils = new PreferenceUtils(context);
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mDeveloperEnabled = mPreferenceUtils.isDeveloperEnabled();
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mInputSettingNeeded = isInputSettingNeeded();
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void refreshContent() {
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        init();
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void init() {
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mGuard) {
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHeaderItems.clear();
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRows.clear();
214dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik            int settingsXml = isRestricted() ? R.xml.restricted_main : R.xml.main;
215dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik            new XmlReader(mContext, settingsXml, "preference-headers", "header",
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    new HeaderXmlReaderListener()).read();
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            updateAccessories(R.id.accessories);
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void checkForDeveloperOptionUpdate() {
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        final boolean developerEnabled = mPreferenceUtils.isDeveloperEnabled();
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (developerEnabled != mDeveloperEnabled) {
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mDeveloperEnabled = developerEnabled;
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            init();
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private class HeaderXmlReaderListener implements XmlReaderListener {
23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void handleRequestedNode(Context context, XmlResourceParser parser,
23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                AttributeSet attrs)
23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throws XmlPullParserException, IOException {
23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            TypedArray sa = mContext.getResources().obtainAttributes(attrs,
23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.PreferenceHeader);
23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            final int headerId = sa.getResourceId(
23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.PreferenceHeader_id,
23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    (int) PreferenceActivity.HEADER_ID_UNDEFINED);
23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String title = getStringFromTypedArray(sa,
24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.PreferenceHeader_title);
24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            sa.recycle();
24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            sa = context.getResources().obtainAttributes(attrs, R.styleable.CanvasSettings);
24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int preferenceRes = sa.getResourceId(R.styleable.CanvasSettings_preference, 0);
24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            sa.recycle();
24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHeaderItems.add(new HeaderItem(headerId, title, null));
24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            final ArrayObjectAdapter currentRow = new ArrayObjectAdapter();
24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRows.put(headerId, currentRow);
24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (headerId != R.id.accessories) {
24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                new XmlReader(context, preferenceRes, "PreferenceScreen", "Preference",
25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        new PreferenceXmlReaderListener(headerId, currentRow)).read();
25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2550898ab0f3d589be95488997e7ec1a8cc2a06b399Tim Kilbourn    private boolean canAddAccount() {
256dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik        return !isRestricted();
257dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik    }
258dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik
259dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik    private boolean isRestricted() {
260dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik        return RestrictedProfileActivity.isRestrictedProfileInEffect(mContext);
2610898ab0f3d589be95488997e7ec1a8cc2a06b399Tim Kilbourn    }
2620898ab0f3d589be95488997e7ec1a8cc2a06b399Tim Kilbourn
26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private class PreferenceXmlReaderListener implements XmlReaderListener {
26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final int mHeaderId;
26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private final ArrayObjectAdapter mRow;
26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        PreferenceXmlReaderListener(int headerId, ArrayObjectAdapter row) {
26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHeaderId = headerId;
27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mRow = row;
27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public void handleRequestedNode(Context context, XmlResourceParser parser,
27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                AttributeSet attrs) throws XmlPullParserException, IOException {
27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            TypedArray sa = context.getResources().obtainAttributes(attrs,
27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.Preference);
27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String key = getStringFromTypedArray(sa,
28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.Preference_key);
28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String title = getStringFromTypedArray(sa,
28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    com.android.internal.R.styleable.Preference_title);
28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int iconRes = sa.getResourceId(com.android.internal.R.styleable.Preference_icon,
28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    R.drawable.settings_default_icon);
28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            sa.recycle();
28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (PREF_KEY_ADD_ACCOUNT.equals(key)) {
28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mAccountHeaderId = mHeaderId;
28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                addAccounts(mRow);
29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if ((!key.equals(PREF_KEY_DEVELOPER) || mDeveloperEnabled)
29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    && (!key.equals(PREF_KEY_INPUTS) || mInputSettingNeeded)) {
29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                MenuItem.TextGetter descriptionGetter = getDescriptionTextGetterFromKey(key);
29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                MenuItem.UriGetter uriGetter = getIconUriGetterFromKey(key);
29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                MenuItem.Builder builder = new MenuItem.Builder().id(mNextItemId++).title(title)
29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .descriptionGetter(descriptionGetter)
29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .intent(getIntent(parser, attrs, mHeaderId));
29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if(uriGetter == null) {
29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    builder.imageResourceId(mContext, iconRes);
29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                } else {
30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    builder.imageUriGetter(uriGetter);
30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (key.equals(PREF_KEY_WIFI)) {
30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mWifiItem = builder.build();
30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mRow.add(mWifiItem);
30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mWifiRow = mRow;
30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                } else {
30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    mRow.add(builder.build());
30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void refreshWifiCard() {
31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mWifiItem != null) {
31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int index = mWifiRow.indexOf(mWifiItem);
31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (index >= 0) {
31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mWifiRow.notifyArrayItemRangeChanged(index, 1);
31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void rebuildInfo() {
32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        init();
32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void updateAccounts() {
32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mGuard) {
328dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik            if (isRestricted()) {
329dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik                // We don't display the accounts in restricted mode
330dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik                return;
331dcc41237e48da2859b97f3ea5618558a4bea676fRoboErik            }
33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ArrayObjectAdapter row = mRows.get(mAccountHeaderId);
33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // Clear any account row cards that are not "Location" or "Security".
33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String dontDelete[] = new String[2];
33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dontDelete[0] = mContext.getString(R.string.system_location);
33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            dontDelete[1] = mContext.getString(R.string.system_security);
33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            int i = 0;
33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            while (i < row.size ()) {
33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                MenuItem menuItem = (MenuItem) row.get(i);
34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String title = menuItem.getTitle ();
34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                boolean deleteItem = true;
34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                for (int j = 0; j < dontDelete.length; ++j) {
34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    if (title.equals(dontDelete[j])) {
34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        deleteItem = false;
34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        break;
34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (deleteItem) {
34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    row.removeItems(i, 1);
35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                } else {
35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    ++i;
35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // Add accounts to end of row.
35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            addAccounts(row);
35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void updateAccessories() {
36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mGuard) {
36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            updateAccessories(R.id.accessories);
36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void updateWifi() {
36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mHandler.post(refreshWifiCardRunnable);
36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void bluetoothDeviceConnected(BluetoothDevice device) {
37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mConnectedDevices) {
37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mConnectedDevices.add(device);
37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    void bluetoothDeviceDisconnected(BluetoothDevice device) {
37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mConnectedDevices) {
37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mConnectedDevices.remove(device);
37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    boolean isDeviceConnected(BluetoothDevice device) {
38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        synchronized (mConnectedDevices) {
38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return mConnectedDevices.contains(device);
38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private boolean isInputSettingNeeded() {
38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        TvInputManager manager = (TvInputManager) mContext.getSystemService(
38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Context.TV_INPUT_SERVICE);
39021d707d5d9ebe7b0b6594fa959f9eb2ff9df69a9Christopher Lane        if (manager != null) {
39121d707d5d9ebe7b0b6594fa959f9eb2ff9df69a9Christopher Lane            for (TvInputInfo input : manager.getTvInputList()) {
39221d707d5d9ebe7b0b6594fa959f9eb2ff9df69a9Christopher Lane                if (input.isPassthroughInput()) {
39321d707d5d9ebe7b0b6594fa959f9eb2ff9df69a9Christopher Lane                    return true;
39421d707d5d9ebe7b0b6594fa959f9eb2ff9df69a9Christopher Lane                }
39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return false;
39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
39965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
40065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void updateAccessories(int headerId) {
40165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ArrayObjectAdapter row = mRows.get(headerId);
40265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        row.clear();
40365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
40465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        addAccessories(row);
40565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
40665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // Add new accessory activity icon
40765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        ComponentName componentName = new ComponentName("com.android.tv.settings",
40865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                "com.android.tv.settings.accessories.AddAccessoryActivity");
40965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent i = new Intent().setComponent(componentName);
41065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
41165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        row.add(new MenuItem.Builder().id(mNextItemId++)
41265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .title(mContext.getString(R.string.accessories_add))
41365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .imageResourceId(mContext, R.drawable.ic_settings_bluetooth)
41465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                .intent(i).build());
41565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
41665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
41765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Intent getIntent(XmlResourceParser parser, AttributeSet attrs, int headerId)
41865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throws org.xmlpull.v1.XmlPullParserException, IOException {
41965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Intent intent = null;
42065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (parser.next() == XmlPullParser.START_TAG && "intent".equals(parser.getName())) {
42165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            TypedArray sa = mContext.getResources()
42265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .obtainAttributes(attrs, com.android.internal.R.styleable.Intent);
42365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String targetClass = getStringFromTypedArray(
42465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    sa, com.android.internal.R.styleable.Intent_targetClass);
42565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String targetPackage = getStringFromTypedArray(
42665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    sa, com.android.internal.R.styleable.Intent_targetPackage);
42765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String action = getStringFromTypedArray(
42865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    sa, com.android.internal.R.styleable.Intent_action);
42965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (targetClass != null && targetPackage != null) {
43065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ComponentName componentName = new ComponentName(targetPackage, targetClass);
43165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                intent = new Intent();
43265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                intent.setComponent(componentName);
43365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else if (action != null) {
43465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                intent = new Intent(action);
43565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
43665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
43765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            XmlUtils.skipCurrentTag(parser);
43865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
43965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
44065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return intent;
44165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
44265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
44365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String getStringFromTypedArray(TypedArray sa, int resourceId) {
44465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String value = null;
44565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        TypedValue tv = sa.peekValue(resourceId);
44665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (tv != null && tv.type == TypedValue.TYPE_STRING) {
44765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (tv.resourceId != 0) {
44865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                value = mContext.getString(tv.resourceId);
44965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
45065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                value = tv.string.toString();
45165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
45265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
45365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return value;
45465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
45565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
45665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private MenuItem.TextGetter getDescriptionTextGetterFromKey(String key) {
45765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (WifiNetworksActivity.PREFERENCE_KEY.equals(key)) {
45865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return ConnectivityStatusTextGetter.createWifiStatusTextGetter(mContext);
45965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
46065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
46165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (ETHERNET_PREFERENCE_KEY.equals(key)) {
46265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return ConnectivityStatusTextGetter.createEthernetStatusTextGetter(mContext);
46365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
46465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
46565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return null;
46665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
46765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
46865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private MenuItem.UriGetter getIconUriGetterFromKey(String key) {
46965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (SoundActivity.getPreferenceKey().equals(key)) {
47065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return new SoundActivityImageUriGetter(mContext);
47165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
47265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
47365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (WifiNetworksActivity.PREFERENCE_KEY.equals(key)) {
47465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return ConnectivityStatusIconUriGetter.createWifiStatusIconUriGetter(mContext);
47565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
47665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
47765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return null;
47865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
47965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
48065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void addAccounts(ArrayObjectAdapter row) {
48165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
48265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (accountTypes.length == 0) {
48365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // That's weird, let's try updating.
48465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mAuthenticatorHelper.onAccountsUpdated(mContext, null);
48565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
48665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
48765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
48865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int googleAccountCount = 0;
48965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
49065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        for (String accountType : accountTypes) {
49165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            CharSequence label = mAuthenticatorHelper.getLabelForType(mContext, accountType);
49265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (label == null) {
49365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                continue;
49465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
49565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
49665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Account[] accounts = AccountManager.get(mContext).getAccountsByType(accountType);
49765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (ACCOUNT_TYPE_GOOGLE.equals(accountType)) {
49865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                googleAccountCount = accounts.length;
49965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
50065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (final Account account : accounts) {
50165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Intent i = new Intent(mContext, AccountSettingsActivity.class)
50265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account.name);
50365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
50465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                row.add(new MenuItem.Builder().id(mNextItemId++).title(account.name)
50565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .imageUriGetter(new AccountImageUriGetter(mContext, account))
50665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .intent(i)
50765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .build());
50865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
50965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
51065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5110898ab0f3d589be95488997e7ec1a8cc2a06b399Tim Kilbourn        if (canAddAccount() && (mAllowMultipleAccounts || googleAccountCount == 0)) {
51265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ComponentName componentName = new ComponentName("com.android.tv.settings",
51365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    "com.android.tv.settings.accounts.AddAccountWithTypeActivity");
51465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Intent i = new Intent().setComponent(componentName);
51565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
51665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (accountTypes.length == 1) {
51765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                i.putExtra(AccountManager.KEY_ACCOUNT_TYPE, accountTypes[0]);
51865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
51965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            row.add(new MenuItem.Builder().id(mNextItemId++)
52065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .title(mContext.getString(R.string.add_account))
52165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .imageResourceId(mContext, R.drawable.ic_settings_add)
52265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .intent(i).build());
52365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
52465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
52565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
52665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void addAccessories(ArrayObjectAdapter row) {
52765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mBtAdapter != null) {
52865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Set<BluetoothDevice> bondedDevices = mBtAdapter.getBondedDevices();
52965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (DEBUG) {
53065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Log.d(TAG, "List of Bonded BT Devices:");
53165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
53265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
53365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (BluetoothDevice device : bondedDevices) {
53465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (DEBUG) {
53565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    Log.d(TAG, "   Device name: " + device.getName() + " , Class: " +
53665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                            device.getBluetoothClass().getDeviceClass());
53765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
53865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
53965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                int resourceId = AccessoryUtils.getImageIdForDevice(device);
54065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Intent i = BluetoothAccessoryActivity.getIntent(mContext, device.getAddress(),
54165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        device.getName(), resourceId);
54265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
54365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
54465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                String desc = isDeviceConnected(device) ? mContext.getString(
54565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        R.string.accessory_connected)
54665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        : null;
54765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
54865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                row.add(new MenuItem.Builder().id(mNextItemId++).title(device.getName())
54965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .description(desc).imageResourceId(mContext, resourceId)
55065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        .intent(i).build());
55165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
55265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
55365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
55465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
555