Settings.java revision 3965ae6d1f60527c49e7914b624c9afe5bdd15e9
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import android.content.Intent;
20import android.content.pm.ActivityInfo;
21import android.content.pm.PackageManager;
22import android.content.pm.PackageManager.NameNotFoundException;
23import android.os.Bundle;
24import android.preference.PreferenceActivity;
25
26import java.util.HashMap;
27import java.util.List;
28
29/**
30 * Top-level settings activity to handle single pane and double pane UI layout.
31 */
32public class Settings extends PreferenceActivity {
33
34    private static final String META_DATA_KEY_HEADER_ID =
35            "com.android.settings.TOP_LEVEL_HEADER_ID";
36    private static final String META_DATA_KEY_FRAGMENT_CLASS =
37            "com.android.settings.FRAGMENT_CLASS";
38
39    private String mFragmentClass;
40    private int mTopLevelHeaderId;
41    private Header mFirstHeader;
42
43    // TODO: Update Call Settings based on airplane mode state.
44
45    protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
46
47    @Override
48    protected void onCreate(Bundle savedInstanceState) {
49        getMetaData();
50        super.onCreate(savedInstanceState);
51
52        // TODO: Do this only if 2-pane mode
53        highlightHeader();
54    }
55
56    @Override
57    public void onNewIntent(Intent intent) {
58        super.onNewIntent(intent);
59
60        // If it is not launched from history, then reset to top-level
61        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0
62                && mFirstHeader != null) {
63            switchToHeader(mFirstHeader);
64        }
65    }
66
67    private void highlightHeader() {
68        if (mTopLevelHeaderId != 0) {
69            Integer index = mHeaderIndexMap.get(mTopLevelHeaderId);
70            if (index != null) {
71                getListView().setItemChecked(index, true);
72            }
73        }
74    }
75
76    @Override
77    public Intent getIntent() {
78        String startingFragment = getStartingFragmentClass(super.getIntent());
79        if (startingFragment != null && !onIsMultiPane()) {
80            Intent modIntent = new Intent(super.getIntent());
81            modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
82            Bundle args = super.getIntent().getExtras();
83            if (args != null) {
84                args = new Bundle(args);
85            } else {
86                args = new Bundle();
87            }
88            args.putParcelable("intent", super.getIntent());
89            modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, super.getIntent().getExtras());
90            return modIntent;
91        }
92        return super.getIntent();
93    }
94
95    /**
96     * Checks if the component name in the intent is different from the Settings class and
97     * returns the class name to load as a fragment.
98     */
99    protected String getStartingFragmentClass(Intent intent) {
100        if (mFragmentClass != null) return mFragmentClass;
101
102        String intentClass = intent.getComponent().getClassName();
103        if (intentClass.equals(getClass().getName())) return null;
104
105        if ("com.android.settings.ManageApplications".equals(intentClass)
106                || "com.android.settings.RunningServices".equals(intentClass)
107                || "com.android.settings.applications.StorageUse".equals(intentClass)) {
108            // Old name of manage apps.
109            intentClass = com.android.settings.applications.ManageApplications.class.getName();
110        }
111
112        return intentClass;
113    }
114
115    /**
116     * Override initial header when an activity-alias is causing Settings to be launched
117     * for a specific fragment encoded in the android:name parameter.
118     */
119    @Override
120    public Header onGetInitialHeader() {
121        String fragmentClass = getStartingFragmentClass(super.getIntent());
122        if (fragmentClass != null) {
123            Header header = new Header();
124            header.fragment = fragmentClass;
125            header.fragmentArguments = getIntent().getExtras();
126            return header;
127        }
128        return super.onGetInitialHeader();
129    }
130
131    /**
132     * Populate the activity with the top-level headers.
133     */
134    @Override
135    public void onBuildHeaders(List<Header> target) {
136        loadHeadersFromResource(R.xml.settings_headers, target);
137
138        updateHeaderList(target);
139    }
140
141    private void updateHeaderList(List<Header> target) {
142        int i = 0;
143        while (i < target.size()) {
144            Header header = target.get(i);
145            // Ids are integers, so downcasting
146            int id = (int) header.id;
147            if (id == R.id.dock_settings) {
148                if (!needsDockSettings())
149                    target.remove(header);
150            } else if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
151                Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
152            } else if (id == R.id.call_settings) {
153                if (!Utils.isVoiceCapable(this))
154                    target.remove(header);
155            }
156            // Increment if the current one wasn't removed by the Utils code.
157            if (target.get(i) == header) {
158                // Hold on to the first header, when we need to reset to the top-level
159                if (i == 0) mFirstHeader = header;
160                mHeaderIndexMap.put(id, i);
161                i++;
162            }
163        }
164    }
165
166    private boolean needsDockSettings() {
167        return getResources().getBoolean(R.bool.has_dock_settings);
168    }
169
170    private void getMetaData() {
171        try {
172            ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
173                    PackageManager.GET_META_DATA);
174            if (ai == null || ai.metaData == null) return;
175            mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
176            mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
177        } catch (NameNotFoundException nnfe) {
178        }
179    }
180
181    /*
182     * Settings subclasses for launching independently.
183     */
184
185    public static class BluetoothSettingsActivity extends Settings { }
186    public static class WirelessSettingsActivity extends Settings { }
187    public static class TetherSettingsActivity extends Settings { }
188    public static class VpnSettingsActivity extends Settings { }
189    public static class DateTimeSettingsActivity extends Settings { }
190    public static class StorageSettingsActivity extends Settings { }
191    public static class WifiSettingsActivity extends Settings { }
192    public static class InputMethodAndLanguageSettingsActivity extends Settings { }
193    public static class InputMethodAndSubtypeEnablerActivity extends Settings { }
194    public static class LocalePickerActivity extends Settings { }
195    public static class UserDictionarySettingsActivity extends Settings { }
196    public static class SoundSettingsActivity extends Settings { }
197    public static class DisplaySettingsActivity extends Settings { }
198    public static class DeviceInfoSettingsActivity extends Settings { }
199    public static class ApplicationSettingsActivity extends Settings { }
200    public static class ManageApplicationsActivity extends Settings { }
201    public static class StorageUseActivity extends Settings { }
202    public static class DevelopmentSettingsActivity extends Settings { }
203    public static class AccessibilitySettingsActivity extends Settings { }
204    public static class SecuritySettingsActivity extends Settings { }
205    public static class PrivacySettingsActivity extends Settings { }
206    public static class DockSettingsActivity extends Settings { }
207    public static class RunningServicesActivity extends Settings { }
208    public static class VoiceInputOutputSettingsActivity extends Settings { }
209    public static class ManageAccountsSettingsActivity extends Settings { }
210    public static class PowerUsageSummaryActivity extends Settings { }
211}
212