summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/settings/AdvancedSecuritySettings.java221
-rw-r--r--src/com/android/settings/AirplaneModeEnabler.java17
-rw-r--r--src/com/android/settings/AirplaneModeVoiceActivity.java40
-rw-r--r--src/com/android/settings/ApnEditor.java10
-rw-r--r--src/com/android/settings/ApnSettings.java81
-rw-r--r--src/com/android/settings/ConfirmDeviceCredentialActivity.java5
-rw-r--r--src/com/android/settings/CryptKeeper.java61
-rw-r--r--src/com/android/settings/CryptKeeperConfirm.java24
-rw-r--r--src/com/android/settings/DataUsageSummary.java20
-rw-r--r--src/com/android/settings/DateTimeSettings.java14
-rw-r--r--src/com/android/settings/DevelopmentSettings.java107
-rw-r--r--src/com/android/settings/DeviceAdminAdd.java22
-rw-r--r--src/com/android/settings/DisplaySettings.java55
-rw-r--r--src/com/android/settings/HomeSettings.java68
-rw-r--r--src/com/android/settings/LocalePicker.java9
-rw-r--r--src/com/android/settings/ManagedProfileSetup.java5
-rw-r--r--src/com/android/settings/MasterClearConfirm.java70
-rw-r--r--src/com/android/settings/PrivacySettings.java77
-rw-r--r--src/com/android/settings/RadioInfo.java33
-rw-r--r--src/com/android/settings/SecuritySettings.java256
-rw-r--r--src/com/android/settings/Settings.java3
-rw-r--r--src/com/android/settings/SettingsActivity.java35
-rw-r--r--src/com/android/settings/SettingsPreferenceFragment.java26
-rw-r--r--src/com/android/settings/TetherSettings.java16
-rw-r--r--src/com/android/settings/TrustAgentSettings.java157
-rw-r--r--src/com/android/settings/UsageAccessSettings.java71
-rwxr-xr-xsrc/com/android/settings/UsageStatsActivity.java (renamed from src/com/android/settings/UsageStats.java)71
-rw-r--r--src/com/android/settings/Utils.java71
-rw-r--r--src/com/android/settings/VoiceSettingsActivity.java51
-rw-r--r--src/com/android/settings/WirelessSettings.java17
-rw-r--r--src/com/android/settings/accessibility/AccessibilitySettings.java40
-rw-r--r--src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java4
-rw-r--r--src/com/android/settings/accounts/AccountSettings.java235
-rw-r--r--src/com/android/settings/accounts/ManageAccountsSettings.java4
-rw-r--r--src/com/android/settings/applications/AppOpsState.java4
-rwxr-xr-xsrc/com/android/settings/applications/InstalledAppDetails.java59
-rw-r--r--src/com/android/settings/applications/ManageApplications.java15
-rw-r--r--src/com/android/settings/bluetooth/BluetoothDevicePreference.java2
-rw-r--r--src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java2
-rwxr-xr-xsrc/com/android/settings/bluetooth/BluetoothPairingDialog.java51
-rw-r--r--src/com/android/settings/bluetooth/BluetoothPairingRequest.java4
-rw-r--r--src/com/android/settings/bluetooth/BluetoothPermissionRequest.java25
-rwxr-xr-xsrc/com/android/settings/bluetooth/BluetoothSettings.java170
-rwxr-xr-xsrc/com/android/settings/bluetooth/CachedBluetoothDevice.java2
-rwxr-xr-xsrc/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java8
-rw-r--r--src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java6
-rwxr-xr-xsrc/com/android/settings/bluetooth/DeviceProfilesSettings.java126
-rw-r--r--src/com/android/settings/bluetooth/MessageAccessSettings.java167
-rwxr-xr-xsrc/com/android/settings/bluetooth/Utils.java17
-rw-r--r--src/com/android/settings/fuelgauge/BatteryEntry.java34
-rw-r--r--src/com/android/settings/fuelgauge/BatteryHistoryChart.java9
-rw-r--r--src/com/android/settings/fuelgauge/BatteryHistoryDetail.java14
-rw-r--r--src/com/android/settings/fuelgauge/BatteryHistoryPreference.java2
-rw-r--r--src/com/android/settings/fuelgauge/PowerGaugePreference.java10
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageSummary.java34
-rw-r--r--src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java243
-rwxr-xr-xsrc/com/android/settings/inputmethod/InputMethodPreference.java12
-rw-r--r--src/com/android/settings/location/DimmableIconPreference.java63
-rw-r--r--src/com/android/settings/location/InjectedSetting.java2
-rw-r--r--src/com/android/settings/location/RecentLocationApps.java50
-rw-r--r--src/com/android/settings/location/SettingsInjector.java2
-rw-r--r--src/com/android/settings/net/UidDetail.java2
-rw-r--r--src/com/android/settings/net/UidDetailProvider.java44
-rw-r--r--src/com/android/settings/nfc/NfcEnabler.java32
-rw-r--r--src/com/android/settings/nfc/PaymentDefaultDialog.java20
-rw-r--r--src/com/android/settings/notification/AppNotificationSettings.java26
-rw-r--r--src/com/android/settings/notification/NotificationAppList.java83
-rw-r--r--src/com/android/settings/notification/NotificationSettings.java62
-rw-r--r--src/com/android/settings/notification/RedactionInterstitial.java2
-rw-r--r--src/com/android/settings/notification/RedactionSettingsStandalone.java43
-rw-r--r--src/com/android/settings/notification/VolumeSeekBarPreference.java31
-rw-r--r--src/com/android/settings/notification/ZenModeConditionSelection.java14
-rw-r--r--src/com/android/settings/search/Index.java72
-rw-r--r--src/com/android/settings/search/Ranking.java4
-rw-r--r--src/com/android/settings/search/SearchIndexableResources.java27
-rw-r--r--src/com/android/settings/sim/SimSettings.java56
-rw-r--r--src/com/android/settings/tts/TtsEngineSettingsFragment.java2
-rw-r--r--src/com/android/settings/users/AppRestrictionsFragment.java19
-rw-r--r--src/com/android/settings/users/UserSettings.java47
-rw-r--r--src/com/android/settings/voice/VoiceInputSettings.java83
-rw-r--r--src/com/android/settings/vpn2/VpnSettings.java53
-rw-r--r--src/com/android/settings/widget/SetupWizardIllustration.java42
-rw-r--r--src/com/android/settings/widget/SwitchBar.java2
-rw-r--r--src/com/android/settings/wifi/AccessPoint.java43
-rw-r--r--src/com/android/settings/wifi/AdvancedWifiSettings.java107
-rw-r--r--src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java29
-rw-r--r--src/com/android/settings/wifi/WifiApEnabler.java56
-rw-r--r--src/com/android/settings/wifi/WifiConfigController.java110
-rw-r--r--src/com/android/settings/wifi/WifiSettings.java190
-rw-r--r--src/com/android/settings/wifi/WifiSettingsForSetupWizard.java53
-rw-r--r--src/com/android/settings/wifi/WifiSetupActivity.java1
-rw-r--r--src/com/android/settings/wifi/WpsDialog.java12
92 files changed, 2693 insertions, 1803 deletions
diff --git a/src/com/android/settings/AdvancedSecuritySettings.java b/src/com/android/settings/AdvancedSecuritySettings.java
deleted file mode 100644
index 3ddbf96..0000000
--- a/src/com/android/settings/AdvancedSecuritySettings.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings;
-
-import com.android.internal.widget.LockPatternUtils;
-
-import android.app.ListFragment;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.service.trust.TrustAgentService;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.CheckBox;
-import android.widget.TextView;
-
-import java.util.List;
-
-public class AdvancedSecuritySettings extends ListFragment implements View.OnClickListener {
- static final String TAG = "AdvancedSecuritySettings";
-
- private static final String SERVICE_INTERFACE = TrustAgentService.SERVICE_INTERFACE;
-
- private final ArraySet<ComponentName> mActiveAgents = new ArraySet<ComponentName>();
- private final ArrayMap<ComponentName, AgentInfo> mAvailableAgents
- = new ArrayMap<ComponentName, AgentInfo>();
-
- private LockPatternUtils mLockPatternUtils;
-
- public static final class AgentInfo {
- CharSequence label;
- ComponentName component; // service that implements ITrustAgent
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof AgentInfo) {
- return component.equals(((AgentInfo)other).component);
- }
- return true;
- }
-
- public int compareTo(AgentInfo other) {
- return component.compareTo(other.component);
- }
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- if (mLockPatternUtils == null) {
- mLockPatternUtils = new LockPatternUtils(
- container.getContext().getApplicationContext());
- }
- setListAdapter(new AgentListAdapter());
- return inflater.inflate(R.layout.advanced_security_settings, container, false);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- updateList();
- }
-
- void updateList() {
- Context context = getActivity();
- if (context == null) {
- return;
- }
-
- loadActiveAgents();
-
- PackageManager pm = getActivity().getPackageManager();
- Intent trustAgentIntent = new Intent(SERVICE_INTERFACE);
- List<ResolveInfo> resolveInfos = pm.queryIntentServices(trustAgentIntent,
- PackageManager.GET_META_DATA);
-
- mAvailableAgents.clear();
- mAvailableAgents.ensureCapacity(resolveInfos.size());
-
- for (ResolveInfo resolveInfo : resolveInfos) {
- if (resolveInfo.serviceInfo == null) continue;
- if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
- ComponentName name = TrustAgentUtils.getComponentName(resolveInfo);
- if (!mAvailableAgents.containsKey(name)) {
- AgentInfo agentInfo = new AgentInfo();
- agentInfo.label = resolveInfo.loadLabel(pm);
- agentInfo.component = name;
- mAvailableAgents.put(name, agentInfo);
- }
- }
- ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
- }
-
- @Override
- public void onClick(View view) {
- ViewHolder h = (ViewHolder) view.getTag();
-
- if (view.getId() == R.id.clickable) {
- boolean wasActive = mActiveAgents.contains(h.agentInfo.component);
- loadActiveAgents();
- if (!wasActive) {
- mActiveAgents.add(h.agentInfo.component);
- } else {
- mActiveAgents.remove(h.agentInfo.component);
- }
- saveActiveAgents();
- ((BaseAdapter) getListAdapter()).notifyDataSetChanged();
- }
- }
-
- private void loadActiveAgents() {
- mActiveAgents.clear();
- List<ComponentName> activeTrustAgents = mLockPatternUtils.getEnabledTrustAgents();
- if (activeTrustAgents != null) {
- mActiveAgents.addAll(activeTrustAgents);
- }
- }
-
- private void saveActiveAgents() {
- mLockPatternUtils.setEnabledTrustAgents(mActiveAgents);
- }
-
- static class ViewHolder {
- TextView name;
- CheckBox checkbox;
- TextView description;
- AgentInfo agentInfo;
- View clickable;
- }
-
- class AgentListAdapter extends BaseAdapter {
- final LayoutInflater mInflater;
-
- AgentListAdapter() {
- mInflater = (LayoutInflater)
- getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- public boolean hasStableIds() {
- return false;
- }
-
- public int getCount() {
- return mAvailableAgents.size();
- }
-
- public Object getItem(int position) {
- return mAvailableAgents.valueAt(position);
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- public boolean isEnabled(int position) {
- return true;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- View v;
- if (convertView == null) {
- v = newView(parent);
- } else {
- v = convertView;
- }
- bindView(v, position);
- return v;
- }
-
- public View newView(ViewGroup parent) {
- View v = mInflater.inflate(R.layout.trust_agent_item, parent, false);
- ViewHolder h = new ViewHolder();
- h.name = (TextView)v.findViewById(R.id.name);
- h.checkbox = (CheckBox)v.findViewById(R.id.checkbox);
- h.clickable = v.findViewById(R.id.clickable);
- h.clickable.setOnClickListener(AdvancedSecuritySettings.this);
- h.description = (TextView)v.findViewById(R.id.description);
- v.setTag(h);
- h.clickable.setTag(h);
- return v;
- }
-
- public void bindView(View view, int position) {
- ViewHolder vh = (ViewHolder) view.getTag();
- AgentInfo item = mAvailableAgents.valueAt(position);
- vh.name.setText(item.label);
- vh.checkbox.setChecked(mActiveAgents.contains(item.component));
- vh.agentInfo = item;
- }
- }
-}
diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java
index d1c591e..4ce5198 100644
--- a/src/com/android/settings/AirplaneModeEnabler.java
+++ b/src/com/android/settings/AirplaneModeEnabler.java
@@ -25,6 +25,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
+import android.preference.SwitchPreference;
import android.provider.Settings;
import com.android.internal.telephony.PhoneStateIntentReceiver;
@@ -36,7 +37,7 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
private PhoneStateIntentReceiver mPhoneStateReceiver;
- private final CheckBoxPreference mCheckBoxPref;
+ private final SwitchPreference mSwitchPref;
private static final int EVENT_SERVICE_STATE_CHANGED = 3;
@@ -58,10 +59,10 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
}
};
- public AirplaneModeEnabler(Context context, CheckBoxPreference airplaneModeCheckBoxPreference) {
+ public AirplaneModeEnabler(Context context, SwitchPreference airplaneModeCheckBoxPreference) {
mContext = context;
- mCheckBoxPref = airplaneModeCheckBoxPreference;
+ mSwitchPref = airplaneModeCheckBoxPreference;
airplaneModeCheckBoxPreference.setPersistent(false);
@@ -71,10 +72,10 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
public void resume() {
- mCheckBoxPref.setChecked(isAirplaneModeOn(mContext));
+ mSwitchPref.setChecked(isAirplaneModeOn(mContext));
mPhoneStateReceiver.registerIntent();
- mCheckBoxPref.setOnPreferenceChangeListener(this);
+ mSwitchPref.setOnPreferenceChangeListener(this);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
mAirplaneModeObserver);
@@ -82,7 +83,7 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
public void pause() {
mPhoneStateReceiver.unregisterIntent();
- mCheckBoxPref.setOnPreferenceChangeListener(null);
+ mSwitchPref.setOnPreferenceChangeListener(null);
mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
}
@@ -96,7 +97,7 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
enabling ? 1 : 0);
// Update the UI to reflect system setting
- mCheckBoxPref.setChecked(enabling);
+ mSwitchPref.setChecked(enabling);
// Post the intent
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
@@ -113,7 +114,7 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
* - mobile does not send failure notification, fail on timeout.
*/
private void onAirplaneModeChanged() {
- mCheckBoxPref.setChecked(isAirplaneModeOn(mContext));
+ mSwitchPref.setChecked(isAirplaneModeOn(mContext));
}
/**
diff --git a/src/com/android/settings/AirplaneModeVoiceActivity.java b/src/com/android/settings/AirplaneModeVoiceActivity.java
new file mode 100644
index 0000000..3ab0c37
--- /dev/null
+++ b/src/com/android/settings/AirplaneModeVoiceActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * Activity for modifying the {@link Settings.Global#AIRPLANE_MODE_ON AIRPLANE_MODE_ON}
+ * setting using the Voice Interaction API.
+ */
+public class AirplaneModeVoiceActivity extends VoiceSettingsActivity {
+ private static final String TAG = "AirplaneModeVoiceActivity";
+
+ protected void onVoiceSettingInteraction(Intent intent) {
+ if (intent.hasExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED)) {
+ boolean enabled =
+ intent.getBooleanExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, false);
+ Settings.Global.putInt(getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, enabled ? 1 : 0);
+ } else {
+ Log.v(TAG, "Missing airplane mode extra");
+ }
+ }
+}
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index 738d433..8cfee92 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -327,6 +327,13 @@ public class ApnEditor extends PreferenceActivity
mMvnoType.setSummary(
checkNull(mvnoDescription(mMvnoType.getValue())));
mMvnoMatchData.setSummary(checkNull(mMvnoMatchData.getText()));
+ // allow user to edit carrier_enabled for some APN
+ boolean ceEditable = getResources().getBoolean(R.bool.config_allow_edit_carrier_enabled);
+ if (ceEditable) {
+ mCarrierEnabled.setEnabled(true);
+ } else {
+ mCarrierEnabled.setEnabled(false);
+ }
}
/**
@@ -571,6 +578,7 @@ public class ApnEditor extends PreferenceActivity
values.put(Telephony.Carriers.MVNO_TYPE, checkNotSet(mMvnoType.getValue()));
values.put(Telephony.Carriers.MVNO_MATCH_DATA, checkNotSet(mMvnoMatchData.getText()));
+ values.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled.isChecked() ? 1 : 0);
getContentResolver().update(mUri, values, null, null);
return true;
@@ -664,6 +672,8 @@ public class ApnEditor extends PreferenceActivity
if (pref != null) {
if (pref.equals(mPassword)){
pref.setSummary(starify(sharedPreferences.getString(key, "")));
+ } else if (pref.equals(mCarrierEnabled)) {
+ // do nothing
} else {
pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
}
diff --git a/src/com/android/settings/ApnSettings.java b/src/com/android/settings/ApnSettings.java
index ef79f2b..d214df2 100644
--- a/src/com/android/settings/ApnSettings.java
+++ b/src/com/android/settings/ApnSettings.java
@@ -39,8 +39,12 @@ import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Telephony;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.telephony.Phone;
@@ -50,7 +54,7 @@ import com.android.internal.telephony.TelephonyProperties;
import java.util.ArrayList;
-public class ApnSettings extends PreferenceActivity implements
+public class ApnSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener {
static final String TAG = "ApnSettings";
@@ -121,33 +125,49 @@ public class ApnSettings extends PreferenceActivity implements
}
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mUm = (UserManager) getSystemService(Context.USER_SERVICE);
+ mMobileStateFilter = new IntentFilter(
+ TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+
+ if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ setHasOptionsMenu(true);
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ TextView empty = (TextView) getView().findViewById(android.R.id.empty);
+ if (empty != null) {
+ empty.setText(R.string.apn_settings_not_available);
+ getListView().setEmptyView(empty);
+ }
+
if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
mUnavailable = true;
- setContentView(R.layout.apn_disallowed_preference_screen);
+ setPreferenceScreen(new PreferenceScreen(getActivity(), null));
return;
}
addPreferencesFromResource(R.xml.apn_settings);
- getListView().setItemsCanFocus(true);
- mMobileStateFilter = new IntentFilter(
- TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+ getListView().setItemsCanFocus(true);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
if (mUnavailable) {
return;
}
- registerReceiver(mMobileStateReceiver, mMobileStateFilter);
+ getActivity().registerReceiver(mMobileStateReceiver, mMobileStateFilter);
if (!mRestoreDefaultApnMode) {
fillList();
@@ -157,18 +177,18 @@ public class ApnSettings extends PreferenceActivity implements
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
if (mUnavailable) {
return;
}
- unregisterReceiver(mMobileStateReceiver);
+ getActivity().unregisterReceiver(mMobileStateReceiver);
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
if (mRestoreDefaultApnThread != null) {
@@ -199,7 +219,7 @@ public class ApnSettings extends PreferenceActivity implements
String key = cursor.getString(ID_INDEX);
String type = cursor.getString(TYPES_INDEX);
- ApnPreference pref = new ApnPreference(this);
+ ApnPreference pref = new ApnPreference(getActivity());
pref.setKey(key);
pref.setTitle(name);
@@ -228,16 +248,18 @@ public class ApnSettings extends PreferenceActivity implements
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- menu.add(0, MENU_NEW, 0,
- getResources().getString(R.string.menu_new))
- .setIcon(android.R.drawable.ic_menu_add)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- menu.add(0, MENU_RESTORE, 0,
- getResources().getString(R.string.menu_restore))
- .setIcon(android.R.drawable.ic_menu_upload);
- return true;
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (!mUnavailable) {
+ menu.add(0, MENU_NEW, 0,
+ getResources().getString(R.string.menu_new))
+ .setIcon(android.R.drawable.ic_menu_add)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ menu.add(0, MENU_RESTORE, 0,
+ getResources().getString(R.string.menu_restore))
+ .setIcon(android.R.drawable.ic_menu_upload);
+ }
+
+ super.onCreateOptionsMenu(menu, inflater);
}
@Override
@@ -329,9 +351,9 @@ public class ApnSettings extends PreferenceActivity implements
fillList();
getPreferenceScreen().setEnabled(true);
mRestoreDefaultApnMode = false;
- dismissDialog(DIALOG_RESTORE_DEFAULTAPN);
+ removeDialog(DIALOG_RESTORE_DEFAULTAPN);
Toast.makeText(
- ApnSettings.this,
+ getActivity(),
getResources().getString(
R.string.restore_default_apn_completed),
Toast.LENGTH_LONG).show();
@@ -362,20 +384,13 @@ public class ApnSettings extends PreferenceActivity implements
}
@Override
- protected Dialog onCreateDialog(int id) {
+ public Dialog onCreateDialog(int id) {
if (id == DIALOG_RESTORE_DEFAULTAPN) {
- ProgressDialog dialog = new ProgressDialog(this);
+ ProgressDialog dialog = new ProgressDialog(getActivity());
dialog.setMessage(getResources().getString(R.string.restore_default_apn));
dialog.setCancelable(false);
return dialog;
}
return null;
}
-
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- if (id == DIALOG_RESTORE_DEFAULTAPN) {
- getPreferenceScreen().setEnabled(false);
- }
- }
}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
index 6a5c486..6b2bfd2 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
@@ -18,6 +18,7 @@
package com.android.settings;
import android.app.Activity;
+import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -34,8 +35,8 @@ public class ConfirmDeviceCredentialActivity extends Activity {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
- String title = intent.getStringExtra(Intent.EXTRA_TITLE);
- String details = intent.getStringExtra(Intent.EXTRA_DETAILS);
+ String title = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
+ String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
if (!helper.launchConfirmationActivity(0 /* request code */, title, details)) {
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 129b201..7e92cc6 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -37,9 +37,8 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
-
-import android.phone.PhoneManager;
import android.provider.Settings;
+import android.telecomm.TelecommManager;
import android.telephony.TelephonyManager;
import android.text.Editable;
import android.text.TextUtils;
@@ -118,6 +117,8 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
private boolean mValidationRequested;
/** A flag to indicate that the volume is in a bad state (e.g. partially encrypted). */
private boolean mEncryptionGoneBad;
+ /** If gone bad, should we show encryption failed (false) or corrupt (true)*/
+ private boolean mCorrupt;
/** A flag to indicate when the back event should be ignored */
private boolean mIgnoreBack = false;
private int mCooldown;
@@ -133,6 +134,9 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
// how long we wait to clear a wrong pattern
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 1500;
+ // how long we wait to clear a right pattern
+ private static final int RIGHT_PATTERN_CLEAR_TIMEOUT_MS = 500;
+
private Runnable mClearPatternRunnable = new Runnable() {
public void run() {
mLockPatternView.clearPattern();
@@ -167,9 +171,18 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
if (failedAttempts == 0) {
// The password was entered successfully. Simply do nothing
// and wait for the service restart to switch to surfacefligner
+ if (mLockPatternView != null) {
+ mLockPatternView.removeCallbacks(mClearPatternRunnable);
+ mLockPatternView.postDelayed(mClearPatternRunnable, RIGHT_PATTERN_CLEAR_TIMEOUT_MS);
+ }
} else if (failedAttempts == MAX_FAILED_ATTEMPTS) {
// Factory reset the device.
sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
+ } else if (failedAttempts == -1) {
+ // Right password, but decryption failed. Tell user bad news ...
+ setContentView(R.layout.crypt_keeper_progress);
+ showFactoryReset(true);
+ return;
} else {
// Wrong entry. Handle pattern case.
if (mLockPatternView != null) {
@@ -213,12 +226,14 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
}
private class ValidationTask extends AsyncTask<Void, Void, Boolean> {
+ int state;
+
@Override
protected Boolean doInBackground(Void... params) {
final IMountService service = getMountService();
try {
Log.d(TAG, "Validating encryption state.");
- int state = service.getEncryptionState();
+ state = service.getEncryptionState();
if (state == IMountService.ENCRYPTION_STATE_NONE) {
Log.w(TAG, "Unexpectedly in CryptKeeper even though there is no encryption.");
return true; // Unexpected, but fine, I guess...
@@ -236,6 +251,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
if (Boolean.FALSE.equals(result)) {
Log.w(TAG, "Incomplete, or corrupted encryption detected. Prompting user to wipe.");
mEncryptionGoneBad = true;
+ mCorrupt = state == IMountService.ENCRYPTION_STATE_ERROR_CORRUPT;
} else {
Log.d(TAG, "Encryption state validated. Proceeding to configure UI");
}
@@ -392,7 +408,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
private void setupUi() {
if (mEncryptionGoneBad || isDebugView(FORCE_VIEW_ERROR)) {
setContentView(R.layout.crypt_keeper_progress);
- showFactoryReset();
+ showFactoryReset(mCorrupt);
return;
}
@@ -404,6 +420,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
new AsyncTask<Void, Void, Void>() {
int type = StorageManager.CRYPT_TYPE_PASSWORD;
String owner_info;
+ boolean pattern_visible;
@Override
public Void doInBackground(Void... v) {
@@ -411,6 +428,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
final IMountService service = getMountService();
type = service.getPasswordType();
owner_info = service.getField("OwnerInfo");
+ pattern_visible = !("0".equals(service.getField("PatternVisible")));
} catch (Exception e) {
Log.e(TAG, "Error calling mount service " + e);
}
@@ -440,6 +458,10 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
passwordEntryInit();
+ if (mLockPatternView != null) {
+ mLockPatternView.setInStealthMode(!pattern_visible);
+ }
+
if (mCooldown > 0) {
setBackFunctionality(false);
cooldown(); // in case we are cooling down and coming back from emergency dialler
@@ -508,7 +530,13 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
updateProgress();
}
- private void showFactoryReset() {
+ /**
+ * Show factory reset screen allowing the user to reset their phone when
+ * there is nothing else we can do
+ * @param corrupt true if userdata is corrupt, false if encryption failed
+ * partway through
+ */
+ private void showFactoryReset(boolean corrupt) {
// Hide the encryption-bot to make room for the "factory reset" button
findViewById(R.id.encroid).setVisibility(View.GONE);
@@ -524,8 +552,13 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
});
// Alert the user of the failure.
- ((TextView) findViewById(R.id.title)).setText(R.string.crypt_keeper_failed_title);
- ((TextView) findViewById(R.id.status)).setText(R.string.crypt_keeper_failed_summary);
+ if (corrupt) {
+ ((TextView) findViewById(R.id.title)).setText(R.string.crypt_keeper_data_corrupt_title);
+ ((TextView) findViewById(R.id.status)).setText(R.string.crypt_keeper_data_corrupt_summary);
+ } else {
+ ((TextView) findViewById(R.id.title)).setText(R.string.crypt_keeper_failed_title);
+ ((TextView) findViewById(R.id.status)).setText(R.string.crypt_keeper_failed_summary);
+ }
final View view = findViewById(R.id.bottom_divider);
// TODO(viki): Why would the bottom divider be missing in certain layouts? Investigate.
@@ -538,7 +571,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
final String state = SystemProperties.get("vold.encrypt_progress");
if ("error_partially_encrypted".equals(state)) {
- showFactoryReset();
+ showFactoryReset(false);
return;
}
@@ -859,7 +892,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
}
int textId;
- if (getPhoneManager().isInAPhoneCall()) {
+ if (getTelecommManager().isInCall()) {
// Show "return to call"
textId = R.string.cryptkeeper_return_to_call;
} else {
@@ -873,9 +906,9 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
}
private void takeEmergencyCallAction() {
- PhoneManager phoneManager = getPhoneManager();
- if (phoneManager.isInAPhoneCall()) {
- phoneManager.showCallScreen(false /* showDialpad */);
+ TelecommManager telecommManager = getTelecommManager();
+ if (telecommManager.isInCall()) {
+ telecommManager.showInCallScreen(false /* showDialpad */);
} else {
launchEmergencyDialer();
}
@@ -894,8 +927,8 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
return (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
}
- private PhoneManager getPhoneManager() {
- return (PhoneManager) getSystemService(Context.PHONE_SERVICE);
+ private TelecommManager getTelecommManager() {
+ return (TelecommManager) getSystemService(Context.TELECOMM_SERVICE);
}
/**
diff --git a/src/com/android/settings/CryptKeeperConfirm.java b/src/com/android/settings/CryptKeeperConfirm.java
index 71d5e96..7641525 100644
--- a/src/com/android/settings/CryptKeeperConfirm.java
+++ b/src/com/android/settings/CryptKeeperConfirm.java
@@ -25,6 +25,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.os.storage.IMountService;
import android.util.Log;
import android.view.LayoutInflater;
@@ -32,6 +33,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import com.android.internal.widget.LockPatternUtils;
+
public class CryptKeeperConfirm extends Fragment {
public static class Blank extends Activity {
@@ -90,6 +93,27 @@ public class CryptKeeperConfirm extends Fragment {
return;
}
+ /* WARNING - nasty hack!
+ Settings for the lock screen are not available to the crypto
+ screen (CryptKeeper) at boot. We duplicate the ones that
+ CryptKeeper needs to the crypto key/value store when they are
+ modified (see LockPatternUtils).
+ However, prior to encryption, the crypto key/value store is not
+ persisted across reboots, thus modified settings are lost to
+ CryptKeeper.
+ In order to make sure CryptKeeper had the correct settings after
+ first encrypting, we thus need to rewrite them, which ensures the
+ crypto key/value store is up to date. On encryption, this store
+ is then persisted, and the settings will be there on future
+ reboots.
+ */
+ LockPatternUtils utils = new LockPatternUtils(getActivity());
+ utils.setVisiblePatternEnabled(utils.isVisiblePatternEnabled());
+ if (utils.isOwnerInfoEnabled()) {
+ utils.setOwnerInfo(utils.getOwnerInfo(UserHandle.USER_OWNER),
+ UserHandle.USER_OWNER);
+ }
+
Intent intent = new Intent(getActivity(), Blank.class);
intent.putExtras(getArguments());
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index f7a0618..17c6d88 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -818,14 +818,21 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
View title = null;
if (detail.detailLabels != null) {
- for (CharSequence label : detail.detailLabels) {
+ final int n = detail.detailLabels.length;
+ for (int i = 0; i < n; ++i) {
+ CharSequence label = detail.detailLabels[i];
+ CharSequence contentDescription = detail.detailContentDescriptions[i];
title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
- ((TextView) title.findViewById(R.id.app_title)).setText(label);
+ TextView appTitle = (TextView) title.findViewById(R.id.app_title);
+ appTitle.setText(label);
+ appTitle.setContentDescription(contentDescription);
mAppTitles.addView(title);
}
} else {
title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
- ((TextView) title.findViewById(R.id.app_title)).setText(detail.label);
+ TextView appTitle = (TextView) title.findViewById(R.id.app_title);
+ appTitle.setText(detail.label);
+ appTitle.setContentDescription(detail.contentDescription);
mAppTitles.addView(title);
}
@@ -1786,10 +1793,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
public static void show(DataUsageSummary parent) {
if (!parent.isAdded()) return;
+ final NetworkPolicy policy = parent.mPolicyEditor.getPolicy(parent.mTemplate);
+ if (policy == null) return;
+
final Resources res = parent.getResources();
final CharSequence message;
- final long minLimitBytes = (long) (
- parent.mPolicyEditor.getPolicy(parent.mTemplate).warningBytes * 1.2f);
+ final long minLimitBytes = (long) (policy.warningBytes * 1.2f);
final long limitBytes;
// TODO: customize default limits based on network template
@@ -2224,6 +2233,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
if (detail != null) {
icon.setImageDrawable(detail.icon);
title.setText(detail.label);
+ title.setContentDescription(detail.contentDescription);
} else {
icon.setImageDrawable(null);
title.setText(null);
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 77561bd..8eb9c52 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -16,6 +16,7 @@
package com.android.settings;
+import android.app.admin.DevicePolicyManager;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.DatePickerDialog;
@@ -89,12 +90,23 @@ public class DateTimeSettings extends SettingsPreferenceFragment
boolean autoTimeEnabled = getAutoState(Settings.Global.AUTO_TIME);
boolean autoTimeZoneEnabled = getAutoState(Settings.Global.AUTO_TIME_ZONE);
+ mAutoTimePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
+
+ DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context
+ .DEVICE_POLICY_SERVICE);
+ if (dpm.getAutoTimeRequired()) {
+ mAutoTimePref.setEnabled(false);
+
+ // If Settings.Global.AUTO_TIME is false it will be set to true
+ // by the device policy manager very soon.
+ // Note that this app listens to that change.
+ }
+
Intent intent = getActivity().getIntent();
boolean isFirstRun = intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
mDummyDate = Calendar.getInstance();
- mAutoTimePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
mAutoTimePref.setChecked(autoTimeEnabled);
mAutoTimeZonePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME_ZONE);
// Override auto-timezone if it's a wifi-only device or if we're still in setup wizard.
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index ba8e2f1..d801ae0 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -31,7 +31,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.database.Cursor;
import android.hardware.usb.IUsbManager;
+import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
@@ -110,6 +112,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private static final String DEBUG_APP_KEY = "debug_app";
private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
+ private static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
private static final String STRICT_MODE_KEY = "strict_mode";
private static final String POINTER_LOCATION_KEY = "pointer_location";
private static final String SHOW_TOUCHES_KEY = "show_touches";
@@ -117,6 +120,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
private static final String USE_NUPLAYER_KEY = "use_nuplayer";
+ private static final String USB_AUDIO_KEY = "usb_audio";
private static final String USE_AWESOMEPLAYER_PROPERTY = "persist.sys.media.use-awesome";
private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
@@ -151,6 +155,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
private static final String WEBVIEW_DATA_REDUCTION_PROXY_KEY = "webview_data_reduction_proxy";
+ // GoogleSetting name for the data reduction proxy setting.
+ // Setting type: int ( 0 = disallow, 1 = allow )
+ private static final String WEBVIEW_DATA_REDUCTION_PROXY = "use_webview_data_reduction_proxy";
private static final String PROCESS_STATS = "proc_stats";
@@ -164,6 +171,11 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
+ // The setting Uri. Used when querying GoogleSettings.
+ private static final Uri GOOGLE_SETTINGS_CONTENT_URI = Uri.parse("content://com.google.settings/partner");
+ private static final String GOOGLE_SETTINGS_COMPONENT = "com.google.android.gms";
+ private static final String GOOGLE_SETTINGS_ACTIVITY = ".app.settings.GoogleSettingsActivity";
+
private static String DEFAULT_LOG_RING_BUFFER_SIZE_IN_BYTES = "262144"; // 256K
private IWindowManager mWindowManager;
@@ -186,6 +198,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private CheckBoxPreference mBtHciSnoopLog;
private CheckBoxPreference mEnableOemUnlock;
private CheckBoxPreference mAllowMockLocation;
+ private CheckBoxPreference mDebugViewAttributes;
private PreferenceScreen mPassword;
private String mDebugApp;
@@ -222,6 +235,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private ListPreference mSimulateColorSpace;
private CheckBoxPreference mUseNuplayer;
+ private CheckBoxPreference mUSBAudio;
private CheckBoxPreference mImmediatelyDestroyActivities;
private ListPreference mAppProcessLimit;
@@ -293,6 +307,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
mEnableOemUnlock = null;
}
mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
+ mDebugViewAttributes = findAndInitCheckboxPref(DEBUG_VIEW_ATTRIBUTES);
mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
mAllPrefs.add(mPassword);
@@ -343,6 +358,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
mOpenGLTraces = addListPreference(OPENGL_TRACES_KEY);
mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
mUseNuplayer = findAndInitCheckboxPref(USE_NUPLAYER_KEY);
+ mUSBAudio = findAndInitCheckboxPref(USB_AUDIO_KEY);
mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
@@ -366,12 +382,13 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
mAllPrefs.add(mProcessStats);
mWebViewDataReductionProxy = findAndInitCheckboxPref(WEBVIEW_DATA_REDUCTION_PROXY_KEY);
- String key = Settings.Global.getString(getActivity().getContentResolver(),
- Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY);
- // Disable the selection if the key is not available for some reason.
- if (key == null || key.isEmpty()) {
- disableForUser(mWebViewDataReductionProxy);
- }
+ mWebViewDataReductionProxy.setOnPreferenceChangeListener(
+ new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ return handleDataReductionProxyPreferenceChange();
+ }
+ });
}
private ListPreference addListPreference(String prefKey) {
@@ -516,6 +533,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
}
updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
+ updateCheckBox(mDebugViewAttributes, Settings.Global.getInt(cr,
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0);
updateHdcpValues();
updatePasswordSummary();
updateDebuggerOptions();
@@ -549,6 +568,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
updateWifiAllowScansWithTrafficOptions();
updateSimulateColorSpace();
updateUseNuplayerOptions();
+ updateUSBAudioOptions();
}
private void resetDangerousOptions() {
@@ -1013,6 +1033,17 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
pokeSystemProperties();
}
+ private void updateUSBAudioOptions() {
+ updateCheckBox(mUSBAudio, Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0) != 0);
+ }
+
+ private void writeUSBAudioOptions() {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
+ mUSBAudio.isChecked() ? 1 : 0);
+ }
+
private void updateForceRtlOptions() {
updateCheckBox(mForceRtlLayout, Settings.Global.getInt(getActivity().getContentResolver(),
Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0);
@@ -1263,6 +1294,50 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
getActivity().getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0);
}
+ // Reads the googlesetting and converts to an int. Throws an exception if GoogleSettings
+ // provider does not exist or if the setting name cannot be found.
+ private int getGoogleSettingValue(String name) throws Exception {
+ String value = null;
+ Cursor c = null;
+ try {
+ ContentResolver resolver = getActivity().getContentResolver();
+ c = resolver.query(GOOGLE_SETTINGS_CONTENT_URI, new String[] { "value" },
+ "name=?", new String[]{ name }, null);
+ if (c != null && c.moveToNext()) value = c.getString(0);
+ } finally {
+ if (c != null) c.close();
+ }
+ // Throw an exception if value is null. This will indicate that setting is not found.
+ return Integer.parseInt(value);
+ }
+
+ private boolean handleDataReductionProxyPreferenceChange() {
+ int val;
+ try {
+ val = getGoogleSettingValue(WEBVIEW_DATA_REDUCTION_PROXY);
+ } catch (Exception e) {
+ // Accessing GoogleSettings failed. Use the developer setting.
+ return true;
+ }
+
+ Intent i = new Intent();
+ i.setClassName(GOOGLE_SETTINGS_COMPONENT,
+ GOOGLE_SETTINGS_COMPONENT + GOOGLE_SETTINGS_ACTIVITY);
+ try {
+ startActivity(i);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // We found the GoogleSetting but for some reason activity not found.
+ // Do our best and put an alert dialog
+ new AlertDialog.Builder(getActivity()).setMessage(
+ getActivity().getResources().getString(
+ R.string.dev_settings_use_google_settings))
+ .setPositiveButton(android.R.string.ok, this)
+ .show();
+ }
+ // Use GoogleSettings to set.
+ return false;
+ }
+
private void writeWebViewDataReductionProxyOptions() {
Settings.Secure.putInt(getActivity().getContentResolver(),
Settings.Secure.WEBVIEW_DATA_REDUCTION_PROXY,
@@ -1273,9 +1348,17 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
}
private void updateWebViewDataReductionProxyOptions() {
- updateCheckBox(mWebViewDataReductionProxy, Settings.Secure.getInt(
- getActivity().getContentResolver(),
- Settings.Secure.WEBVIEW_DATA_REDUCTION_PROXY, 0) != 0);
+ int val = -1;
+ try {
+ val = getGoogleSettingValue(WEBVIEW_DATA_REDUCTION_PROXY);
+ } catch (Exception e) {
+ // Accessing GoogleSettings failed. Use the developer setting
+ }
+ if (val == -1) {
+ val = Settings.Secure.getInt(getActivity().getContentResolver(),
+ Settings.Secure.WEBVIEW_DATA_REDUCTION_PROXY, 0);
+ }
+ updateCheckBox(mWebViewDataReductionProxy, val != 0);
}
@Override
@@ -1371,6 +1454,10 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
Settings.Secure.putInt(getActivity().getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION,
mAllowMockLocation.isChecked() ? 1 : 0);
+ } else if (preference == mDebugViewAttributes) {
+ Settings.Global.putInt(getActivity().getContentResolver(),
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES,
+ mDebugViewAttributes.isChecked() ? 1 : 0);
} else if (preference == mDebugAppPref) {
startActivityForResult(new Intent(getActivity(), AppPicker.class), RESULT_DEBUG_APP);
} else if (preference == mWaitForDebugger) {
@@ -1417,6 +1504,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
writeWifiAllowScansWithTrafficOptions();
} else if (preference == mUseNuplayer) {
writeUseNuplayerOptions();
+ } else if (preference == mUSBAudio) {
+ writeUSBAudioOptions();
} else {
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index 0bd548f..ed95500 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -32,7 +32,10 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.Bundle;
@@ -103,6 +106,7 @@ public class DeviceAdminAdd extends Activity {
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
+ PackageManager packageManager = getPackageManager();
if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
@@ -120,6 +124,8 @@ public class DeviceAdminAdd extends Activity {
}
if (action != null && action.equals(DevicePolicyManager.ACTION_SET_PROFILE_OWNER)) {
+ setResult(RESULT_CANCELED);
+ setFinishOnTouchOutside(true);
mAddingProfileOwner = true;
mProfileOwnerName =
getIntent().getStringExtra(DevicePolicyManager.EXTRA_PROFILE_OWNER_NAME);
@@ -129,11 +135,23 @@ public class DeviceAdminAdd extends Activity {
finish();
return;
}
+ try {
+ PackageInfo packageInfo = packageManager.getPackageInfo(callingPackage, 0);
+ if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ Log.e(TAG, "Cannot set a non-system app as a profile owner");
+ finish();
+ return;
+ }
+ } catch (NameNotFoundException nnfe) {
+ Log.e(TAG, "Cannot find the package " + callingPackage);
+ finish();
+ return;
+ }
}
ActivityInfo ai;
try {
- ai = getPackageManager().getReceiverInfo(who, PackageManager.GET_META_DATA);
+ ai = packageManager.getReceiverInfo(who, PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to retrieve device policy " + who, e);
finish();
@@ -144,7 +162,7 @@ public class DeviceAdminAdd extends Activity {
// No need to check this when deactivating, because it is safe to deactivate an active
// invalid device admin.
if (!mDPM.isAdminActive(who)) {
- List<ResolveInfo> avail = getPackageManager().queryBroadcastReceivers(
+ List<ResolveInfo> avail = packageManager.queryBroadcastReceivers(
new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
int count = avail == null ? 0 : avail.size();
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index f85b74e..ddd6728 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -16,6 +16,9 @@
package com.android.settings;
+import com.android.internal.view.RotationPolicy;
+import com.android.settings.notification.DropDownPreference;
+import com.android.settings.notification.DropDownPreference.Callback;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
@@ -26,6 +29,7 @@ import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
@@ -65,6 +69,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
private static final String KEY_LIFT_TO_WAKE = "lift_to_wake";
private static final String KEY_DOZE = "doze";
private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
+ private static final String KEY_AUTO_ROTATE = "auto_rotate";
private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
@@ -81,7 +86,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ContentResolver resolver = getActivity().getContentResolver();
+ final Activity activity = getActivity();
+ final ContentResolver resolver = activity.getContentResolver();
addPreferencesFromResource(R.xml.display_settings);
@@ -111,19 +117,59 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
removePreference(KEY_AUTO_BRIGHTNESS);
}
- if (isLiftToWakeAvailable(getActivity())) {
+ if (isLiftToWakeAvailable(activity)) {
mLiftToWakePreference = (SwitchPreference) findPreference(KEY_LIFT_TO_WAKE);
mLiftToWakePreference.setOnPreferenceChangeListener(this);
} else {
removePreference(KEY_LIFT_TO_WAKE);
}
- if (isDozeAvailable(getActivity())) {
+ if (isDozeAvailable(activity)) {
mDozePreference = (SwitchPreference) findPreference(KEY_DOZE);
mDozePreference.setOnPreferenceChangeListener(this);
} else {
removePreference(KEY_DOZE);
}
+
+ if (RotationPolicy.isRotationLockToggleVisible(activity)) {
+ DropDownPreference rotatePreference =
+ (DropDownPreference) findPreference(KEY_AUTO_ROTATE);
+ rotatePreference.addItem(activity.getString(R.string.display_auto_rotate_rotate),
+ false);
+ int rotateLockedResourceId;
+ // The following block sets the string used when rotation is locked.
+ // If the device locks specifically to portrait or landscape (rather than current
+ // rotation), then we use a different string to include this information.
+ if (allowAllRotations(activity)) {
+ rotateLockedResourceId = R.string.display_auto_rotate_stay_in_current;
+ } else {
+ if (RotationPolicy.getRotationLockOrientation(activity)
+ == Configuration.ORIENTATION_PORTRAIT) {
+ rotateLockedResourceId =
+ R.string.display_auto_rotate_stay_in_portrait;
+ } else {
+ rotateLockedResourceId =
+ R.string.display_auto_rotate_stay_in_landscape;
+ }
+ }
+ rotatePreference.addItem(activity.getString(rotateLockedResourceId), true);
+ rotatePreference.setSelectedItem(RotationPolicy.isRotationLocked(activity) ?
+ 1 : 0);
+ rotatePreference.setCallback(new Callback() {
+ @Override
+ public boolean onItemSelected(int pos, Object value) {
+ RotationPolicy.setRotationLock(activity, (Boolean) value);
+ return true;
+ }
+ });
+ } else {
+ removePreference(KEY_AUTO_ROTATE);
+ }
+ }
+
+ private static boolean allowAllRotations(Context context) {
+ return Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_allowAllRotations);
}
private static boolean isLiftToWakeAvailable(Context context) {
@@ -382,6 +428,9 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
if (!isDozeAvailable(context)) {
result.add(KEY_DOZE);
}
+ if (!RotationPolicy.isRotationLockToggleVisible(context)) {
+ result.add(KEY_AUTO_ROTATE);
+ }
return result;
}
};
diff --git a/src/com/android/settings/HomeSettings.java b/src/com/android/settings/HomeSettings.java
index 845fe1e..2ac93c6 100644
--- a/src/com/android/settings/HomeSettings.java
+++ b/src/com/android/settings/HomeSettings.java
@@ -19,6 +19,7 @@ package com.android.settings;
import java.util.ArrayList;
import java.util.List;
+import android.app.Activity;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -32,18 +33,22 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.content.pm.UserInfo;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.RadioButton;
@@ -55,6 +60,10 @@ import com.android.settings.search.SearchIndexableRaw;
public class HomeSettings extends SettingsPreferenceFragment implements Indexable {
static final String TAG = "HomeSettings";
+ // Boolean extra, indicates only launchers that support managed profiles should be shown.
+ // Note: must match the constant defined in ManagedProvisioning
+ private static final String EXTRA_SUPPORT_MANAGED_PROFILES = "support_managed_profiles";
+
static final int REQUESTING_UNINSTALL = 10;
public static final String HOME_PREFS = "home_prefs";
@@ -114,6 +123,8 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
mPm.replacePreferredActivity(mHomeFilter, IntentFilter.MATCH_CATEGORY_EMPTY,
mHomeComponentSet, newHome.activityName);
+
+ getActivity().setResult(Activity.RESULT_OK);
}
void uninstallApp(HomeAppPreference pref) {
@@ -171,6 +182,10 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
mPrefs = new ArrayList<HomeAppPreference>();
mHomeComponentSet = new ComponentName[homeActivities.size()];
int prefIndex = 0;
+ boolean supportManagedProfilesExtra =
+ getActivity().getIntent().getBooleanExtra(EXTRA_SUPPORT_MANAGED_PROFILES, false);
+ boolean mustSupportManagedProfile = hasManagedProfile()
+ || supportManagedProfilesExtra;
for (int i = 0; i < homeActivities.size(); i++) {
final ResolveInfo candidate = homeActivities.get(i);
final ActivityInfo info = candidate.activityInfo;
@@ -179,11 +194,19 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
try {
Drawable icon = info.loadIcon(mPm);
CharSequence name = info.loadLabel(mPm);
- HomeAppPreference pref = new HomeAppPreference(context, activityName, prefIndex,
- icon, name, this, info);
+ HomeAppPreference pref;
+
+ if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(candidate)) {
+ pref = new HomeAppPreference(context, activityName, prefIndex,
+ icon, name, this, info, false /* not enabled */,
+ getResources().getString(R.string.home_work_profile_not_supported));
+ } else {
+ pref = new HomeAppPreference(context, activityName, prefIndex,
+ icon, name, this, info, true /* enabled */, null);
+ }
+
mPrefs.add(pref);
mPrefGroup.addPreference(pref);
- pref.setEnabled(true);
if (activityName.equals(currentDefaultHome)) {
mCurrentHome = pref;
}
@@ -194,6 +217,10 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
}
if (mCurrentHome != null) {
+ if (mCurrentHome.isEnabled()) {
+ getActivity().setResult(Activity.RESULT_OK);
+ }
+
new Handler().post(new Runnable() {
public void run() {
mCurrentHome.setChecked(true);
@@ -202,6 +229,31 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
}
}
+ private boolean hasManagedProfile() {
+ Context context = getActivity();
+ UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+ List<UserInfo> profiles = userManager.getProfiles(context.getUserId());
+ for (UserInfo userInfo : profiles) {
+ if (userInfo.isManagedProfile()) return true;
+ }
+ return false;
+ }
+
+ private boolean launcherHasManagedProfilesFeature(ResolveInfo resolveInfo) {
+ try {
+ ApplicationInfo appInfo = getPackageManager().getApplicationInfo(
+ resolveInfo.activityInfo.packageName, 0 /* default flags */);
+ return versionNumberAtLeastL(appInfo.targetSdkVersion);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private boolean versionNumberAtLeastL(int versionNumber) {
+ // TODO: remove "|| true" once the build code for L is fixed.
+ return versionNumber >= Build.VERSION_CODES.L || true;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -245,12 +297,14 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
String uninstallTarget;
public HomeAppPreference(Context context, ComponentName activity,
- int i, Drawable icon, CharSequence title,
- HomeSettings parent, ActivityInfo info) {
+ int i, Drawable icon, CharSequence title, HomeSettings parent, ActivityInfo info,
+ boolean enabled, CharSequence summary) {
super(context);
setLayoutResource(R.layout.preference_home_app);
setIcon(icon);
setTitle(title);
+ setEnabled(enabled);
+ setSummary(summary);
activityName = activity;
fragment = parent;
index = i;
@@ -305,13 +359,15 @@ public class HomeSettings extends SettingsPreferenceFragment implements Indexabl
icon.setEnabled(false);
icon.setColorFilter(grayscaleFilter);
} else {
+ icon.setEnabled(true);
icon.setOnClickListener(mDeleteClickListener);
icon.setTag(indexObj);
}
View v = view.findViewById(R.id.home_app_pref);
- v.setOnClickListener(mHomeClickListener);
v.setTag(indexObj);
+
+ v.setOnClickListener(mHomeClickListener);
}
void setChecked(boolean state) {
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
index 6600703..c6158b1 100644
--- a/src/com/android/settings/LocalePicker.java
+++ b/src/com/android/settings/LocalePicker.java
@@ -48,15 +48,6 @@ public class LocalePicker extends com.android.internal.app.LocalePicker
}
@Override
- protected boolean isInDeveloperMode() {
- final boolean showDev = getActivity().getSharedPreferences(DevelopmentSettings.PREF_FILE,
- Context.MODE_PRIVATE).getBoolean(
- DevelopmentSettings.PREF_SHOW,
- android.os.Build.TYPE.equals("eng"));
- return showDev;
- }
-
- @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_TARGET_LOCALE)) {
diff --git a/src/com/android/settings/ManagedProfileSetup.java b/src/com/android/settings/ManagedProfileSetup.java
index 1b3c838..198abe0 100644
--- a/src/com/android/settings/ManagedProfileSetup.java
+++ b/src/com/android/settings/ManagedProfileSetup.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.util.Log;
import android.os.UserHandle;
import android.os.UserManager;
@@ -37,6 +38,7 @@ import static android.content.pm.PackageManager.GET_RESOLVED_FILTER;
* adds cross-profile intent filters for the appropriate Settings activities).
*/
public class ManagedProfileSetup extends BroadcastReceiver {
+ private static final String TAG = "Settings";
private static final String PRIMARY_PROFILE_SETTING =
"com.android.settings.PRIMARY_PROFILE_CONTROLLED";
@@ -46,7 +48,8 @@ public class ManagedProfileSetup extends BroadcastReceiver {
if (!Utils.isManagedProfile(um)) {
return;
}
-
+ Log.i(TAG, "Received broadcast: " + broadcast.getAction()
+ + ". Setting up intent forwarding for managed profile.");
final PackageManager pm = context.getPackageManager();
// Clear any previous intent forwarding we set up
pm.clearCrossProfileIntentFilters(UserHandle.myUserId());
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index 2ba1e7f..0455d74 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -16,22 +16,21 @@
package com.android.settings;
+import android.app.ProgressDialog;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.os.AsyncTask;
import android.service.persistentdata.PersistentDataBlockManager;
import com.android.internal.os.storage.ExternalStorageFormatter;
-import com.android.internal.widget.LockPatternUtils;
-import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.CheckBox;
/**
* Confirm and execute a reset of the device to a clean "just out of the box"
@@ -47,7 +46,6 @@ public class MasterClearConfirm extends Fragment {
private View mContentView;
private boolean mEraseSdCard;
- private Button mFinalButton;
/**
* The user has gone through the multiple confirmation, so now we go ahead
@@ -61,30 +59,68 @@ public class MasterClearConfirm extends Fragment {
return;
}
- PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
+ final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
if (pdbManager != null) {
- pdbManager.wipe();
- }
+ // if OEM unlock is enabled, this will be wiped during FR process.
+ if (!pdbManager.getOemUnlockEnabled()) {
+ final ProgressDialog progressDialog = getProgressDialog();
+ progressDialog.show();
+
+ // need to prevent orientation changes as we're about to go into
+ // a long IO request, so we won't be able to access inflate resources on flash
+ final int oldOrientation = getActivity().getRequestedOrientation();
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ pdbManager.wipe();
+ return null;
+ }
- if (mEraseSdCard) {
- Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
- intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
- getActivity().startService(intent);
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ progressDialog.hide();
+ getActivity().setRequestedOrientation(oldOrientation);
+ doMasterClear();
+ }
+ }.execute();
+ }
} else {
- getActivity().sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
- // Intent handling is asynchronous -- assume it will happen soon.
+ doMasterClear();
}
}
+
+ private ProgressDialog getProgressDialog() {
+ final ProgressDialog progressDialog = new ProgressDialog(getActivity());
+ progressDialog.setIndeterminate(true);
+ progressDialog.setCancelable(false);
+ progressDialog.setTitle(
+ getActivity().getString(R.string.master_clear_progress_title));
+ progressDialog.setMessage(
+ getActivity().getString(R.string.master_clear_progress_text));
+ return progressDialog;
+ }
};
+ private void doMasterClear() {
+ if (mEraseSdCard) {
+ Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
+ intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
+ getActivity().startService(intent);
+ } else {
+ getActivity().sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
+ // Intent handling is asynchronous -- assume it will happen soon.
+ }
+ }
+
/**
* Configure the UI for the final confirmation interaction
*/
private void establishFinalConfirmationState() {
- mFinalButton = (Button) mContentView.findViewById(R.id.execute_master_clear);
- mFinalButton.setOnClickListener(mFinalClickListener);
+ mContentView.findViewById(R.id.execute_master_clear)
+ .setOnClickListener(mFinalClickListener);
}
@Override
@@ -104,6 +140,6 @@ public class MasterClearConfirm extends Fragment {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
- mEraseSdCard = args != null ? args.getBoolean(MasterClear.ERASE_EXTERNAL_EXTRA) : false;
+ mEraseSdCard = args != null && args.getBoolean(MasterClear.ERASE_EXTERNAL_EXTRA);
}
}
diff --git a/src/com/android/settings/PrivacySettings.java b/src/com/android/settings/PrivacySettings.java
index aac7638..1236c48 100644
--- a/src/com/android/settings/PrivacySettings.java
+++ b/src/com/android/settings/PrivacySettings.java
@@ -27,9 +27,10 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserManager;
-import android.preference.CheckBoxPreference;
import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
import android.provider.Settings;
/**
@@ -46,8 +47,8 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
private static final String CONFIGURE_ACCOUNT = "configure_account";
private static final String PERSONAL_DATA_CATEGORY = "personal_data_category";
private IBackupManager mBackupManager;
- private CheckBoxPreference mBackup;
- private CheckBoxPreference mAutoRestore;
+ private SwitchPreference mBackup;
+ private SwitchPreference mAutoRestore;
private Dialog mConfirmDialog;
private PreferenceScreen mConfigure;
@@ -63,8 +64,12 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
mBackupManager = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
- mBackup = (CheckBoxPreference) screen.findPreference(BACKUP_DATA);
- mAutoRestore = (CheckBoxPreference) screen.findPreference(AUTO_RESTORE);
+ mBackup = (SwitchPreference) screen.findPreference(BACKUP_DATA);
+ mBackup.setOnPreferenceChangeListener(preferenceChangeListener);
+
+ mAutoRestore = (SwitchPreference) screen.findPreference(AUTO_RESTORE);
+ mAutoRestore.setOnPreferenceChangeListener(preferenceChangeListener);
+
mConfigure = (PreferenceScreen) screen.findPreference(CONFIGURE_ACCOUNT);
if (UserManager.get(getActivity()).hasUserRestriction(
@@ -98,29 +103,36 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
super.onStop();
}
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
- Preference preference) {
- if (preference == mBackup) {
- if (!mBackup.isChecked()) {
- showEraseBackupDialog();
- } else {
- setBackupEnabled(true);
+ private OnPreferenceChangeListener preferenceChangeListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (!(preference instanceof SwitchPreference)) {
+ return true;
}
- } else if (preference == mAutoRestore) {
- boolean curState = mAutoRestore.isChecked();
- try {
- mBackupManager.setAutoRestore(curState);
- } catch (RemoteException e) {
- mAutoRestore.setChecked(!curState);
+ boolean nextValue = (Boolean) newValue;
+ boolean result = false;
+ if (preference == mBackup) {
+ if (nextValue == false) {
+ // Don't change Switch status until user makes choice in dialog
+ // so return false here.
+ showEraseBackupDialog();
+ } else {
+ setBackupEnabled(true);
+ result = true;
+ }
+ } else if (preference == mAutoRestore) {
+ try {
+ mBackupManager.setAutoRestore(nextValue);
+ result = true;
+ } catch (RemoteException e) {
+ mAutoRestore.setChecked(!nextValue);
+ }
}
+ return result;
}
- return super.onPreferenceTreeClick(preferenceScreen, preference);
- }
+ };
private void showEraseBackupDialog() {
- mBackup.setChecked(true);
-
mDialogType = DIALOG_ERASE_BACKUP;
CharSequence msg = getResources().getText(R.string.backup_erase_dialog_message);
// TODO: DialogFragment?
@@ -159,7 +171,7 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
mConfigure.setEnabled(configureEnabled);
mConfigure.setIntent(configIntent);
setConfigureSummary(configSummary);
-}
+ }
private void setConfigureSummary(String summary) {
if (summary != null) {
@@ -179,13 +191,20 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
}
}
+ @Override
public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- //updateProviders();
- if (mDialogType == DIALOG_ERASE_BACKUP) {
+ // Dialog is triggered before Switch status change, that means marking the Switch to
+ // true in showEraseBackupDialog() method will be override by following status change.
+ // So we do manual switching here due to users' response.
+ if (mDialogType == DIALOG_ERASE_BACKUP) {
+ // Accept turning off backup
+ if (which == DialogInterface.BUTTON_POSITIVE) {
setBackupEnabled(false);
- updateConfigureSummary();
+ } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+ // Reject turning off backup
+ setBackupEnabled(true);
}
+ updateConfigureSummary();
}
mDialogType = 0;
}
@@ -214,4 +233,4 @@ public class PrivacySettings extends SettingsPreferenceFragment implements
protected int getHelpResource() {
return R.string.help_url_backup_reset;
}
-}
+} \ No newline at end of file
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 75de222..b0a4a53 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -303,9 +303,6 @@ public class RadioInfo extends Activity {
imsRegRequiredButton = (Button) findViewById(R.id.ims_reg_required);
imsRegRequiredButton.setOnClickListener(mImsRegRequiredHandler);
- moOverVolteButton = (Button) findViewById(R.id.mo_over_volte);
- moOverVolteButton.setOnClickListener(mMoOverVolteHandler);
-
smsOverImsButton = (Button) findViewById(R.id.sms_over_ims);
smsOverImsButton.setOnClickListener(mSmsOverImsHandler);
@@ -363,7 +360,6 @@ public class RadioInfo extends Activity {
updatePowerState();
updateCellInfoListRate();
updateImsRegRequiredState();
- updateMoOverImsState();
updateSmsOverImsState();
updateLteRamDumpState();
updateProperties();
@@ -989,35 +985,6 @@ public class RadioInfo extends Activity {
imsRegRequiredButton.setText(buttonText);
}
- private Button moOverVolteButton;
- OnClickListener mMoOverVolteHandler = new OnClickListener() {
- @Override
- public void onClick(View v) {
- boolean moOverVolteEnabled = isMoOverVolteEnabled();
- log(String.format("toggle %s: currently %s",
- TelephonyProperties.PROPERTY_DBG_IMS_VOLTE_ENABLE,
- (moOverVolteEnabled ? "on" : "off")));
- boolean newValue = !moOverVolteEnabled;
- SystemProperties.set(TelephonyProperties.PROPERTY_DBG_IMS_VOLTE_ENABLE,
- newValue ? "1" : "0");
- updateMoOverImsState();
- }
- };
-
- private boolean isMoOverVolteEnabled() {
- return SystemProperties.getInt(TelephonyProperties.PROPERTY_DBG_IMS_VOLTE_ENABLE,
- TelephonyProperties.PROPERTY_DBG_IMS_VOLTE_ENABLE_DEAFULT) == 1;
- }
-
- private void updateMoOverImsState() {
- boolean moOverVolteEnabled = isMoOverVolteEnabled();
- log("updateMoOverImsState isMoOverVolteEnabled()=" + moOverVolteEnabled);
- String buttonText = moOverVolteEnabled ?
- getString(R.string.mo_over_volte_off) :
- getString(R.string.mo_over_volte_on);
- moOverVolteButton.setText(buttonText);
- }
-
private Button smsOverImsButton;
static final String PROPERTY_SMS_OVER_IMS = "persist.radio.imsallowmtsms";
OnClickListener mSmsOverImsHandler = new OnClickListener() {
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index e5f7736..7798937 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -31,7 +31,7 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.preference.CheckBoxPreference;
+import android.preference.SwitchPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
@@ -47,7 +47,9 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo;
import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Index;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
@@ -76,6 +78,8 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
+ private static final String KEY_ADVANCED_SECURITY = "advanced_security";
+ private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124;
@@ -95,23 +99,31 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_TRUST_AGENT = "trust_agent";
private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
+ // These switch preferences need special handling since they're not all stored in Settings.
+ private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
+ KEY_LOCK_ENABLED, KEY_VISIBLE_PATTERN, KEY_BIOMETRIC_WEAK_LIVELINESS,
+ KEY_POWER_INSTANTLY_LOCKS, KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS };
+
+ // Only allow one trust agent on the platform.
+ private static final boolean ONLY_ONE_TRUST_AGENT = true;
+
private DevicePolicyManager mDPM;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
private ListPreference mLockAfter;
- private CheckBoxPreference mBiometricWeakLiveliness;
- private CheckBoxPreference mVisiblePattern;
+ private SwitchPreference mBiometricWeakLiveliness;
+ private SwitchPreference mVisiblePattern;
- private CheckBoxPreference mShowPassword;
+ private SwitchPreference mShowPassword;
private KeyStore mKeyStore;
private Preference mResetCredentials;
- private CheckBoxPreference mToggleAppInstallation;
+ private SwitchPreference mToggleAppInstallation;
private DialogInterface mWarnInstallApps;
- private CheckBoxPreference mPowerButtonInstantlyLocks;
+ private SwitchPreference mPowerButtonInstantlyLocks;
private boolean mIsPrimary;
@@ -214,33 +226,26 @@ public class SecuritySettings extends SettingsPreferenceFragment
PreferenceGroup securityCategory = (PreferenceGroup)
root.findPreference(KEY_SECURITY_CATEGORY);
if (securityCategory != null) {
- PackageManager pm = getPackageManager();
- List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
- PackageManager.GET_META_DATA);
- List<ComponentName> enabledTrustAgents = mLockPatternUtils.getEnabledTrustAgents();
- if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
- for (ResolveInfo resolveInfo : resolveInfos) {
- if (resolveInfo.serviceInfo == null) continue;
- if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
- TrustAgentUtils.TrustAgentComponentInfo trustAgentComponentInfo =
- TrustAgentUtils.getSettingsComponent(pm, resolveInfo);
- if (trustAgentComponentInfo.componentName == null ||
- !enabledTrustAgents.contains(
- TrustAgentUtils.getComponentName(resolveInfo)) ||
- TextUtils.isEmpty(trustAgentComponentInfo.title)) continue;
- Preference trustAgentPreference =
- new Preference(securityCategory.getContext());
- trustAgentPreference.setKey(KEY_TRUST_AGENT);
- trustAgentPreference.setTitle(trustAgentComponentInfo.title);
- trustAgentPreference.setSummary(trustAgentComponentInfo.summary);
- // Create intent for this preference.
- Intent intent = new Intent();
- intent.setComponent(trustAgentComponentInfo.componentName);
- intent.setAction(Intent.ACTION_MAIN);
- trustAgentPreference.setIntent(intent);
- // Add preference to the settings menu.
- securityCategory.addPreference(trustAgentPreference);
- break; // Only render the first one.
+ final boolean hasSecurity = mLockPatternUtils.isSecure();
+ ArrayList<TrustAgentComponentInfo> agents =
+ getActiveTrustAgents(getPackageManager(), mLockPatternUtils);
+ for (int i = 0; i < agents.size(); i++) {
+ final TrustAgentComponentInfo agent = agents.get(i);
+ Preference trustAgentPreference =
+ new Preference(securityCategory.getContext());
+ trustAgentPreference.setKey(KEY_TRUST_AGENT);
+ trustAgentPreference.setTitle(agent.title);
+ trustAgentPreference.setSummary(agent.summary);
+ // Create intent for this preference.
+ Intent intent = new Intent();
+ intent.setComponent(agent.componentName);
+ intent.setAction(Intent.ACTION_MAIN);
+ trustAgentPreference.setIntent(intent);
+ // Add preference to the settings menu.
+ securityCategory.addPreference(trustAgentPreference);
+ if (!hasSecurity) {
+ trustAgentPreference.setEnabled(false);
+ trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
}
}
}
@@ -254,13 +259,13 @@ public class SecuritySettings extends SettingsPreferenceFragment
// biometric weak liveliness
mBiometricWeakLiveliness =
- (CheckBoxPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
+ (SwitchPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
// visible pattern
- mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN);
+ mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN);
// lock instantly on power key press
- mPowerButtonInstantlyLocks = (CheckBoxPreference) root.findPreference(
+ mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference(
KEY_POWER_INSTANTLY_LOCKS);
Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT);
if (mPowerButtonInstantlyLocks != null &&
@@ -296,18 +301,14 @@ public class SecuritySettings extends SettingsPreferenceFragment
root.findPreference(KEY_SIM_LOCK).setEnabled(false);
}
}
- try {
- if (Settings.System.getInt(getContentResolver(), Settings.System.LOCK_TO_APP_ENABLED)
- != 0) {
- root.findPreference(KEY_SCREEN_PINNING).setSummary(
- getResources().getString(R.string.switch_on_text));
- }
- } catch (SettingNotFoundException e) {
- Log.w(TAG, "No Lock-to-app enabled setting", e);
+ if (Settings.System.getInt(getContentResolver(),
+ Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) {
+ root.findPreference(KEY_SCREEN_PINNING).setSummary(
+ getResources().getString(R.string.switch_on_text));
}
// Show password
- mShowPassword = (CheckBoxPreference) root.findPreference(KEY_SHOW_PASSWORD);
+ mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD);
mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
// Credential storage
@@ -331,7 +332,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
// Application install
PreferenceGroup deviceAdminCategory = (PreferenceGroup)
root.findPreference(KEY_DEVICE_ADMIN_CATEGORY);
- mToggleAppInstallation = (CheckBoxPreference) findPreference(
+ mToggleAppInstallation = (SwitchPreference) findPreference(
KEY_TOGGLE_INSTALL_APPLICATIONS);
mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
// Side loading of apps.
@@ -341,9 +342,54 @@ public class SecuritySettings extends SettingsPreferenceFragment
mToggleAppInstallation.setEnabled(false);
}
+ // Advanced Security features
+ PreferenceGroup advancedCategory =
+ (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY);
+ if (advancedCategory != null) {
+ Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS);
+ if (manageAgents != null && !mLockPatternUtils.isSecure()) {
+ manageAgents.setEnabled(false);
+ manageAgents.setSummary(R.string.disabled_because_no_backup_security);
+ }
+ }
+
+ // The above preferences come and go based on security state, so we need to update
+ // the index. This call is expected to be fairly cheap, but we may want to do something
+ // smarter in the future.
+ Index.getInstance(getActivity())
+ .updateFromClassNameResource(SecuritySettings.class.getName(), true, true);
+
+ for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
+ final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
+ if (pref != null) pref.setOnPreferenceChangeListener(this);
+ }
return root;
}
+ private static ArrayList<TrustAgentComponentInfo> getActiveTrustAgents(
+ PackageManager pm, LockPatternUtils utils) {
+ ArrayList<TrustAgentComponentInfo> result = new ArrayList<TrustAgentComponentInfo>();
+ List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA);
+ List<ComponentName> enabledTrustAgents = utils.getEnabledTrustAgents();
+ if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
+ for (int i = 0; i < resolveInfos.size(); i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ if (resolveInfo.serviceInfo == null) continue;
+ if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
+ TrustAgentComponentInfo trustAgentComponentInfo =
+ TrustAgentUtils.getSettingsComponent(pm, resolveInfo);
+ if (trustAgentComponentInfo.componentName == null ||
+ !enabledTrustAgents.contains(
+ TrustAgentUtils.getComponentName(resolveInfo)) ||
+ TextUtils.isEmpty(trustAgentComponentInfo.title)) continue;
+ result.add(trustAgentComponentInfo);
+ if (ONLY_ONE_TRUST_AGENT) break;
+ }
+ }
+ return result;
+ }
+
private boolean isNonMarketAppsAllowed() {
return Settings.Global.getInt(getContentResolver(),
Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
@@ -366,16 +412,17 @@ public class SecuritySettings extends SettingsPreferenceFragment
.setIcon(com.android.internal.R.drawable.ic_dialog_alert)
.setMessage(getResources().getString(R.string.install_all_warning))
.setPositiveButton(android.R.string.yes, this)
- .setNegativeButton(android.R.string.no, null)
+ .setNegativeButton(android.R.string.no, this)
.show();
}
@Override
public void onClick(DialogInterface dialog, int which) {
- if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) {
- setNonMarketAppsAllowed(true);
+ if (dialog == mWarnInstallApps) {
+ boolean turnOn = which == DialogInterface.BUTTON_POSITIVE;
+ setNonMarketAppsAllowed(turnOn);
if (mToggleAppInstallation != null) {
- mToggleAppInstallation.setChecked(true);
+ mToggleAppInstallation.setChecked(turnOn);
}
}
}
@@ -490,8 +537,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
final String key = preference.getKey();
-
- final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
@@ -506,42 +551,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
// can't be reached, but is here in case things change in the future
startBiometricWeakImprove();
}
- } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) {
- if (isToggled(preference)) {
- lockPatternUtils.setBiometricWeakLivelinessEnabled(true);
- } else {
- // In this case the user has just unchecked the checkbox, but this action requires
- // them to confirm their password. We need to re-check the checkbox until
- // they've confirmed their password
- mBiometricWeakLiveliness.setChecked(true);
- ChooseLockSettingsHelper helper =
- new ChooseLockSettingsHelper(this.getActivity(), this);
- if (!helper.launchConfirmationActivity(
- CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
- // If this returns false, it means no password confirmation is required, so
- // go ahead and uncheck it here.
- // Note: currently a backup is required for biometric_weak so this code path
- // can't be reached, but is here in case things change in the future
- lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
- mBiometricWeakLiveliness.setChecked(false);
- }
- }
- } else if (KEY_LOCK_ENABLED.equals(key)) {
- lockPatternUtils.setLockPatternEnabled(isToggled(preference));
- } else if (KEY_VISIBLE_PATTERN.equals(key)) {
- lockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
- } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
- lockPatternUtils.setPowerButtonInstantlyLocks(isToggled(preference));
- } else if (preference == mShowPassword) {
- Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
- mShowPassword.isChecked() ? 1 : 0);
- } else if (preference == mToggleAppInstallation) {
- if (mToggleAppInstallation.isChecked()) {
- mToggleAppInstallation.setChecked(false);
- warnAppInstallation();
- } else {
- setNonMarketAppsAllowed(false);
- }
} else if (KEY_TRUST_AGENT.equals(key)) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
@@ -556,14 +565,9 @@ public class SecuritySettings extends SettingsPreferenceFragment
// If we didn't handle it, let preferences handle it.
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
-
return true;
}
- private boolean isToggled(Preference pref) {
- return ((CheckBoxPreference) pref).isChecked();
- }
-
/**
* see confirmPatternThenDisableAndClear
*/
@@ -596,7 +600,10 @@ public class SecuritySettings extends SettingsPreferenceFragment
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
- if (preference == mLockAfter) {
+ boolean result = true;
+ final String key = preference.getKey();
+ final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+ if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
int timeout = Integer.parseInt((String) value);
try {
Settings.Secure.putInt(getContentResolver(),
@@ -605,8 +612,46 @@ public class SecuritySettings extends SettingsPreferenceFragment
Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
}
updateLockAfterPreferenceSummary();
+ } else if (KEY_LOCK_ENABLED.equals(key)) {
+ lockPatternUtils.setLockPatternEnabled((Boolean) value);
+ } else if (KEY_VISIBLE_PATTERN.equals(key)) {
+ lockPatternUtils.setVisiblePatternEnabled((Boolean) value);
+ } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) {
+ if ((Boolean) value) {
+ lockPatternUtils.setBiometricWeakLivelinessEnabled(true);
+ } else {
+ // In this case the user has just unchecked the checkbox, but this action requires
+ // them to confirm their password. We need to re-check the checkbox until
+ // they've confirmed their password
+ mBiometricWeakLiveliness.setChecked(true);
+ ChooseLockSettingsHelper helper =
+ new ChooseLockSettingsHelper(this.getActivity(), this);
+ if (!helper.launchConfirmationActivity(
+ CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
+ // If this returns false, it means no password confirmation is required, so
+ // go ahead and uncheck it here.
+ // Note: currently a backup is required for biometric_weak so this code path
+ // can't be reached, but is here in case things change in the future
+ lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
+ mBiometricWeakLiveliness.setChecked(false);
+ }
+ }
+ } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
+ mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value);
+ } else if (KEY_SHOW_PASSWORD.equals(key)) {
+ Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
+ ((Boolean) value) ? 1 : 0);
+ } else if (KEY_TOGGLE_INSTALL_APPLICATIONS.equals(key)) {
+ if ((Boolean) value) {
+ mToggleAppInstallation.setChecked(false);
+ warnAppInstallation();
+ // Don't change Switch status until user makes choice in dialog, so return false.
+ result = false;
+ } else {
+ setNonMarketAppsAllowed(false);
+ }
}
- return true;
+ return result;
}
@Override
@@ -626,7 +671,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new SecuritySearchIndexProvider();
- static private class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
+ private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
boolean mIsPrimary;
@@ -716,6 +761,19 @@ public class SecuritySettings extends SettingsPreferenceFragment
result.add(data);
}
+ // Advanced
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+ if (lockPatternUtils.isSecure()) {
+ ArrayList<TrustAgentComponentInfo> agents =
+ getActiveTrustAgents(context.getPackageManager(), lockPatternUtils);
+ for (int i = 0; i < agents.size(); i++) {
+ final TrustAgentComponentInfo agent = agents.get(i);
+ data = new SearchIndexableRaw(context);
+ data.title = agent.title;
+ data.screenTitle = screenTitle;
+ result.add(data);
+ }
+ }
return result;
}
@@ -745,6 +803,12 @@ public class SecuritySettings extends SettingsPreferenceFragment
keys.add(KEY_CREDENTIALS_MANAGER);
}
+ // TrustAgent settings disappear when the user has no primary security.
+ if (!lockPatternUtils.isSecure()) {
+ keys.add(KEY_TRUST_AGENT);
+ keys.add(KEY_MANAGE_TRUST_AGENTS);
+ }
+
return keys;
}
}
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 123d4fe..84bf615 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -38,6 +38,7 @@ public class Settings extends SettingsActivity {
public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ }
public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }
public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ }
+ public static class VoiceInputSettingsActivity extends SettingsActivity { /* empty */ }
public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ }
public static class LocalePickerActivity extends SettingsActivity { /* empty */ }
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
@@ -63,6 +64,7 @@ public class Settings extends SettingsActivity {
public static class AccessibilityContrastSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccessibilityDaltonizerSettingsActivity extends SettingsActivity { /* empty */ }
public static class SecuritySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class UsageAccessSettingsActivity extends SettingsActivity { /* empty */ }
public static class LocationSettingsActivity extends SettingsActivity { /* empty */ }
public static class PrivacySettingsActivity extends SettingsActivity { /* empty */ }
public static class RunningServicesActivity extends SettingsActivity { /* empty */ }
@@ -98,5 +100,6 @@ public class Settings extends SettingsActivity {
public static class QuickLaunchSettingsActivity extends SettingsActivity { /* empty */ }
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
+ public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index bb5ac00..c566f6c 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -72,7 +72,6 @@ import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageApplications;
import com.android.settings.applications.ProcessStatsUi;
import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.bluetooth.MessageAccessSettings;
import com.android.settings.dashboard.DashboardCategory;
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.dashboard.DashboardTile;
@@ -105,6 +104,7 @@ import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.sim.SimSettings;
import com.android.settings.tts.TextToSpeechSettings;
import com.android.settings.users.UserSettings;
+import com.android.settings.voice.VoiceInputSettings;
import com.android.settings.vpn2.VpnSettings;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
@@ -184,8 +184,13 @@ public class SettingsActivity extends Activity
* that fragment.
*/
public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
- public static final String EXTRA_SHOW_FRAGMENT_TITLE_RESID = ":settings:show_fragment_title_resid";
- public static final String EXTRA_SHOW_FRAGMENT_AS_SHORTCUT = ":settings:show_fragment_as_shortcut";
+ public static final String EXTRA_SHOW_FRAGMENT_TITLE_RESID =
+ ":settings:show_fragment_title_resid";
+ public static final String EXTRA_SHOW_FRAGMENT_AS_SHORTCUT =
+ ":settings:show_fragment_as_shortcut";
+
+ public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
+ ":settings:show_fragment_as_subsetting";
private static final String META_DATA_KEY_FRAGMENT_CLASS =
"com.android.settings.FRAGMENT_CLASS";
@@ -237,7 +242,6 @@ public class SettingsActivity extends Activity
AdvancedWifiSettings.class.getName(),
SavedAccessPointsWifiSettings.class.getName(),
BluetoothSettings.class.getName(),
- MessageAccessSettings.class.getName(),
SimSettings.class.getName(),
TetherSettings.class.getName(),
WifiP2pSettings.class.getName(),
@@ -245,6 +249,7 @@ public class SettingsActivity extends Activity
DateTimeSettings.class.getName(),
LocalePicker.class.getName(),
InputMethodAndLanguageSettings.class.getName(),
+ VoiceInputSettings.class.getName(),
SpellCheckersSettings.class.getName(),
UserDictionaryList.class.getName(),
UserDictionarySettings.class.getName(),
@@ -256,6 +261,7 @@ public class SettingsActivity extends Activity
NotificationStation.class.getName(),
LocationSettings.class.getName(),
SecuritySettings.class.getName(),
+ UsageAccessSettings.class.getName(),
PrivacySettings.class.getName(),
DeviceAdminSettings.class.getName(),
AccessibilitySettings.class.getName(),
@@ -290,7 +296,8 @@ public class SettingsActivity extends Activity
NotificationAppList.class.getName(),
AppNotificationSettings.class.getName(),
OtherSoundSettings.class.getName(),
- QuickLaunchSettings.class.getName()
+ QuickLaunchSettings.class.getName(),
+ ApnSettings.class.getName()
};
@@ -495,12 +502,15 @@ public class SettingsActivity extends Activity
final String className = cn.getClassName();
mIsShowingDashboard = className.equals(Settings.class.getName());
- final boolean isSubSettings = className.equals(SubSettings.class.getName());
- // If this is a sub settings or not the main Dashboard and not a Shortcut and an initial
- // Fragment then apply the SubSettings theme for the ActionBar content insets
- if (isSubSettings ||
- (!mIsShowingDashboard && !mIsShortcut && (initialFragmentName != null))) {
+ // This is a "Sub Settings" when:
+ // - this is a real SubSettings
+ // - or :settings:show_fragment_as_subsetting is passed to the Intent
+ final boolean isSubSettings = className.equals(SubSettings.class.getName()) ||
+ intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
+
+ // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content insets
+ if (isSubSettings) {
// Check also that we are not a Theme Dialog as we don't want to override them
final int themeResId = getThemeResId();
if (themeResId != R.style.Theme_DialogWhenLarge &&
@@ -550,6 +560,9 @@ public class SettingsActivity extends Activity
} else if (isSubSettings) {
mDisplayHomeAsUpEnabled = true;
mDisplaySearch = true;
+ } else {
+ mDisplayHomeAsUpEnabled = false;
+ mDisplaySearch = false;
}
setTitleFromIntent(intent);
@@ -1042,7 +1055,7 @@ public class SettingsActivity extends Activity
}
// Show the SIM Cards setting if there are more than 2 SIMs installed.
- if(tile.id != R.id.sim_settings || SimSettings.showSimCardScreen(this)){
+ if(tile.id != R.id.sim_settings || Utils.showSimCardTile(this)){
category.addTile(tile);
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index f89b72e..83b3a68 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -66,7 +66,7 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
private boolean mPreferenceHighlighted = false;
private Drawable mHighlightDrawable;
- private Object mRegisterLock = new Object();
+ private ListAdapter mCurrentRootAdapter;
private boolean mIsDataSetObserverRegistered = false;
private DataSetObserver mDataSetObserver = new DataSetObserver() {
@Override
@@ -147,6 +147,11 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
}
@Override
+ protected void onUnbindPreferences() {
+ unregisterObserverIfNeeded();
+ }
+
+ @Override
public void onStop() {
super.onStop();
@@ -154,20 +159,23 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
}
public void registerObserverIfNeeded() {
- synchronized (mRegisterLock) {
- if (!mIsDataSetObserverRegistered) {
- getPreferenceScreen().getRootAdapter().registerDataSetObserver(mDataSetObserver);
- mIsDataSetObserverRegistered = true;
+ if (!mIsDataSetObserverRegistered) {
+ if (mCurrentRootAdapter != null) {
+ mCurrentRootAdapter.unregisterDataSetObserver(mDataSetObserver);
}
+ mCurrentRootAdapter = getPreferenceScreen().getRootAdapter();
+ mCurrentRootAdapter.registerDataSetObserver(mDataSetObserver);
+ mIsDataSetObserverRegistered = true;
}
}
public void unregisterObserverIfNeeded() {
- synchronized (mRegisterLock) {
- if (mIsDataSetObserverRegistered) {
- getPreferenceScreen().getRootAdapter().unregisterDataSetObserver(mDataSetObserver);
- mIsDataSetObserverRegistered = false;
+ if (mIsDataSetObserverRegistered) {
+ if (mCurrentRootAdapter != null) {
+ mCurrentRootAdapter.unregisterDataSetObserver(mDataSetObserver);
+ mCurrentRootAdapter = null;
}
+ mIsDataSetObserverRegistered = false;
}
}
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index d960ce6..8069d52 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -40,9 +40,9 @@ import android.os.Environment;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
-import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
import android.text.TextUtils;
import android.view.ViewGroup;
import android.view.ViewParent;
@@ -68,12 +68,12 @@ public class TetherSettings extends SettingsPreferenceFragment
private static final int DIALOG_AP_SETTINGS = 1;
private WebView mView;
- private CheckBoxPreference mUsbTether;
+ private SwitchPreference mUsbTether;
private WifiApEnabler mWifiApEnabler;
- private CheckBoxPreference mEnableWifiAp;
+ private SwitchPreference mEnableWifiAp;
- private CheckBoxPreference mBluetoothTether;
+ private SwitchPreference mBluetoothTether;
private BroadcastReceiver mTetherChangeReceiver;
@@ -135,10 +135,10 @@ public class TetherSettings extends SettingsPreferenceFragment
}
mEnableWifiAp =
- (CheckBoxPreference) findPreference(ENABLE_WIFI_AP);
+ (SwitchPreference) findPreference(ENABLE_WIFI_AP);
Preference wifiApSettings = findPreference(WIFI_AP_SSID_AND_SECURITY);
- mUsbTether = (CheckBoxPreference) findPreference(USB_TETHER_SETTINGS);
- mBluetoothTether = (CheckBoxPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
+ mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS);
+ mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -484,7 +484,7 @@ public class TetherSettings extends SettingsPreferenceFragment
if (resultCode == Activity.RESULT_OK) {
startTethering();
} else {
- //BT and USB need checkbox turned off on failure
+ //BT and USB need switch turned off on failure
//Wifi tethering is never turned on until afterwards
switch (mTetherChoice) {
case BLUETOOTH_TETHERING:
diff --git a/src/com/android/settings/TrustAgentSettings.java b/src/com/android/settings/TrustAgentSettings.java
new file mode 100644
index 0000000..54fef36
--- /dev/null
+++ b/src/com/android/settings/TrustAgentSettings.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import java.util.List;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.preference.SwitchPreference;
+import android.service.trust.TrustAgentService;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public class TrustAgentSettings extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener {
+ private static final String SERVICE_INTERFACE = TrustAgentService.SERVICE_INTERFACE;
+ private ArrayMap<ComponentName, AgentInfo> mAvailableAgents;
+ private final ArraySet<ComponentName> mActiveAgents = new ArraySet<ComponentName>();
+ private LockPatternUtils mLockPatternUtils;
+
+ public static final class AgentInfo {
+ CharSequence label;
+ ComponentName component; // service that implements ITrustAgent
+ SwitchPreference preference;
+ public Drawable icon;
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof AgentInfo) {
+ return component.equals(((AgentInfo)other).component);
+ }
+ return true;
+ }
+
+ public int compareTo(AgentInfo other) {
+ return component.compareTo(other.component);
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ addPreferencesFromResource(R.xml.trust_agent_settings);
+ }
+
+ public void onResume() {
+ super.onResume();
+ updateAgents();
+ };
+
+ private void updateAgents() {
+ final Context context = getActivity();
+ if (mAvailableAgents == null) {
+ mAvailableAgents = findAvailableTrustAgents();
+ }
+ if (mLockPatternUtils == null) {
+ mLockPatternUtils = new LockPatternUtils(getActivity());
+ }
+ loadActiveAgents();
+ PreferenceGroup category =
+ (PreferenceGroup) getPreferenceScreen().findPreference("trust_agents");
+ category.removeAll();
+ final int count = mAvailableAgents.size();
+ for (int i = 0; i < count; i++) {
+ AgentInfo agent = mAvailableAgents.valueAt(i);
+ final SwitchPreference preference = new SwitchPreference(context);
+ agent.preference = preference;
+ preference.setPersistent(false);
+ preference.setTitle(agent.label);
+ preference.setIcon(agent.icon);
+ preference.setPersistent(false);
+ preference.setOnPreferenceChangeListener(this);
+ preference.setChecked(mActiveAgents.contains(agent.component));
+ category.addPreference(agent.preference);
+ }
+ }
+
+ private void loadActiveAgents() {
+ List<ComponentName> activeTrustAgents = mLockPatternUtils.getEnabledTrustAgents();
+ if (activeTrustAgents != null) {
+ mActiveAgents.addAll(activeTrustAgents);
+ }
+ }
+
+ private void saveActiveAgents() {
+ mLockPatternUtils.setEnabledTrustAgents(mActiveAgents);
+ }
+
+ ArrayMap<ComponentName, AgentInfo> findAvailableTrustAgents() {
+ PackageManager pm = getActivity().getPackageManager();
+ Intent trustAgentIntent = new Intent(SERVICE_INTERFACE);
+ List<ResolveInfo> resolveInfos = pm.queryIntentServices(trustAgentIntent,
+ PackageManager.GET_META_DATA);
+
+ ArrayMap<ComponentName, AgentInfo> agents = new ArrayMap<ComponentName, AgentInfo>();
+ final int count = resolveInfos.size();
+ agents.ensureCapacity(count);
+ for (int i = 0; i < count; i++ ) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ if (resolveInfo.serviceInfo == null) continue;
+ if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
+ ComponentName name = TrustAgentUtils.getComponentName(resolveInfo);
+ AgentInfo agentInfo = new AgentInfo();
+ agentInfo.label = resolveInfo.loadLabel(pm);
+ agentInfo.icon = resolveInfo.loadIcon(pm);
+ agentInfo.component = name;
+ agents.put(name, agentInfo);
+ }
+ return agents;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference instanceof SwitchPreference) {
+ final int count = mAvailableAgents.size();
+ for (int i = 0; i < count; i++) {
+ AgentInfo agent = mAvailableAgents.valueAt(i);
+ if (agent.preference == preference) {
+ if ((Boolean) newValue) {
+ if (!mActiveAgents.contains(agent.component)) {
+ mActiveAgents.add(agent.component);
+ }
+ } else {
+ mActiveAgents.remove(agent.component);
+ }
+ saveActiveAgents();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/src/com/android/settings/UsageAccessSettings.java b/src/com/android/settings/UsageAccessSettings.java
index 8ae277d..8d0650b 100644
--- a/src/com/android/settings/UsageAccessSettings.java
+++ b/src/com/android/settings/UsageAccessSettings.java
@@ -20,8 +20,12 @@ import com.android.internal.content.PackageMonitor;
import android.Manifest;
import android.app.ActivityThread;
+import android.app.AlertDialog;
import android.app.AppOpsManager;
+import android.app.Dialog;
+import android.app.DialogFragment;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -30,6 +34,7 @@ import android.os.Bundle;
import android.os.Looper;
import android.os.RemoteException;
import android.preference.Preference;
+import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.util.ArrayMap;
import android.util.Log;
@@ -176,7 +181,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
if (newEntries == null) {
mPackageEntryMap.clear();
- getPreferenceScreen().removeAll();
+ mPreferenceScreen.removeAll();
return;
}
@@ -187,7 +192,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
final PackageEntry newPackageEntry = newEntries.get(oldPackageEntry.packageName);
if (newPackageEntry == null) {
// This package has been removed.
- getPreferenceScreen().removePreference(oldPackageEntry.preference);
+ mPreferenceScreen.removePreference(oldPackageEntry.preference);
} else {
// This package already exists in the preference hierarchy, so reuse that
// Preference.
@@ -203,7 +208,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
packageEntry.preference = new SwitchPreference(mContext);
packageEntry.preference.setPersistent(false);
packageEntry.preference.setOnPreferenceChangeListener(UsageAccessSettings.this);
- getPreferenceScreen().addPreference(packageEntry.preference);
+ mPreferenceScreen.addPreference(packageEntry.preference);
}
updatePreference(packageEntry);
}
@@ -232,20 +237,22 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
}
}
- private static boolean shouldIgnorePackage(String packageName) {
+ static boolean shouldIgnorePackage(String packageName) {
return packageName.equals("android") || packageName.equals("com.android.settings");
}
- private ArrayMap<String, PackageEntry> mPackageEntryMap = new ArrayMap<>();
- private AppOpsManager mAppOpsManager;
private AppsRequestingAccessFetcher mLastFetcherTask;
+ ArrayMap<String, PackageEntry> mPackageEntryMap = new ArrayMap<>();
+ AppOpsManager mAppOpsManager;
+ PreferenceScreen mPreferenceScreen;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.usage_access_settings);
- getPreferenceScreen().setOrderingAsAdded(false);
+ mPreferenceScreen = getPreferenceScreen();
+ mPreferenceScreen.setOrderingAsAdded(false);
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
}
@@ -302,13 +309,27 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
// Check if we need to do any work.
if (pe.appOpMode != newMode) {
- mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS,
- pe.packageInfo.applicationInfo.uid, packageName, newMode);
- pe.appOpMode = newMode;
+ if (newMode != AppOpsManager.MODE_ALLOWED) {
+ // Turning off the setting has no warning.
+ setNewMode(pe, newMode);
+ return true;
+ }
+
+ // Turning on the setting has a Warning.
+ getFragmentManager().beginTransaction()
+ .add(new WarningDialog(pe), "warning")
+ .commit();
+ return false;
}
return true;
}
+ void setNewMode(PackageEntry pe, int newMode) {
+ mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS,
+ pe.packageInfo.applicationInfo.uid, pe.packageName, newMode);
+ pe.appOpMode = newMode;
+ }
+
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override
public void onPackageAdded(String packageName, int uid) {
@@ -320,4 +341,34 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
updateInterestedApps();
}
};
+
+ private class WarningDialog extends DialogFragment
+ implements DialogInterface.OnClickListener {
+ private final PackageEntry mEntry;
+
+ public WarningDialog(PackageEntry pe) {
+ mEntry = pe;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.allow_usage_access_title)
+ .setMessage(R.string.allow_usage_access_message)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setNegativeButton(R.string.cancel, this)
+ .setPositiveButton(android.R.string.ok, this)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ setNewMode(mEntry, AppOpsManager.MODE_ALLOWED);
+ mEntry.preference.setChecked(true);
+ } else {
+ dialog.cancel();
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/UsageStats.java b/src/com/android/settings/UsageStatsActivity.java
index 08c272e..90aec5b 100755
--- a/src/com/android/settings/UsageStats.java
+++ b/src/com/android/settings/UsageStatsActivity.java
@@ -17,7 +17,7 @@
package com.android.settings;
import android.app.Activity;
-import android.app.usage.PackageUsageStats;
+import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
import java.util.Map;
import android.text.format.DateUtils;
@@ -48,15 +49,15 @@ import android.widget.AdapterView.OnItemSelectedListener;
/**
* Activity to display package usage statistics.
*/
-public class UsageStats extends Activity implements OnItemSelectedListener {
+public class UsageStatsActivity extends Activity implements OnItemSelectedListener {
private static final String TAG = "UsageStatsActivity";
private static final boolean localLOGV = false;
private UsageStatsManager mUsageStatsManager;
private LayoutInflater mInflater;
private UsageStatsAdapter mAdapter;
private PackageManager mPm;
-
- public static class AppNameComparator implements Comparator<PackageUsageStats> {
+
+ public static class AppNameComparator implements Comparator<UsageStats> {
private Map<String, String> mAppLabelList;
AppNameComparator(Map<String, String> appList) {
@@ -64,76 +65,87 @@ public class UsageStats extends Activity implements OnItemSelectedListener {
}
@Override
- public final int compare(PackageUsageStats a, PackageUsageStats b) {
+ public final int compare(UsageStats a, UsageStats b) {
String alabel = mAppLabelList.get(a.getPackageName());
String blabel = mAppLabelList.get(b.getPackageName());
return alabel.compareTo(blabel);
}
}
- public static class LastTimeUsedComparator implements Comparator<PackageUsageStats> {
+ public static class LastTimeUsedComparator implements Comparator<UsageStats> {
@Override
- public final int compare(PackageUsageStats a, PackageUsageStats b) {
+ public final int compare(UsageStats a, UsageStats b) {
// return by descending order
return (int)(b.getLastTimeUsed() - a.getLastTimeUsed());
}
}
-
- public static class UsageTimeComparator implements Comparator<PackageUsageStats> {
+
+ public static class UsageTimeComparator implements Comparator<UsageStats> {
@Override
- public final int compare(PackageUsageStats a, PackageUsageStats b) {
- return (int)(b.getTotalTimeSpent() - a.getTotalTimeSpent());
+ public final int compare(UsageStats a, UsageStats b) {
+ return (int)(b.getTotalTimeInForeground() - a.getTotalTimeInForeground());
}
}
-
+
// View Holder used when displaying views
static class AppViewHolder {
TextView pkgName;
TextView lastTimeUsed;
TextView usageTime;
}
-
+
class UsageStatsAdapter extends BaseAdapter {
// Constants defining order for display order
private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
private static final int _DISPLAY_ORDER_LAST_TIME_USED = 1;
private static final int _DISPLAY_ORDER_APP_NAME = 2;
-
+
private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
private LastTimeUsedComparator mLastTimeUsedComparator = new LastTimeUsedComparator();
private UsageTimeComparator mUsageTimeComparator = new UsageTimeComparator();
private AppNameComparator mAppLabelComparator;
private final ArrayMap<String, String> mAppLabelMap = new ArrayMap<>();
- private final ArrayList<PackageUsageStats> mPackageStats = new ArrayList<>();
+ private final ArrayList<UsageStats> mPackageStats = new ArrayList<>();
UsageStatsAdapter() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -5);
- final android.app.usage.UsageStats stats =
- mUsageStatsManager.getRecentStatsSince(cal.getTimeInMillis());
+ final List<UsageStats> stats =
+ mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
+ cal.getTimeInMillis(), System.currentTimeMillis());
if (stats == null) {
return;
}
- final int pkgCount = stats.getPackageCount();
- for (int i = 0; i < pkgCount; i++) {
- final PackageUsageStats pkgStats = stats.getPackage(i);
+ ArrayMap<String, UsageStats> map = new ArrayMap<>();
+ final int statCount = stats.size();
+ for (int i = 0; i < statCount; i++) {
+ final android.app.usage.UsageStats pkgStats = stats.get(i);
// load application labels for each application
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(pkgStats.getPackageName(), 0);
String label = appInfo.loadLabel(mPm).toString();
mAppLabelMap.put(pkgStats.getPackageName(), label);
- mPackageStats.add(pkgStats);
+
+ UsageStats existingStats =
+ map.get(pkgStats.getPackageName());
+ if (existingStats == null) {
+ map.put(pkgStats.getPackageName(), pkgStats);
+ } else {
+ existingStats.add(pkgStats);
+ }
+
} catch (NameNotFoundException e) {
// This package may be gone.
}
- }
+ }
+ mPackageStats.addAll(map.values());
- // Sort list
- mAppLabelComparator = new AppNameComparator(mAppLabelMap);
- sortList();
+ // Sort list
+ mAppLabelComparator = new AppNameComparator(mAppLabelMap);
+ sortList();
}
@Override
@@ -177,20 +189,20 @@ public class UsageStats extends Activity implements OnItemSelectedListener {
}
// Bind the data efficiently with the holder
- PackageUsageStats pkgStats = mPackageStats.get(position);
+ UsageStats pkgStats = mPackageStats.get(position);
if (pkgStats != null) {
String label = mAppLabelMap.get(pkgStats.getPackageName());
holder.pkgName.setText(label);
holder.lastTimeUsed.setText(DateUtils.formatSameDayTime(pkgStats.getLastTimeUsed(),
System.currentTimeMillis(), DateFormat.MEDIUM, DateFormat.MEDIUM));
holder.usageTime.setText(
- DateUtils.formatElapsedTime(pkgStats.getTotalTimeSpent() / 1000));
+ DateUtils.formatElapsedTime(pkgStats.getTotalTimeInForeground() / 1000));
} else {
Log.w(TAG, "No usage stats info for package:" + position);
}
return convertView;
}
-
+
void sortList(int sortOrder) {
if (mDisplayOrder == sortOrder) {
// do nothing
@@ -226,7 +238,7 @@ public class UsageStats extends Activity implements OnItemSelectedListener {
Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
typeSpinner.setOnItemSelectedListener(this);
-
+
ListView listView = (ListView) findViewById(R.id.pkg_list);
mAdapter = new UsageStatsAdapter();
listView.setAdapter(mAdapter);
@@ -242,4 +254,3 @@ public class UsageStats extends Activity implements OnItemSelectedListener {
// do nothing
}
}
-
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 255ab58..47ff6af 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -30,9 +30,11 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
@@ -774,17 +776,24 @@ public final class Utils {
DialogInterface.OnClickListener onConfirmListener) {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
UserInfo userInfo = um.getUserInfo(removingUserId);
+ int titleResId;
+ int messageResId;
+ if (UserHandle.myUserId() == removingUserId) {
+ titleResId = R.string.user_confirm_remove_self_title;
+ messageResId = R.string.user_confirm_remove_self_message;
+ } else if (userInfo.isRestricted()) {
+ titleResId = R.string.user_profile_confirm_remove_title;
+ messageResId = R.string.user_profile_confirm_remove_message;
+ } else if (userInfo.isManagedProfile()) {
+ titleResId = R.string.work_profile_confirm_remove_title;
+ messageResId = R.string.work_profile_confirm_remove_message;
+ } else {
+ titleResId = R.string.user_confirm_remove_title;
+ messageResId = R.string.user_confirm_remove_message;
+ }
Dialog dlg = new AlertDialog.Builder(context)
- .setTitle(UserHandle.myUserId() == removingUserId
- ? R.string.user_confirm_remove_self_title
- : (userInfo.isRestricted()
- ? R.string.user_profile_confirm_remove_title
- : R.string.user_confirm_remove_title))
- .setMessage(UserHandle.myUserId() == removingUserId
- ? R.string.user_confirm_remove_self_message
- : (userInfo.isRestricted()
- ? R.string.user_profile_confirm_remove_message
- : R.string.user_confirm_remove_message))
+ .setTitle(titleResId)
+ .setMessage(messageResId)
.setPositiveButton(R.string.user_delete_button,
onConfirmListener)
.setNegativeButton(android.R.string.cancel, null)
@@ -820,4 +829,46 @@ public final class Utils {
if (icon == null) return null;
return CircleFramedDrawable.getInstance(context, icon);
}
+
+ /**
+ * Return whether or not the user should have a SIM Cards option in Settings.
+ * TODO: Change back to returning true if count is greater than one after testing.
+ * TODO: See bug 16533525.
+ */
+ public static boolean showSimCardTile(Context context) {
+ final TelephonyManager tm =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+
+ return tm.getSimCount() > 0;
+ }
+
+ /**
+ * Determine whether a package is a "system package", in which case certain things (like
+ * disabling notifications or disabling the package altogether) should be disallowed.
+ */
+ public static boolean isSystemPackage(PackageManager pm, PackageInfo pkg) {
+ if (sSystemSignature == null) {
+ sSystemSignature = new Signature[]{ getSystemSignature(pm) };
+ }
+ return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg));
+ }
+
+ private static Signature[] sSystemSignature;
+
+ private static Signature getFirstSignature(PackageInfo pkg) {
+ if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
+ return pkg.signatures[0];
+ }
+ return null;
+ }
+
+ private static Signature getSystemSignature(PackageManager pm) {
+ try {
+ final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
+ return getFirstSignature(sys);
+ } catch (NameNotFoundException e) {
+ }
+ return null;
+ }
+
}
diff --git a/src/com/android/settings/VoiceSettingsActivity.java b/src/com/android/settings/VoiceSettingsActivity.java
new file mode 100644
index 0000000..b5e8ede
--- /dev/null
+++ b/src/com/android/settings/VoiceSettingsActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity for modifying a setting using the Voice Interaction API. This activity
+ * MUST only modify the setting if the intent was sent using
+ * {@link android.service.voice.VoiceInteractionSession#startVoiceActivity startVoiceActivity}.
+ */
+abstract public class VoiceSettingsActivity extends Activity {
+
+ private static final String TAG = "VoiceSettingsActivity";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (isVoiceInteraction()) {
+ // Only permit if this is a voice interaction.
+ onVoiceSettingInteraction(getIntent());
+ } else {
+ Log.v(TAG, "Cannot modify settings without voice interaction");
+ }
+ finish();
+ }
+
+ /**
+ * Modify the setting as a voice interaction. The activity will finish
+ * after this method is called.
+ */
+ abstract protected void onVoiceSettingInteraction(Intent intent);
+}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 39d0f4c..ab7e28b 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -39,6 +39,7 @@ import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -79,7 +80,7 @@ public class WirelessSettings extends SettingsPreferenceFragment
public static final int REQUEST_CODE_EXIT_ECM = 1;
private AirplaneModeEnabler mAirplaneModeEnabler;
- private CheckBoxPreference mAirplaneModePreference;
+ private SwitchPreference mAirplaneModePreference;
private NfcEnabler mNfcEnabler;
private NfcAdapter mNfcAdapter;
private NsdEnabler mNsdEnabler;
@@ -128,9 +129,13 @@ public class WirelessSettings extends SettingsPreferenceFragment
if (mTm.hasIccCard() && (ni != null)) {
// Check for carrier apps that can handle provisioning first
Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP);
- provisioningIntent.addCategory(TelephonyIntents.CATEGORY_MCCMNC_PREFIX
- + mTm.getSimOperator());
- if (mPm.resolveActivity(provisioningIntent, 0 /* flags */) != null) {
+ List<String> carrierPackages =
+ mTm.getCarrierPackageNamesForIntent(provisioningIntent);
+ if (carrierPackages != null && !carrierPackages.isEmpty()) {
+ if (carrierPackages.size() != 1) {
+ Log.w(TAG, "Multiple matching carrier apps found, launching the first.");
+ }
+ provisioningIntent.setPackage(carrierPackages.get(0));
startActivity(provisioningIntent);
return;
}
@@ -254,8 +259,8 @@ public class WirelessSettings extends SettingsPreferenceFragment
final boolean isSecondaryUser = UserHandle.myUserId() != UserHandle.USER_OWNER;
final Activity activity = getActivity();
- mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
- CheckBoxPreference nfc = (CheckBoxPreference) findPreference(KEY_TOGGLE_NFC);
+ mAirplaneModePreference = (SwitchPreference) findPreference(KEY_TOGGLE_AIRPLANE);
+ SwitchPreference nfc = (SwitchPreference) findPreference(KEY_TOGGLE_NFC);
PreferenceScreen androidBeam = (PreferenceScreen) findPreference(KEY_ANDROID_BEAM_SETTINGS);
CheckBoxPreference nsd = (CheckBoxPreference) findPreference(KEY_TOGGLE_NSD);
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 36025a6..92c478e 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -18,6 +18,7 @@ package com.android.settings.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.ActivityManagerNative;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -28,6 +29,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
@@ -197,11 +199,15 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
private int mLongPressTimeoutDefault;
+ private DevicePolicyManager mDpm;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.accessibility_settings);
initializeAllPreferences();
+ mDpm = (DevicePolicyManager) (getActivity()
+ .getSystemService(Context.DEVICE_POLICY_SERVICE));
}
@Override
@@ -434,7 +440,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
accessibilityManager.getInstalledAccessibilityServiceList();
Set<ComponentName> enabledServices = AccessibilityUtils.getEnabledServicesFromSettings(
getActivity());
-
+ List<String> permittedServices = mDpm.getPermittedAccessibilityServices(
+ UserHandle.myUserId());
final boolean accessibilityEnabled = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
@@ -454,11 +461,26 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
preference.setTitle(title);
final boolean serviceEnabled = accessibilityEnabled
&& enabledServices.contains(componentName);
+ String serviceEnabledString;
if (serviceEnabled) {
- preference.setSummary(getString(R.string.accessibility_feature_state_on));
+ serviceEnabledString = getString(R.string.accessibility_feature_state_on);
} else {
- preference.setSummary(getString(R.string.accessibility_feature_state_off));
+ serviceEnabledString = getString(R.string.accessibility_feature_state_off);
+ }
+
+ // Disable all accessibility services that are not permitted.
+ String packageName = serviceInfo.packageName;
+ boolean serviceAllowed =
+ permittedServices == null || permittedServices.contains(packageName);
+ preference.setEnabled(serviceAllowed || serviceEnabled);
+
+ String summaryString;
+ if (serviceAllowed) {
+ summaryString = serviceEnabledString;
+ } else {
+ summaryString = getString(R.string.accessibility_feature_or_input_method_not_allowed);
}
+ preference.setSummary(summaryString);
preference.setOrder(i);
preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
@@ -491,19 +513,13 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
if (mServicesCategory.getPreferenceCount() == 0) {
if (mNoServicesMessagePreference == null) {
- mNoServicesMessagePreference = new Preference(getActivity()) {
- @Override
- protected void onBindView(View view) {
- super.onBindView(view);
- TextView summaryView = (TextView) view.findViewById(R.id.summary);
- String title = getString(R.string.accessibility_no_services_installed);
- summaryView.setText(title);
- }
- };
+ mNoServicesMessagePreference = new Preference(getActivity());
mNoServicesMessagePreference.setPersistent(false);
mNoServicesMessagePreference.setLayoutResource(
R.layout.text_description_preference);
mNoServicesMessagePreference.setSelectable(false);
+ mNoServicesMessagePreference.setSummary(
+ getString(R.string.accessibility_no_services_installed));
}
mServicesCategory.addPreference(mNoServicesMessagePreference);
}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 9fe70df..b23035b 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -55,10 +55,10 @@ public abstract class ToggleFeaturePreferenceFragment
getActivity());
setPreferenceScreen(preferenceScreen);
mSummaryPreference = new Preference(getActivity()) {
- @Override
+ @Override
protected void onBindView(View view) {
super.onBindView(view);
- TextView summaryView = (TextView) view.findViewById(R.id.summary);
+ final TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
summaryView.setText(getSummary());
sendAccessibilityEvent(summaryView);
}
diff --git a/src/com/android/settings/accounts/AccountSettings.java b/src/com/android/settings/accounts/AccountSettings.java
index ffd6037..9bcef13 100644
--- a/src/com/android/settings/accounts/AccountSettings.java
+++ b/src/com/android/settings/accounts/AccountSettings.java
@@ -29,10 +29,12 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.Process;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
@@ -41,6 +43,7 @@ import android.view.MenuItem;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
+import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import com.android.settings.R;
@@ -50,8 +53,10 @@ import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
import static android.content.Intent.EXTRA_USER;
+import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
/**
* Settings screen for the account types on the device.
@@ -64,26 +69,20 @@ public class AccountSettings extends SettingsPreferenceFragment
implements AuthenticatorHelper.OnAccountsUpdateListener,
OnPreferenceClickListener {
public static final String TAG = "AccountSettings";
- private static final String KEY_ACCOUNT = "account";
- private static final String KEY_ADD_ACCOUNT = "add_account";
- private static final String KEY_CATEGORY_PERSONAL = "account_personal";
- private static final String KEY_ADD_ACCOUNT_PERSONAL = "add_account_personal";
- private static final String KEY_CATEGORY_WORK = "account_work";
- private static final String KEY_ADD_ACCOUNT_WORK = "add_account_work";
+ private static final String KEY_ACCOUNT = "account";
private static final String ADD_ACCOUNT_ACTION = "android.settings.ADD_ACCOUNT_SETTINGS";
-
- private static final ArrayList<String> EMPTY_LIST = new ArrayList<String>();
-
private static final String TAG_CONFIRM_AUTO_SYNC_CHANGE = "confirmAutoSyncChange";
+ private static final int ORDER_LAST = 1001;
+ private static final int ORDER_NEXT_TO_LAST = 1000;
private UserManager mUm;
- private SparseArray<ProfileData> mProfiles;
+ private SparseArray<ProfileData> mProfiles = new SparseArray<ProfileData>();
private ManagedProfileBroadcastReceiver mManagedProfileBroadcastReceiver
= new ManagedProfileBroadcastReceiver();
- private boolean mIsSingleProfileUi = true;
+ private Preference mProfileNotAvailablePreference;
/**
* Holds data related to the accounts belonging to one profile.
@@ -98,64 +97,62 @@ public class AccountSettings extends SettingsPreferenceFragment
*/
public Preference addAccountPreference;
/**
- * The user handle of the user that these accounts belong to.
+ * The preference that displays the button to remove the managed profile
*/
- public UserHandle userHandle;
+ public Preference removeWorkProfilePreference;
/**
* The {@link AuthenticatorHelper} that holds accounts data for this profile.
*/
public AuthenticatorHelper authenticatorHelper;
+ /**
+ * The {@link UserInfo} of the profile.
+ */
+ public UserInfo userInfo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUm = (UserManager) getSystemService(Context.USER_SERVICE);
- mProfiles = new SparseArray<ProfileData>(2);
+ mProfileNotAvailablePreference = new Preference(getActivity());
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.account_settings, menu);
- final UserHandle currentProfile = UserHandle.getCallingUserHandle();
- if (mIsSingleProfileUi) {
- menu.findItem(R.id.account_settings_menu_auto_sync)
- .setVisible(true)
- .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile));
- menu.removeItem(R.id.account_settings_menu_auto_sync_personal);
- menu.removeItem(R.id.account_settings_menu_auto_sync_work);
- } else {
- final UserHandle managedProfile = Utils.getManagedProfile(mUm);
-
- menu.findItem(R.id.account_settings_menu_auto_sync_personal)
- .setVisible(true)
- .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile));
- menu.findItem(R.id.account_settings_menu_auto_sync_work)
- .setVisible(true)
- .setOnMenuItemClickListener(new MasterSyncStateClickListener(managedProfile));
- menu.removeItem(R.id.account_settings_menu_auto_sync);
- }
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
- final UserHandle currentProfile = UserHandle.getCallingUserHandle();
- if (mIsSingleProfileUi) {
+ final UserHandle currentProfile = Process.myUserHandle();
+ if (mProfiles.size() == 1) {
menu.findItem(R.id.account_settings_menu_auto_sync)
+ .setVisible(true)
+ .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
.setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
currentProfile.getIdentifier()));
- } else {
- final UserHandle managedProfile = Utils.getManagedProfile(mUm);
+ menu.findItem(R.id.account_settings_menu_auto_sync_personal).setVisible(false);
+ menu.findItem(R.id.account_settings_menu_auto_sync_work).setVisible(false);
+ } else if (mProfiles.size() > 1) {
+ // We assume there's only one managed profile, otherwise UI needs to change
+ final UserHandle managedProfile = mProfiles.valueAt(1).userInfo.getUserHandle();
menu.findItem(R.id.account_settings_menu_auto_sync_personal)
+ .setVisible(true)
+ .setOnMenuItemClickListener(new MasterSyncStateClickListener(currentProfile))
.setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
currentProfile.getIdentifier()));
menu.findItem(R.id.account_settings_menu_auto_sync_work)
+ .setVisible(true)
+ .setOnMenuItemClickListener(new MasterSyncStateClickListener(managedProfile))
.setChecked(ContentResolver.getMasterSyncAutomaticallyAsUser(
managedProfile.getIdentifier()));
- }
+ menu.findItem(R.id.account_settings_menu_auto_sync).setVisible(false);
+ } else {
+ Log.w(TAG, "Method onPrepareOptionsMenu called before mProfiles was initialized");
+ }
}
@Override
@@ -192,10 +189,22 @@ public class AccountSettings extends SettingsPreferenceFragment
ProfileData profileData = mProfiles.valueAt(i);
if (preference == profileData.addAccountPreference) {
Intent intent = new Intent(ADD_ACCOUNT_ACTION);
- intent.putExtra(EXTRA_USER, profileData.userHandle);
+ intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
startActivity(intent);
return true;
}
+ if (preference == profileData.removeWorkProfilePreference) {
+ final int userId = profileData.userInfo.id;
+ Utils.createRemoveConfirmationDialog(getActivity(), userId,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mUm.removeUser(userId);
+ }
+ }
+ ).show();
+ return true;
+ }
}
return false;
}
@@ -204,61 +213,82 @@ public class AccountSettings extends SettingsPreferenceFragment
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.account_settings);
+ if (Utils.isManagedProfile(mUm)) {
+ // This should not happen
+ Log.e(TAG, "We should not be showing settings for a managed profile");
+ finish();
+ return;
+ }
+
+ final PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference(KEY_ACCOUNT);
if(mUm.isLinkedUser()) {
// Restricted user or similar
- updateSingleProfileUi();
+ UserInfo userInfo = mUm.getUserInfo(UserHandle.myUserId());
+ updateProfileUi(userInfo, false /* no category needed */, preferenceScreen);
} else {
- if (Utils.isManagedProfile(mUm)) {
- // This should not happen
- Log.w(TAG, "We should not be showing settings for a managed profile");
- updateSingleProfileUi();
+ List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
+ final int profilesCount = profiles.size();
+ final boolean addCategory = profilesCount > 1;
+ for (int i = 0; i < profilesCount; i++) {
+ updateProfileUi(profiles.get(i), addCategory, preferenceScreen);
}
- final UserHandle currentProfile = UserHandle.getCallingUserHandle();
- final UserHandle managedProfile = Utils.getManagedProfile(mUm);
- if (managedProfile == null) {
- updateSingleProfileUi();
- } else {
- mIsSingleProfileUi = false;
- updateProfileUi(currentProfile, KEY_CATEGORY_PERSONAL, KEY_ADD_ACCOUNT_PERSONAL,
- EMPTY_LIST);
- final ArrayList<String> unusedPreferences = new ArrayList<String>(2);
- unusedPreferences.add(KEY_ADD_ACCOUNT);
- updateProfileUi(managedProfile, KEY_CATEGORY_WORK, KEY_ADD_ACCOUNT_WORK,
- unusedPreferences);
- }
- }
- final int count = mProfiles.size();
- for (int i = 0; i < count; i++) {
- updateAccountTypes(mProfiles.valueAt(i));
}
- }
- private void updateSingleProfileUi() {
- final ArrayList<String> unusedPreferences = new ArrayList<String>(2);
- unusedPreferences.add(KEY_CATEGORY_PERSONAL);
- unusedPreferences.add(KEY_CATEGORY_WORK);
- updateProfileUi(UserHandle.getCallingUserHandle(), KEY_ACCOUNT, KEY_ADD_ACCOUNT,
- unusedPreferences);
+ // Add all preferences, starting with one for the primary profile.
+ // Note that we're relying on the ordering given by the SparseArray keys, and on the
+ // value of UserHandle.USER_OWNER being smaller than all the rest.
+ final int profilesCount = mProfiles.size();
+ for (int i = 0; i < profilesCount; i++) {
+ ProfileData profileData = mProfiles.valueAt(i);
+ if (!profileData.preferenceGroup.equals(preferenceScreen)) {
+ preferenceScreen.addPreference(profileData.preferenceGroup);
+ }
+ updateAccountTypes(profileData);
+ }
}
- private void updateProfileUi(final UserHandle userHandle, String categoryKey,
- String addAccountKey, ArrayList<String> unusedPreferences) {
- final int count = unusedPreferences.size();
- for (int i = 0; i < count; i++) {
- removePreference(unusedPreferences.get(i));
- }
+ private void updateProfileUi(final UserInfo userInfo, boolean addCategory,
+ PreferenceScreen parent) {
+ final Context context = getActivity();
final ProfileData profileData = new ProfileData();
- profileData.preferenceGroup = (PreferenceGroup) findPreference(categoryKey);
- if (mUm.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, userHandle)) {
- removePreference(addAccountKey);
+ profileData.userInfo = userInfo;
+ if (addCategory) {
+ profileData.preferenceGroup = new PreferenceCategory(context);
+ profileData.preferenceGroup.setTitle(userInfo.isManagedProfile()
+ ? R.string.category_work : R.string.category_personal);
+ parent.addPreference(profileData.preferenceGroup);
} else {
- profileData.addAccountPreference = findPreference(addAccountKey);
- profileData.addAccountPreference.setOnPreferenceClickListener(this);
+ profileData.preferenceGroup = parent;
+ }
+ if (userInfo.isEnabled()) {
+ profileData.authenticatorHelper = new AuthenticatorHelper(context,
+ userInfo.getUserHandle(), mUm, this);
+ if (!mUm.hasUserRestriction(DISALLOW_MODIFY_ACCOUNTS, userInfo.getUserHandle())) {
+ profileData.addAccountPreference = newAddAccountPreference(context);
+ }
+ }
+ if (userInfo.isManagedProfile()) {
+ profileData.removeWorkProfilePreference = newRemoveWorkProfilePreference(context);
}
- profileData.userHandle = userHandle;
- profileData.authenticatorHelper = new AuthenticatorHelper(
- getActivity(), userHandle, mUm, this);
- mProfiles.put(userHandle.getIdentifier(), profileData);
+ mProfiles.put(userInfo.id, profileData);
+ }
+
+ private Preference newAddAccountPreference(Context context) {
+ Preference preference = new Preference(context);
+ preference.setTitle(R.string.add_account_label);
+ preference.setIcon(R.drawable.ic_menu_add_dark);
+ preference.setOnPreferenceClickListener(this);
+ preference.setOrder(ORDER_NEXT_TO_LAST);
+ return preference;
+ }
+
+ private Preference newRemoveWorkProfilePreference(Context context) {
+ Preference preference = new Preference(context);
+ preference.setTitle(R.string.remove_managed_profile_label);
+ preference.setIcon(R.drawable.ic_menu_delete);
+ preference.setOnPreferenceClickListener(this);
+ preference.setOrder(ORDER_LAST);
+ return preference;
}
private void cleanUpPreferences() {
@@ -266,32 +296,52 @@ public class AccountSettings extends SettingsPreferenceFragment
if (preferenceScreen != null) {
preferenceScreen.removeAll();
}
+ mProfiles.clear();
}
private void listenToAccountUpdates() {
final int count = mProfiles.size();
for (int i = 0; i < count; i++) {
- mProfiles.valueAt(i).authenticatorHelper.listenToAccountUpdates();
+ AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
+ if (authenticatorHelper != null) {
+ authenticatorHelper.listenToAccountUpdates();
+ }
}
}
private void stopListeningToAccountUpdates() {
final int count = mProfiles.size();
for (int i = 0; i < count; i++) {
- mProfiles.valueAt(i).authenticatorHelper.stopListeningToAccountUpdates();
+ AuthenticatorHelper authenticatorHelper = mProfiles.valueAt(i).authenticatorHelper;
+ if (authenticatorHelper != null) {
+ authenticatorHelper.stopListeningToAccountUpdates();
+ }
}
}
private void updateAccountTypes(ProfileData profileData) {
profileData.preferenceGroup.removeAll();
- final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
- profileData.authenticatorHelper, profileData.userHandle);
- final int count = preferences.size();
- for (int i = 0; i < count; i++) {
- profileData.preferenceGroup.addPreference(preferences.get(i));
+ if (profileData.userInfo.isEnabled()) {
+ final ArrayList<AccountPreference> preferences = getAccountTypePreferences(
+ profileData.authenticatorHelper, profileData.userInfo.getUserHandle());
+ final int count = preferences.size();
+ for (int i = 0; i < count; i++) {
+ profileData.preferenceGroup.addPreference(preferences.get(i));
+ }
+ if (profileData.addAccountPreference != null) {
+ profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
+ }
+ } else {
+ // Put a label instead of the accounts list
+ mProfileNotAvailablePreference.setEnabled(false);
+ mProfileNotAvailablePreference.setIcon(R.drawable.empty_icon);
+ mProfileNotAvailablePreference.setTitle(null);
+ mProfileNotAvailablePreference.setSummary(
+ R.string.managed_profile_not_available_label);
+ profileData.preferenceGroup.addPreference(mProfileNotAvailablePreference);
}
- if (profileData.addAccountPreference != null) {
- profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
+ if (profileData.removeWorkProfilePreference != null) {
+ profileData.preferenceGroup.addPreference(profileData.removeWorkProfilePreference);
}
}
@@ -404,6 +454,9 @@ public class AccountSettings extends SettingsPreferenceFragment
// Build new state
updateUi();
listenToAccountUpdates();
+ // Force the menu to update. Note that #onPrepareOptionsMenu uses data built by
+ // #updateUi so we must call this later
+ getActivity().invalidateOptionsMenu();
return;
}
Log.w(TAG, "Cannot handle received broadcast: " + intent.getAction());
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index b69bf3f..8787bce 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -97,6 +97,8 @@ public class ManageAccountsSettings extends AccountPreferenceBase
public void onStart() {
super.onStart();
mAuthenticatorHelper.listenToAccountUpdates();
+ updateAuthDescriptions();
+ showAccountsIfNeeded();
}
@Override
@@ -124,8 +126,6 @@ public class ManageAccountsSettings extends AccountPreferenceBase
if (args != null && args.containsKey(KEY_ACCOUNT_LABEL)) {
getActivity().setTitle(args.getString(KEY_ACCOUNT_LABEL));
}
- updateAuthDescriptions();
- showAccountsIfNeeded();
}
@Override
diff --git a/src/com/android/settings/applications/AppOpsState.java b/src/com/android/settings/applications/AppOpsState.java
index 75a8372..580c44e 100644
--- a/src/com/android/settings/applications/AppOpsState.java
+++ b/src/com/android/settings/applications/AppOpsState.java
@@ -190,13 +190,15 @@ public class AppOpsState {
AppOpsManager.OP_WRITE_SETTINGS,
AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
AppOpsManager.OP_WAKE_LOCK,
- AppOpsManager.OP_PROJECT_MEDIA },
+ AppOpsManager.OP_PROJECT_MEDIA,
+ AppOpsManager.OP_ACTIVATE_VPN, },
new boolean[] { false,
true,
true,
true,
true,
true,
+ false,
false, }
);
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 463520d..4b1bc10 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -316,22 +316,13 @@ public class InstalledAppDetails extends Fragment
}
}
- private boolean isThisASystemPackage() {
- try {
- PackageInfo sys = mPm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
- return (mPackageInfo != null && mPackageInfo.signatures != null &&
- sys.signatures[0].equals(mPackageInfo.signatures[0]));
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- }
-
private boolean handleDisableable(Button button) {
boolean disableable = false;
// Try to prevent the user from bricking their phone
// by not allowing disabling of apps signed with the
// system cert and any launcher app in the system.
- if (mHomePackages.contains(mAppEntry.info.packageName) || isThisASystemPackage()) {
+ if (mHomePackages.contains(mAppEntry.info.packageName)
+ || Utils.isSystemPackage(mPm, mPackageInfo)) {
// Disable button for core system applications.
button.setText(R.string.disable_text);
} else if (mAppEntry.info.enabled) {
@@ -347,18 +338,22 @@ public class InstalledAppDetails extends Fragment
private void initUninstallButtons() {
mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
+ final boolean isBundled = (mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
boolean enabled = true;
if (mUpdatedSysApp) {
mUninstallButton.setText(R.string.app_factory_reset);
- boolean specialDisable = false;
- if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- specialDisable = handleDisableable(mSpecialDisableButton);
+ boolean showSpecialDisable = false;
+ if (isBundled) {
+ showSpecialDisable = handleDisableable(mSpecialDisableButton);
mSpecialDisableButton.setOnClickListener(this);
}
- mMoreControlButtons.setVisibility(specialDisable ? View.VISIBLE : View.GONE);
+ if (mAppControlRestricted) {
+ showSpecialDisable = false;
+ }
+ mMoreControlButtons.setVisibility(showSpecialDisable ? View.VISIBLE : View.GONE);
} else {
mMoreControlButtons.setVisibility(View.GONE);
- if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if (isBundled) {
enabled = handleDisableable(mUninstallButton);
} else if ((mPackageInfo.applicationInfo.flags
& ApplicationInfo.FLAG_INSTALLED) == 0
@@ -377,19 +372,27 @@ public class InstalledAppDetails extends Fragment
enabled = false;
}
- // If this is the default (or only) home app, suppress uninstall (even if
- // we still think it should be allowed for other reasons)
+ // Home apps need special handling. Bundled ones we don't risk downgrading
+ // because that can interfere with home-key resolution. Furthermore, we
+ // can't allow uninstallation of the only home app, and we don't want to
+ // allow uninstallation of an explicitly preferred one -- the user can go
+ // to Home settings and pick a different one, after which we'll permit
+ // uninstallation of the now-not-default one.
if (enabled && mHomePackages.contains(mPackageInfo.packageName)) {
- ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
- ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
- if (currentDefaultHome == null) {
- // No preferred default, so permit uninstall only when
- // there is more than one candidate
- enabled = (mHomePackages.size() > 1);
+ if (isBundled) {
+ enabled = false;
} else {
- // There is an explicit default home app -- forbid uninstall of
- // that one, but permit it for installed-but-inactive ones.
- enabled = !mPackageInfo.packageName.equals(currentDefaultHome.getPackageName());
+ ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
+ ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
+ if (currentDefaultHome == null) {
+ // No preferred default, so permit uninstall only when
+ // there is more than one candidate
+ enabled = (mHomePackages.size() > 1);
+ } else {
+ // There is an explicit default home app -- forbid uninstall of
+ // that one, but permit it for installed-but-inactive ones.
+ enabled = !mPackageInfo.packageName.equals(currentDefaultHome.getPackageName());
+ }
}
}
@@ -415,7 +418,7 @@ public class InstalledAppDetails extends Fragment
// this does not bode well
}
mNotificationSwitch.setChecked(enabled);
- if (isThisASystemPackage()) {
+ if (Utils.isSystemPackage(mPm, mPackageInfo)) {
mNotificationSwitch.setEnabled(false);
} else {
mNotificationSwitch.setEnabled(true);
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 1889634..ac5a78a 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -74,7 +74,6 @@ import com.android.settings.SettingsActivity;
import com.android.settings.UserSpinnerAdapter;
import com.android.settings.Settings.RunningServicesActivity;
import com.android.settings.Settings.StorageUseActivity;
-import com.android.settings.UserSpinnerAdapter.UserDetails;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.deviceinfo.StorageMeasurement;
import com.android.settings.Utils;
@@ -142,6 +141,7 @@ public class ManageApplications extends Fragment implements
static final String TAG = "ManageApplications";
static final boolean DEBUG = false;
+ private static final String EXTRA_LIST_TYPE = "currentListType";
private static final String EXTRA_SORT_ORDER = "sortOrder";
private static final String EXTRA_SHOW_BACKGROUND = "showBackground";
private static final String EXTRA_DEFAULT_LIST_TYPE = "defaultListType";
@@ -467,7 +467,8 @@ public class ManageApplications extends Fragment implements
// These are for keeping track of activity and spinner switch state.
private boolean mActivityResumed;
-
+
+ private static final int LIST_TYPE_MISSING = -1;
static final int LIST_TYPE_DOWNLOADED = 0;
static final int LIST_TYPE_RUNNING = 1;
static final int LIST_TYPE_SDCARD = 2;
@@ -954,9 +955,13 @@ public class ManageApplications extends Fragment implements
if (savedInstanceState == null) {
// First time init: make sure view pager is showing the correct tab.
- for (int i = 0; i < mTabs.size(); i++) {
+ int extraCurrentListType = getActivity().getIntent().getIntExtra(EXTRA_LIST_TYPE,
+ LIST_TYPE_MISSING);
+ int currentListType = (extraCurrentListType != LIST_TYPE_MISSING)
+ ? extraCurrentListType : mDefaultListType;
+ for (int i = 0; i < mNumTabs; i++) {
TabInfo tab = mTabs.get(i);
- if (tab.mListType == mDefaultListType) {
+ if (tab.mListType == currentListType) {
mViewPager.setCurrentItem(i);
break;
}
@@ -1036,6 +1041,8 @@ public class ManageApplications extends Fragment implements
if (selectedUser.getIdentifier() != UserHandle.myUserId()) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ int currentTab = mViewPager.getCurrentItem();
+ intent.putExtra(EXTRA_LIST_TYPE, mTabs.get(currentTab).mListType);
mContext.startActivityAsUser(intent, selectedUser);
getActivity().finish();
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index e8bad0c..eca0cca 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -318,6 +318,6 @@ public final class BluetoothDevicePreference extends Preference implements
return R.drawable.ic_bt_headset_hfp;
}
}
- return 0;
+ return R.drawable.ic_settings_bluetooth2;
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
index bf0356c..4466aea 100644
--- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
@@ -92,7 +92,6 @@ public final class BluetoothNameDialogFragment extends DialogFragment implements
mDeviceNameEdited = savedInstanceState.getBoolean(KEY_NAME_EDITED, false);
}
mAlertDialog = new AlertDialog.Builder(getActivity())
- .setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.bluetooth_rename_device)
.setView(createDialogView(deviceName))
.setPositiveButton(R.string.bluetooth_rename_button,
@@ -178,7 +177,6 @@ public final class BluetoothNameDialogFragment extends DialogFragment implements
mDeviceNameUpdated = true;
mDeviceNameEdited = false;
mDeviceNameView.setText(mLocalAdapter.getName());
- getActivity().setTitle(mLocalAdapter.getName());
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
index 9922042..02eed99 100755
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
@@ -175,7 +175,8 @@ public final class BluetoothPairingDialog extends AlertActivity implements
private View createPinEntryView(String deviceName) {
View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_entry, null);
- TextView messageView = (TextView) view.findViewById(R.id.message);
+ TextView messageViewCaption = (TextView) view.findViewById(R.id.message_caption);
+ TextView messageViewContent = (TextView) view.findViewById(R.id.message_subhead);
TextView messageView2 = (TextView) view.findViewById(R.id.message_below_pin);
CheckBox alphanumericPin = (CheckBox) view.findViewById(R.id.alphanumeric_pin);
mPairingView = (EditText) view.findViewById(R.id.text);
@@ -194,7 +195,7 @@ public final class BluetoothPairingDialog extends AlertActivity implements
break;
case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
- messageId1 = R.string.bluetooth_enter_passkey_msg;
+ messageId1 = R.string.bluetooth_enter_pin_msg;
messageId2 = R.string.bluetooth_enter_passkey_other_device;
// Maximum of 6 digits for passkey
maxLength = BLUETOOTH_PASSKEY_MAX_LENGTH;
@@ -206,9 +207,8 @@ public final class BluetoothPairingDialog extends AlertActivity implements
return null;
}
- // HTML escape deviceName, Format the message string, then parse HTML style tags
- String messageText = getString(messageId1, Html.escapeHtml(deviceName));
- messageView.setText(Html.fromHtml(messageText));
+ messageViewCaption.setText(messageId1);
+ messageViewContent.setText(deviceName);
messageView2.setText(messageId2);
mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
mPairingView.setFilters(new InputFilter[] {
@@ -219,33 +219,46 @@ public final class BluetoothPairingDialog extends AlertActivity implements
private View createView(CachedBluetoothDeviceManager deviceManager) {
View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_confirm, null);
- // Escape device name to avoid HTML injection.
+ // Escape device name to avoid HTML injection.
String name = Html.escapeHtml(deviceManager.getName(mDevice));
- TextView messageView = (TextView) view.findViewById(R.id.message);
-
- String messageText; // formatted string containing HTML style tags
+ TextView messageViewCaption = (TextView) view.findViewById(R.id.message_caption);
+ TextView messageViewContent = (TextView) view.findViewById(R.id.message_subhead);
+ TextView pairingViewCaption = (TextView) view.findViewById(R.id.pairing_caption);
+ TextView pairingViewContent = (TextView) view.findViewById(R.id.pairing_subhead);
+ TextView messagePairing = (TextView) view.findViewById(R.id.pairing_code_message);
+
+ String messageCaption = null;
+ String pairingContent = null;
switch (mType) {
+ case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
+ case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
- messageText = getString(R.string.bluetooth_confirm_passkey_msg,
- name, mPairingKey);
+ messageCaption = getString(R.string.bluetooth_enter_pin_msg);
+ pairingContent = mPairingKey;
break;
case BluetoothDevice.PAIRING_VARIANT_CONSENT:
case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
- messageText = getString(R.string.bluetooth_incoming_pairing_msg, name);
- break;
-
- case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
- case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
- messageText = getString(R.string.bluetooth_display_passkey_pin_msg, name,
- mPairingKey);
+ messageCaption = getString(R.string.bluetooth_enter_pin_msg);
break;
default:
Log.e(TAG, "Incorrect pairing type received, not creating view");
return null;
}
- messageView.setText(Html.fromHtml(messageText));
+
+ if (messageViewCaption != null) {
+ messageViewCaption.setText(messageCaption);
+ messageViewContent.setText(name);
+ }
+
+ if (pairingContent != null) {
+ pairingViewCaption.setVisibility(View.VISIBLE);
+ pairingViewContent.setVisibility(View.VISIBLE);
+ pairingViewContent.setText(pairingContent);
+ messagePairing.setVisibility(View.VISIBLE);
+ }
+
return view;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
index ea36fee..44198d3 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
@@ -90,7 +90,9 @@ public final class BluetoothPairingRequest extends BroadcastReceiver {
.setContentText(res.getString(R.string.bluetooth_notif_message, name))
.setContentIntent(pending)
.setAutoCancel(true)
- .setDefaults(Notification.DEFAULT_SOUND);
+ .setDefaults(Notification.DEFAULT_SOUND)
+ .setColor(res.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
NotificationManager manager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index c3b93be..1ede05b 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -122,17 +122,20 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
break;
}
Notification notification = new Notification.Builder(context)
- .setContentTitle(title)
- .setTicker(message)
- .setContentText(message)
- .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
- .setAutoCancel(true)
- .setPriority(Notification.PRIORITY_MAX)
- .setOnlyAlertOnce(false)
- .setDefaults(Notification.DEFAULT_ALL)
- .setContentIntent(PendingIntent.getActivity(context, 0, connectionAccessIntent, 0))
- .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0))
- .build();
+ .setContentTitle(title)
+ .setTicker(message)
+ .setContentText(message)
+ .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
+ .setAutoCancel(true)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setOnlyAlertOnce(false)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setContentIntent(PendingIntent.getActivity(context, 0,
+ connectionAccessIntent, 0))
+ .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0))
+ .setColor(context.getResources().getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .build();
notification.flags |= Notification.FLAG_NO_CLEAR; /* cannot be set with the builder */
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index f1125bc..ec288f3 100755
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -18,28 +18,39 @@ package com.android.settings.bluetooth;
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
+import android.app.Activity;
+import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.EditText;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Index;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.widget.SwitchBar;
@@ -58,19 +69,20 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
private static final int MENU_ID_SCAN = Menu.FIRST;
private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 2;
- private static final int MENU_ID_MESSAGE_ACCESS = Menu.FIRST + 3;
/* Private intent to show the list of received files */
private static final String BTOPP_ACTION_OPEN_RECEIVED_FILES =
"android.btopp.intent.action.OPEN_RECEIVED_FILES";
+ private static View mSettingsDialogView = null;
+
private BluetoothEnabler mBluetoothEnabler;
private PreferenceGroup mPairedDevicesCategory;
private PreferenceGroup mAvailableDevicesCategory;
private boolean mAvailableDevicesCategoryIsPresent;
- private boolean mActivityStarted;
+ private boolean mInitialScanStarted;
private TextView mEmptyView;
private SwitchBar mSwitchBar;
@@ -86,13 +98,14 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
- updateDeviceName();
+ updateDeviceName(context);
}
}
- private void updateDeviceName() {
+ private void updateDeviceName(Context context) {
if (mLocalAdapter.isEnabled() && mMyDevicePreference != null) {
- mMyDevicePreference.setTitle(mLocalAdapter.getName());
+ mMyDevicePreference.setSummary(context.getResources().getString(
+ R.string.bluetooth_is_visible_message, mLocalAdapter.getName()));
}
}
};
@@ -105,7 +118,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- mActivityStarted = (savedInstanceState == null); // don't auto start scan after rotation
+ mInitialScanStarted = (savedInstanceState != null); // don't auto start scan after rotation
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
getListView().setEmptyView(mEmptyView);
@@ -140,6 +153,9 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
}
super.onResume();
+ // Make the device visible to other devices.
+ mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
if (isUiRestricted()) {
setDeviceListGroup(getPreferenceScreen());
removeAllDevices();
@@ -149,11 +165,8 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
getActivity().registerReceiver(mReceiver, mIntentFilter);
if (mLocalAdapter != null) {
- updateContent(mLocalAdapter.getBluetoothState(), mActivityStarted);
+ updateContent(mLocalAdapter.getBluetoothState());
}
-
- // Make the device visible to other devices.
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
}
@Override
@@ -163,14 +176,14 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
mBluetoothEnabler.pause();
}
+ // Make the device only visible to connected devices.
+ mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+
if (isUiRestricted()) {
return;
}
getActivity().unregisterReceiver(mReceiver);
-
- // Make the device only visible to connected devices.
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
}
@Override
@@ -191,12 +204,6 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_SHOW_RECEIVED, 0, R.string.bluetooth_show_received_files)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- // Message Access API is still not finished, once completed we undo this check.
- // Bug 16232864
- if (android.os.SystemProperties.get("show_bluetooth_message_access").equals("true")){
- menu.add(Menu.NONE, MENU_ID_MESSAGE_ACCESS, 0, R.string.bluetooth_show_message_access)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- }
super.onCreateOptionsMenu(menu, inflater);
}
@@ -218,23 +225,28 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
getActivity().sendBroadcast(intent);
return true;
-
- case MENU_ID_MESSAGE_ACCESS:
- if (getActivity() instanceof SettingsActivity) {
- ((SettingsActivity) getActivity()).startPreferencePanel(
- MessageAccessSettings.class.getCanonicalName(), null,
- R.string.bluetooth_show_message_access, null, this, 0);
- }
- return true;
}
return super.onOptionsItemSelected(item);
}
private void startScanning() {
- if (isUiRestricted()) return;
+ if (isUiRestricted()) {
+ return;
+ }
+
if (!mAvailableDevicesCategoryIsPresent) {
getPreferenceScreen().addPreference(mAvailableDevicesCategory);
+ mAvailableDevicesCategoryIsPresent = true;
}
+
+ if (mAvailableDevicesCategory != null) {
+ setDeviceListGroup(mAvailableDevicesCategory);
+ removeAllDevices();
+ }
+
+ mLocalManager.getCachedDeviceManager().clearCachedDevices();
+ mAvailableDevicesCategory.removeAll();
+ mInitialScanStarted = true;
mLocalAdapter.startScanning(true);
}
@@ -245,16 +257,18 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
}
private void addDeviceCategory(PreferenceGroup preferenceGroup, int titleId,
- BluetoothDeviceFilter.Filter filter) {
+ BluetoothDeviceFilter.Filter filter, boolean addCachedDevices) {
preferenceGroup.setTitle(titleId);
getPreferenceScreen().addPreference(preferenceGroup);
setFilter(filter);
setDeviceListGroup(preferenceGroup);
- addCachedDevices();
+ if (addCachedDevices) {
+ addCachedDevices();
+ }
preferenceGroup.setEnabled(true);
}
- private void updateContent(int bluetoothState, boolean scanState) {
+ private void updateContent(int bluetoothState) {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
int messageId = 0;
@@ -277,9 +291,13 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
}
addDeviceCategory(mPairedDevicesCategory,
R.string.bluetooth_preference_paired_devices,
- BluetoothDeviceFilter.BONDED_DEVICE_FILTER);
+ BluetoothDeviceFilter.BONDED_DEVICE_FILTER, true);
int numberOfPairedDevices = mPairedDevicesCategory.getPreferenceCount();
+ if (isUiRestricted() || numberOfPairedDevices <= 0) {
+ preferenceScreen.removePreference(mPairedDevicesCategory);
+ }
+
// Available devices category
if (mAvailableDevicesCategory == null) {
mAvailableDevicesCategory = new BluetoothProgressCategory(getActivity());
@@ -289,30 +307,17 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
}
addDeviceCategory(mAvailableDevicesCategory,
R.string.bluetooth_preference_found_devices,
- BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER);
+ BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted);
int numberOfAvailableDevices = mAvailableDevicesCategory.getPreferenceCount();
- mAvailableDevicesCategoryIsPresent = true;
-
- if (numberOfAvailableDevices == 0) {
- preferenceScreen.removePreference(mAvailableDevicesCategory);
- mAvailableDevicesCategoryIsPresent = false;
- }
- if (numberOfPairedDevices == 0) {
- preferenceScreen.removePreference(mPairedDevicesCategory);
- if (scanState == true) {
- mActivityStarted = false;
- startScanning();
- } else {
- if (!mAvailableDevicesCategoryIsPresent) {
- getPreferenceScreen().addPreference(mAvailableDevicesCategory);
- }
- }
+ if (!mInitialScanStarted) {
+ startScanning();
}
if (mMyDevicePreference == null) {
mMyDevicePreference = new Preference(getActivity());
}
+
mMyDevicePreference.setSummary(getResources().getString(
R.string.bluetooth_is_visible_message, mLocalAdapter.getName()));
mMyDevicePreference.setSelectable(false);
@@ -349,7 +354,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
@Override
public void onBluetoothStateChanged(int bluetoothState) {
super.onBluetoothStateChanged(bluetoothState);
- updateContent(bluetoothState, true);
+ updateContent(bluetoothState);
}
@Override
@@ -361,30 +366,69 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
}
}
- @Override
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
setDeviceListGroup(getPreferenceScreen());
removeAllDevices();
- updateContent(mLocalAdapter.getBluetoothState(), false);
+ updateContent(mLocalAdapter.getBluetoothState());
}
private final View.OnClickListener mDeviceProfilesListener = new View.OnClickListener() {
public void onClick(View v) {
// User clicked on advanced options icon for a device in the list
- if (v.getTag() instanceof CachedBluetoothDevice) {
- if (isUiRestricted()) return;
-
- CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
+ if (!(v.getTag() instanceof CachedBluetoothDevice)) {
+ Log.w(TAG, "onClick() called for other View: " + v);
+ return;
+ }
- Bundle args = new Bundle(1);
- args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
+ final CachedBluetoothDevice device = (CachedBluetoothDevice) v.getTag();
+ final Activity activity = getActivity();
+ DeviceProfilesSettings profileFrag = (DeviceProfilesSettings)activity.
+ getFragmentManager().findFragmentById(R.id.bluetooth_fragment_settings);
- ((SettingsActivity) getActivity()).startPreferencePanel(
- DeviceProfilesSettings.class.getName(), args,
- R.string.bluetooth_device_advanced_title, null, null, 0);
- } else {
- Log.w(TAG, "onClick() called for other View: " + v); // TODO remove
+ if (mSettingsDialogView != null){
+ ViewGroup parent = (ViewGroup) mSettingsDialogView.getParent();
+ if (parent != null) {
+ parent.removeView(mSettingsDialogView);
+ }
}
+ if (profileFrag == null) {
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ mSettingsDialogView = inflater.inflate(R.layout.bluetooth_device_settings, null);
+ profileFrag = (DeviceProfilesSettings)activity.getFragmentManager()
+ .findFragmentById(R.id.bluetooth_fragment_settings);
+ }
+
+ final View dialogLayout = mSettingsDialogView;
+ AlertDialog.Builder settingsDialog = new AlertDialog.Builder(activity);
+ profileFrag.setDevice(device);
+ final EditText deviceName = (EditText)dialogLayout.findViewById(R.id.name);
+ deviceName.setText(device.getName(), TextView.BufferType.EDITABLE);
+ settingsDialog.setView(dialogLayout);
+ settingsDialog.setTitle(R.string.bluetooth_preference_paired_devices);
+ settingsDialog.setPositiveButton(R.string.okay,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ EditText deviceName = (EditText)dialogLayout.findViewById(R.id.name);
+ device.setName(deviceName.getText().toString());
+ }
+ });
+ final Context context = v.getContext();
+ settingsDialog.setNegativeButton(R.string.forget,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ device.unpair();
+ com.android.settings.bluetooth.Utils.updateSearchIndex(activity,
+ BluetoothSettings.class.getName(), device.getName(),
+ context.getResources().getString(R.string.bluetooth_settings),
+ R.drawable.ic_settings_bluetooth2, false);
+ }
+ });
+
+ AlertDialog dialog = settingsDialog.create();
+ dialog.create();
+ dialog.show();
}
};
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
index a7104df..3b64ade 100755
--- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
@@ -539,7 +539,7 @@ final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
if (bondState == BluetoothDevice.BOND_NONE) {
mProfiles.clear();
mConnectAfterPairing = false; // cancel auto-connect
- setPhonebookPermissionChoice(ACCESS_ALLOWED);
+ setPhonebookPermissionChoice(ACCESS_UNKNOWN);
setMessagePermissionChoice(ACCESS_UNKNOWN);
mPhonebookRejectedTimes = 0;
savePhonebookRejectTimes();
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java b/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java
index ff282cc..0b53b1a 100755
--- a/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDeviceManager.java
@@ -86,7 +86,9 @@ final class CachedBluetoothDeviceManager {
BluetoothDevice device) {
CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
profileManager, device);
- mCachedDevices.add(newDevice);
+ synchronized (mCachedDevices) {
+ mCachedDevices.add(newDevice);
+ }
return newDevice;
}
@@ -110,6 +112,10 @@ final class CachedBluetoothDeviceManager {
return device.getAddress();
}
+ public synchronized void clearCachedDevices() {
+ mCachedDevices.clear();
+ }
+
public synchronized void onScanningStateChanged(boolean started) {
if (!started) return;
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
index f482ecd..e7208b5 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
@@ -167,6 +167,12 @@ public abstract class DeviceListPreferenceFragment extends
}
void createDevicePreference(CachedBluetoothDevice cachedDevice) {
+ if (mDeviceListGroup == null) {
+ Log.w(TAG, "Trying to create a device preference before the list group/category "
+ + "exists!");
+ return;
+ }
+
BluetoothDevicePreference preference = new BluetoothDevicePreference(
getActivity(), cachedDevice);
diff --git a/src/com/android/settings/bluetooth/DeviceProfilesSettings.java b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
index fb7668f..64c807f 100755
--- a/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
+++ b/src/com/android/settings/bluetooth/DeviceProfilesSettings.java
@@ -17,6 +17,7 @@
package com.android.settings.bluetooth;
import android.app.AlertDialog;
+import android.app.Fragment;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -36,6 +37,7 @@ import android.text.TextWatcher;
import android.app.Dialog;
import android.widget.Button;
import android.text.Editable;
+
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.Index;
@@ -52,15 +54,12 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
implements CachedBluetoothDevice.Callback, Preference.OnPreferenceChangeListener {
private static final String TAG = "DeviceProfilesSettings";
- private static final String KEY_RENAME_DEVICE = "rename_device";
private static final String KEY_PROFILE_CONTAINER = "profile_container";
private static final String KEY_UNPAIR = "unpair";
private static final String KEY_PBAP_SERVER = "PBAP Server";
- public static final String EXTRA_DEVICE = "device";
- private RenameEditTextPreference mRenameDeviceNamePref;
- private LocalBluetoothManager mManager;
private CachedBluetoothDevice mCachedDevice;
+ private LocalBluetoothManager mManager;
private LocalBluetoothProfileManager mProfileManager;
private PreferenceGroup mProfileContainer;
@@ -72,66 +71,18 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
private AlertDialog mDisconnectDialog;
private boolean mProfileGroupIsRemoved;
- private class RenameEditTextPreference implements TextWatcher{
- public void afterTextChanged(Editable s) {
- Dialog d = mDeviceNamePref.getDialog();
- if (d instanceof AlertDialog) {
- ((AlertDialog) d).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(s.length() > 0);
- }
- }
-
- // TextWatcher interface
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // not used
- }
-
- // TextWatcher interface
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- // not used
- }
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- BluetoothDevice device;
- if (savedInstanceState != null) {
- device = savedInstanceState.getParcelable(EXTRA_DEVICE);
- } else {
- Bundle args = getArguments();
- device = args.getParcelable(EXTRA_DEVICE);
- }
-
addPreferencesFromResource(R.xml.bluetooth_device_advanced);
getPreferenceScreen().setOrderingAsAdded(false);
mProfileContainer = (PreferenceGroup) findPreference(KEY_PROFILE_CONTAINER);
- mDeviceNamePref = (EditTextPreference) findPreference(KEY_RENAME_DEVICE);
- if (device == null) {
- Log.w(TAG, "Activity started without a remote Bluetooth device");
- finish();
- return; // TODO: test this failure path
- }
- mRenameDeviceNamePref = new RenameEditTextPreference();
mManager = LocalBluetoothManager.getInstance(getActivity());
CachedBluetoothDeviceManager deviceManager =
mManager.getCachedDeviceManager();
mProfileManager = mManager.getProfileManager();
- mCachedDevice = deviceManager.findDevice(device);
- if (mCachedDevice == null) {
- Log.w(TAG, "Device not found, cannot connect to it");
- finish();
- return; // TODO: test this failure path
- }
-
- String deviceName = mCachedDevice.getName();
- mDeviceNamePref.setSummary(deviceName);
- mDeviceNamePref.setText(deviceName);
- mDeviceNamePref.setOnPreferenceChangeListener(this);
-
- // Add a preference for each profile
- addPreferencesForProfiles();
}
@Override
@@ -141,12 +92,14 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
mDisconnectDialog.dismiss();
mDisconnectDialog = null;
}
+ if (mCachedDevice != null) {
+ mCachedDevice.unregisterCallback(this);
+ }
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putParcelable(EXTRA_DEVICE, mCachedDevice.getDevice());
}
@Override
@@ -154,18 +107,13 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
super.onResume();
mManager.setForegroundActivity(getActivity());
- mCachedDevice.registerCallback(this);
- if(mCachedDevice.getBondState() == BluetoothDevice.BOND_NONE)
- finish();
- refresh();
- EditText et = mDeviceNamePref.getEditText();
- if (et != null) {
- et.addTextChangedListener(mRenameDeviceNamePref);
- Dialog d = mDeviceNamePref.getDialog();
- if (d instanceof AlertDialog) {
- Button b = ((AlertDialog) d).getButton(AlertDialog.BUTTON_POSITIVE);
- b.setEnabled(et.getText().length() > 0);
+ if (mCachedDevice != null) {
+ mCachedDevice.registerCallback(this);
+ if (mCachedDevice.getBondState() == BluetoothDevice.BOND_NONE) {
+ finish();
+ return;
}
+ refresh();
}
}
@@ -173,11 +121,25 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
public void onPause() {
super.onPause();
- mCachedDevice.unregisterCallback(this);
+ if (mCachedDevice != null) {
+ mCachedDevice.unregisterCallback(this);
+ }
+
mManager.setForegroundActivity(null);
}
+ public void setDevice(CachedBluetoothDevice cachedDevice) {
+ mCachedDevice = cachedDevice;
+
+ mCachedDevice.registerCallback(this);
+ if (isResumed()) {
+ addPreferencesForProfiles();
+ refresh();
+ }
+ }
+
private void addPreferencesForProfiles() {
+ mProfileContainer.removeAll();
for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
Preference pref = createProfilePreference(profile);
mProfileContainer.addPreference(pref);
@@ -238,28 +200,6 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
return pref;
}
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
- String key = preference.getKey();
- if (key.equals(KEY_UNPAIR)) {
- unpairDevice();
- finish();
- final Context context = preference.getContext();
-
- SearchIndexableRaw data = new SearchIndexableRaw(context);
- data.className = BluetoothSettings.class.getName();
- data.title = mCachedDevice.getName();
- data.screenTitle = context.getResources().getString(R.string.bluetooth_settings);
- data.iconResId = R.drawable.ic_settings_bluetooth2;
- data.enabled = false;
-
- Index.getInstance(context).updateFromSearchIndexableData(data);
- return true;
- }
-
- return super.onPreferenceTreeClick(screen, preference);
- }
-
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mDeviceNamePref) {
mCachedDevice.setName((String) newValue);
@@ -331,14 +271,16 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
}
+ @Override
public void onDeviceAttributesChanged() {
refresh();
}
private void refresh() {
- String deviceName = mCachedDevice.getName();
- mDeviceNamePref.setSummary(deviceName);
- mDeviceNamePref.setText(deviceName);
+ final EditText deviceNameField = (EditText) getView().findViewById(R.id.name);
+ if (deviceNameField != null) {
+ deviceNameField.setText(mCachedDevice.getName());
+ }
refreshProfiles();
}
@@ -391,8 +333,4 @@ public final class DeviceProfilesSettings extends SettingsPreferenceFragment
private int getProfilePreferenceIndex(int profIndex) {
return mProfileContainer.getOrder() + profIndex * 10;
}
-
- private void unpairDevice() {
- mCachedDevice.unpair();
- }
}
diff --git a/src/com/android/settings/bluetooth/MessageAccessSettings.java b/src/com/android/settings/bluetooth/MessageAccessSettings.java
deleted file mode 100644
index 913357c..0000000
--- a/src/com/android/settings/bluetooth/MessageAccessSettings.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.bluetooth;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.ActivityManagerNative;
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.preference.SwitchPreference;
-import android.preference.Preference;
-import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
-import android.provider.SearchIndexableResource;
-import android.util.Log;
-
-import com.android.settings.accounts.AuthenticatorHelper;
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MessageAccessSettings extends SettingsPreferenceFragment
- implements AuthenticatorHelper.OnAccountsUpdateListener, Indexable {
- private static final String TAG = "MessageAccessSettings";
- private static final String GMAIL_PACKAGE_NAME = "com.google.android.gm";
- private static final String EMAIL_PACKAGE_NAME = "com.google.android.email";
-
- private Account[] mAccounts;
- private UserHandle mUserHandle;
- private PreferenceGroup mAvailableAccounts;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // TODO: Define behavior for managed profile. See: http://b/16287773
- mUserHandle = new UserHandle(UserHandle.myUserId());
-
- addPreferencesFromResource(R.xml.bluetooth_message_access);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- initPreferences();
- }
-
- @Override
- public void onAccountsUpdate(final UserHandle userHandle) {
- mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
- mUserHandle.getIdentifier());
-
- final int mAccountsSize = mAccounts.length;
- for (int i = 0; i < mAccountsSize; ++i){
- Log.d(TAG, String.format("account.type = %s\n", mAccounts[i].type));
- }
- }
-
- /**
- * Retrieves the email icon for a given account's email preference
- *
- * @param accountPref The user's account to retrieve the icon from.
- *
- * @return The drawable representing the icon of the user's email preference
- **/
- private Drawable getIcon(AccountPreference accountPref){
- Drawable icon = null;
-
- // Currently only two types of icons are allowed.
- final String packageName = accountPref.account.type.equals("com.google")
- ? GMAIL_PACKAGE_NAME : EMAIL_PACKAGE_NAME;
-
- try{
- icon = getPackageManager().getApplicationIcon(packageName);
- }catch(NameNotFoundException nnfe){
- icon = null;
- }
-
- return icon;
- }
-
- private void initPreferences() {
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- mAvailableAccounts = (PreferenceGroup)preferenceScreen.findPreference("accounts");
- mAccounts = AccountManager.get(getActivity()).getAccountsAsUser(
- mUserHandle.getIdentifier());
-
- final int mAccountsSize = mAccounts.length;
- for (int i = 0; i < mAccountsSize; ++i){
- AccountPreference accountPref = new AccountPreference(getActivity(), mAccounts[i]);
- Drawable icon = getIcon(accountPref);
- if (icon != null){
- accountPref.setIcon(icon);
- }
- mAvailableAccounts.addPreference(accountPref);
- }
- }
-
- private class AccountPreference extends SwitchPreference
- implements Preference.OnPreferenceChangeListener{
- private Account account;
-
- AccountPreference(Context context, Account account){
- super(context);
- this.account = account;
- setTitle(account.type);
- setSummary(account.name);
-
- setOnPreferenceChangeListener(this);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object val) {
- if (preference instanceof AccountPreference){
- final AccountPreference accountPref = (AccountPreference) preference;
-
- if (((Boolean)val).booleanValue()){
- // Enable paired deviced to connect, fill in once API is available
- Log.w(TAG, String.format(
- "User has turned on '%s' for Bluetooth message access.",
- accountPref.account.name));
- } else {
- // Disable paired deviced to connect, fill in once API is available
- Log.w(TAG, String.format(
- "User has turned off '%s' for Bluetooth message access.",
- accountPref.account.name));
- }
- }
- return true;
- }
- }
-
- public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableResource> getXmlResourcesToIndex(
- Context context, boolean enabled) {
- List<SearchIndexableResource> indexables = new ArrayList<SearchIndexableResource>();
- SearchIndexableResource indexable = new SearchIndexableResource(context);
- indexable.xmlResId = R.xml.bluetooth_message_access;
- indexables.add(indexable);
- return indexables;
- }
- };
-}
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index 1970400..e9230de 100755
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -24,6 +24,8 @@ import android.content.DialogInterface;
import android.widget.Toast;
import com.android.settings.R;
+import com.android.settings.search.Index;
+import com.android.settings.search.SearchIndexableRaw;
/**
* Utils is a helper class that contains constants for various
@@ -101,4 +103,19 @@ final class Utils {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}
+
+ /**
+ * Update the search Index for a specific class name and resources.
+ */
+ public static void updateSearchIndex(Context context, String className, String title,
+ String screenTitle, int iconResId, boolean enabled) {
+ SearchIndexableRaw data = new SearchIndexableRaw(context);
+ data.className = className;
+ data.title = title;
+ data.screenTitle = screenTitle;
+ data.iconResId = iconResId;
+ data.enabled = enabled;
+
+ Index.getInstance(context).updateFromSearchIndexableData(data);
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 92eaade..4ff4dfd 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -16,15 +16,20 @@
package com.android.settings.fuelgauge;
+import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Handler;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
import com.android.internal.os.BatterySipper;
import com.android.settings.R;
@@ -256,9 +261,17 @@ public class BatteryEntry {
System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
// Convert package names to user-facing labels where possible
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ final int userId = UserHandle.getUserId(uid);
for (int i = 0; i < packageLabels.length; i++) {
try {
- ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
+ final ApplicationInfo ai = ipm.getApplicationInfo(packageLabels[i],
+ 0 /* no flags */, userId);
+ if (ai == null) {
+ Log.d(PowerUsageSummary.TAG, "Retrieving null app info for package "
+ + packageLabels[i] + ", user " + userId);
+ continue;
+ }
CharSequence label = ai.loadLabel(pm);
if (label != null) {
packageLabels[i] = label.toString();
@@ -268,10 +281,14 @@ public class BatteryEntry {
icon = ai.loadIcon(pm);
break;
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
+ Log.d(PowerUsageSummary.TAG, "Error while retrieving app info for package "
+ + packageLabels[i] + ", user " + userId, e);
}
}
- if (icon == null) icon = defaultActivityIcon;
+ if (icon == null) {
+ icon = defaultActivityIcon;
+ }
if (packageLabels.length == 1) {
name = packageLabels[0];
@@ -279,7 +296,12 @@ public class BatteryEntry {
// Look for an official name for this UID.
for (String pkgName : sipper.mPackages) {
try {
- final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
+ final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId);
+ if (pi == null) {
+ Log.d(PowerUsageSummary.TAG, "Retrieving null package info for package "
+ + pkgName + ", user " + userId);
+ continue;
+ }
if (pi.sharedUserLabel != 0) {
final CharSequence nm = pm.getText(pkgName,
pi.sharedUserLabel, pi.applicationInfo);
@@ -292,7 +314,9 @@ public class BatteryEntry {
break;
}
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
+ Log.d(PowerUsageSummary.TAG, "Error while retrieving package info for package "
+ + pkgName + ", user " + userId, e);
}
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index d88c516..9d3edd5 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -86,7 +86,7 @@ public class BatteryHistoryChart extends View {
void addTick(int x, int bin) {
if (bin != mLastBin && mNumTicks < mTicks.length) {
- mTicks[mNumTicks] = x | bin << CHART_DATA_BIN_SHIFT;
+ mTicks[mNumTicks] = (x&CHART_DATA_X_MASK) | (bin<<CHART_DATA_BIN_SHIFT);
mNumTicks++;
mLastBin = bin;
}
@@ -540,6 +540,7 @@ public class BatteryHistoryChart extends View {
}
mDrainString = "";
mChargeDurationString = "";
+ setContentDescription(mChargeLabelString);
int pos = 0;
int lastInteresting = 0;
@@ -804,6 +805,9 @@ public class BatteryHistoryChart extends View {
}
if (curWalltime != 0 && rec.isDeltaData()) {
x = mLevelLeft + (int)(((curWalltime-walltimeStart)*levelWidth)/walltimeChange);
+ if (x < 0) {
+ x = 0;
+ }
if (false) {
StringBuilder sb = new StringBuilder(128);
sb.append("walloff=");
@@ -984,6 +988,9 @@ public class BatteryHistoryChart extends View {
} else {
// Figure out where the actual data ends on the screen.
x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange);
+ if (x < 0) {
+ x = 0;
+ }
}
finishPaths(x, h, levelh, startX, lastY, curLevelPath, lastX,
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java b/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
index 248d471..63e4e13 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
@@ -18,31 +18,27 @@ package com.android.settings.fuelgauge;
import android.app.Fragment;
import android.content.Intent;
+import android.os.BatteryStats;
import android.os.Bundle;
-import android.os.Parcel;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
public class BatteryHistoryDetail extends Fragment {
public static final String EXTRA_STATS = "stats";
public static final String EXTRA_BROADCAST = "broadcast";
- private BatteryStatsImpl mStats;
+ private BatteryStats mStats;
private Intent mBatteryBroadcast;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- byte[] data = getArguments().getByteArray(EXTRA_STATS);
- Parcel parcel = Parcel.obtain();
- parcel.unmarshall(data, 0, data.length);
- parcel.setDataPosition(0);
- mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
- .createFromParcel(parcel);
+ String histFile = getArguments().getString(EXTRA_STATS);
+ mStats = BatteryStatsHelper.statsFromFile(getActivity(), histFile);
mBatteryBroadcast = getArguments().getParcelable(EXTRA_BROADCAST);
}
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 300b98f..e7326b1 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -47,8 +47,6 @@ public class BatteryHistoryPreference extends Preference {
setLayoutResource(R.layout.preference_batteryhistory);
mStats = stats;
mBatteryBroadcast = batteryBroadcast;
- // Make it non selectable
- setSelectable(false);
}
BatteryStats getStats() {
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index 990b654..a558533 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -34,12 +34,15 @@ public class PowerGaugePreference extends Preference {
private BatteryEntry mInfo;
private int mProgress;
private CharSequence mProgressText;
+ private final CharSequence mContentDescription;
- public PowerGaugePreference(Context context, Drawable icon, BatteryEntry info) {
+ public PowerGaugePreference(Context context, Drawable icon, CharSequence contentDescription,
+ BatteryEntry info) {
super(context);
setLayoutResource(R.layout.preference_app_percentage);
setIcon(icon != null ? icon : new ColorDrawable(0));
mInfo = info;
+ mContentDescription = contentDescription;
}
public void setPercent(double percentOfMax, double percentOfTotal) {
@@ -62,5 +65,10 @@ public class PowerGaugePreference extends Preference {
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
text1.setText(mProgressText);
+
+ if (mContentDescription != null) {
+ final TextView titleView = (TextView) view.findViewById(android.R.id.title);
+ titleView.setContentDescription(mContentDescription);
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 3ce2ac0..5325ed3 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -21,11 +21,11 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.Parcel;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
@@ -45,8 +45,6 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import java.util.List;
-import java.util.ArrayList;
-import java.util.Collections;
/**
* Displays a list of apps and subsystems that consume power, ordered by how much power was
@@ -56,10 +54,12 @@ public class PowerUsageSummary extends PreferenceFragment {
private static final boolean DEBUG = false;
- private static final String TAG = "PowerUsageSummary";
+ static final String TAG = "PowerUsageSummary";
private static final String KEY_APP_LIST = "app_list";
+ private static final String BATTERY_HISTORY_FILE = "tmp_bat_history.bin";
+
private static final int MENU_STATS_TYPE = Menu.FIRST;
private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
private static final int MENU_BATTERY_SAVER = Menu.FIRST + 2;
@@ -113,8 +113,15 @@ public class PowerUsageSummary extends PreferenceFragment {
}
@Override
+ public void onStart() {
+ super.onStart();
+ mStatsHelper.clearStats();
+ }
+
+ @Override
public void onResume() {
super.onResume();
+ BatteryStatsHelper.dropFile(getActivity(), BATTERY_HISTORY_FILE);
updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
if (mHandler.hasMessages(MSG_REFRESH_STATS)) {
@@ -150,11 +157,9 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference instanceof BatteryHistoryPreference) {
- Parcel hist = Parcel.obtain();
- mStatsHelper.getStats().writeToParcelWithoutUids(hist, 0);
- byte[] histData = hist.marshall();
+ mStatsHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
- args.putByteArray(BatteryHistoryDetail.EXTRA_STATS, histData);
+ args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
mStatsHelper.getBatteryBroadcast());
SettingsActivity sa = (SettingsActivity) getActivity();
@@ -251,7 +256,8 @@ public class PowerUsageSummary extends PreferenceFragment {
mAppListGroup.addPreference(mHistPref);
boolean addedSome = false;
- PowerProfile powerProfile = mStatsHelper.getPowerProfile();
+ final PowerProfile powerProfile = mStatsHelper.getPowerProfile();
+ final BatteryStats stats = mStatsHelper.getStats();
final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP) {
final List<UserHandle> profiles = mUm.getUserProfiles();
@@ -260,7 +266,7 @@ public class PowerUsageSummary extends PreferenceFragment {
final List<BatterySipper> usageList = mStatsHelper.getUsageList();
- final int dischargeAmount = mStatsHelper.getStats().getDischargeAmount(mStatsType);
+ final int dischargeAmount = stats != null ? stats.getDischargeAmount(mStatsType) : 0;
final int numSippers = usageList.size();
for (int i = 0; i < numSippers; i++) {
final BatterySipper sipper = usageList.get(i);
@@ -294,8 +300,12 @@ public class PowerUsageSummary extends PreferenceFragment {
}
final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid()));
final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
+ final Drawable badgedIcon = mUm.getBadgedIconForUser(entry.getIcon(),
+ userHandle);
+ final CharSequence contentDescription = mUm.getBadgedLabelForUser(entry.getLabel(),
+ userHandle);
final PowerGaugePreference pref = new PowerGaugePreference(getActivity(),
- mUm.getBadgedDrawableForUser(entry.getIcon(), userHandle), entry);
+ badgedIcon, contentDescription, entry);
final double percentOfMax = (sipper.value * 100) / mStatsHelper.getMaxPower();
sipper.percent = percentOfTotal;
@@ -334,7 +344,7 @@ public class PowerUsageSummary extends PreferenceFragment {
if (pgp != null) {
final int userId = UserHandle.getUserId(entry.sipper.getUid());
final UserHandle userHandle = new UserHandle(userId);
- pgp.setIcon(mUm.getBadgedDrawableForUser(entry.getIcon(), userHandle));
+ pgp.setIcon(mUm.getBadgedIconForUser(entry.getIcon(), userHandle));
pgp.setTitle(entry.name);
}
break;
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
index 1601cd0..e1bcac5 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java
@@ -18,6 +18,7 @@ package com.android.settings.inputmethod;
import android.app.Activity;
import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -34,6 +35,7 @@ import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
import android.os.Handler;
+import android.os.UserHandle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
@@ -80,7 +82,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
InputMethodPreference.OnSavePreferenceListener {
private static final String KEY_SPELL_CHECKERS = "spellcheckers_settings";
private static final String KEY_PHONE_LANGUAGE = "phone_language";
- private static final String KEY_CHOOSE_INPUT_METHODS = "choose_input_methods";
private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector";
private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings";
@@ -88,14 +89,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
// false: on ICS or later
private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false;
- private static final String[] sSystemSettingNames = {
- System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE,
- };
-
- private static final String[] sHardKeyboardKeys = {
- "auto_replace", "auto_caps", "auto_punctuate",
- };
-
private int mDefaultInputMethodSelectorVisibility = 0;
private ListPreference mShowInputMethodSelectorPref;
private PreferenceCategory mKeyboardSettingsCategory;
@@ -111,6 +104,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
private SettingsObserver mSettingsObserver;
private Intent mIntentWaitingForResult;
private InputMethodSettingValuesWrapper mInputMethodSettingValues;
+ private DevicePolicyManager mDpm;
@Override
public void onCreate(Bundle icicle) {
@@ -162,14 +156,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
}
mKeyboardSettingsCategory.removeAll();
getPreferenceScreen().addPreference(mKeyboardSettingsCategory);
- } else {
- final Preference pref = findPreference(KEY_CHOOSE_INPUT_METHODS);
- final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
- intent.setClass(activity, SubSettings.class);
- intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, getClass().getName());
- intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID,
- R.string.choose_input_methods);
- pref.setIntent(intent);
}
// Build hard keyboard and game controller preference categories.
@@ -192,6 +178,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
mHandler = new Handler();
mSettingsObserver = new SettingsObserver(mHandler, activity);
+ mDpm = (DevicePolicyManager) (getActivity().
+ getSystemService(Context.DEVICE_POLICY_SERVICE));
}
private void updateInputMethodSelectorSummary(int value) {
@@ -274,16 +262,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
}
}
- // Hard keyboard
- if (!mHardKeyboardPreferenceList.isEmpty()) {
- for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
- CheckBoxPreference chkPref = (CheckBoxPreference)
- mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]);
- chkPref.setChecked(
- System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0);
- }
- }
-
updateInputDevices();
// Refresh internal states in mInputMethodSettingValues to keep the latest
@@ -339,15 +317,6 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
}
} else if (preference instanceof CheckBoxPreference) {
final CheckBoxPreference chkPref = (CheckBoxPreference) preference;
- if (!mHardKeyboardPreferenceList.isEmpty()) {
- for (int i = 0; i < sHardKeyboardKeys.length; ++i) {
- if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) {
- System.putInt(getContentResolver(), sSystemSettingNames[i],
- chkPref.isChecked() ? 1 : 0);
- return true;
- }
- }
- }
if (chkPref == mGameControllerCategory.findPreference("vibrate_input_devices")) {
System.putInt(getContentResolver(), Settings.System.VIBRATE_INPUT_DEVICES,
chkPref.isChecked() ? 1 : 0);
@@ -366,16 +335,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
// and want to pretend that the language is valid for all locales.
// We need a way to support languages that aren't tied to a particular
// locale instead of hiding the locale qualifier.
- if (language.equals("zz")) {
- String country = conf.locale.getCountry();
- if (country.equals("ZZ")) {
- localeName = "[Developer] Accented English (zz_ZZ)";
- } else if (country.equals("ZY")) {
- localeName = "[Developer] Fake Bi-Directional (zz_ZY)";
- } else {
- localeName = "";
- }
- } else if (hasOnlyOneLanguageInstance(language,
+ if (hasOnlyOneLanguageInstance(language,
Resources.getSystem().getAssets().getLocales())) {
localeName = conf.locale.getDisplayLanguage(conf.locale);
} else {
@@ -439,6 +399,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
mKeyboardSettingsCategory.removePreference(pref);
}
mInputMethodPreferenceList.clear();
+ List<String> permittedList = mDpm.getPermittedInputMethodsForCurrentUser();
final Context context = getActivity();
final List<InputMethodInfo> imis = mShowsOnlyFullImeAndKeyboardList
? mInputMethodSettingValues.getInputMethodList()
@@ -446,8 +407,11 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
final int N = (imis == null ? 0 : imis.size());
for (int i = 0; i < N; ++i) {
final InputMethodInfo imi = imis.get(i);
+ final boolean isAllowedByOrganization = permittedList == null
+ || permittedList.contains(imi.getPackageName());
final InputMethodPreference pref = new InputMethodPreference(
- context, imi, mShowsOnlyFullImeAndKeyboardList /* hasSwitch */, this);
+ context, imi, mShowsOnlyFullImeAndKeyboardList /* hasSwitch */,
+ isAllowedByOrganization, this);
mInputMethodPreferenceList.add(pref);
}
final Collator collator = Collator.getInstance();
@@ -564,35 +528,33 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
private void updateHardKeyboards() {
mHardKeyboardPreferenceList.clear();
- if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY) {
- final int[] devices = InputDevice.getDeviceIds();
- for (int i = 0; i < devices.length; i++) {
- InputDevice device = InputDevice.getDevice(devices[i]);
- if (device != null
- && !device.isVirtual()
- && device.isFullKeyboard()) {
- final InputDeviceIdentifier identifier = device.getIdentifier();
- final String keyboardLayoutDescriptor =
- mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
- final KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
- mIm.getKeyboardLayout(keyboardLayoutDescriptor) : null;
-
- final PreferenceScreen pref = new PreferenceScreen(getActivity(), null);
- pref.setTitle(device.getName());
- if (keyboardLayout != null) {
- pref.setSummary(keyboardLayout.toString());
- } else {
- pref.setSummary(R.string.keyboard_layout_default_label);
- }
- pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- showKeyboardLayoutDialog(identifier);
- return true;
- }
- });
- mHardKeyboardPreferenceList.add(pref);
+ final int[] devices = InputDevice.getDeviceIds();
+ for (int i = 0; i < devices.length; i++) {
+ InputDevice device = InputDevice.getDevice(devices[i]);
+ if (device != null
+ && !device.isVirtual()
+ && device.isFullKeyboard()) {
+ final InputDeviceIdentifier identifier = device.getIdentifier();
+ final String keyboardLayoutDescriptor =
+ mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
+ final KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
+ mIm.getKeyboardLayout(keyboardLayoutDescriptor) : null;
+
+ final PreferenceScreen pref = new PreferenceScreen(getActivity(), null);
+ pref.setTitle(device.getName());
+ if (keyboardLayout != null) {
+ pref.setSummary(keyboardLayout.toString());
+ } else {
+ pref.setSummary(R.string.keyboard_layout_default_label);
}
+ pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ showKeyboardLayoutDialog(identifier);
+ return true;
+ }
+ });
+ mHardKeyboardPreferenceList.add(pref);
}
}
@@ -702,8 +664,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
List<SearchIndexableRaw> indexables = new ArrayList<>();
- Resources resources = context.getResources();
- String screenTitle = context.getString(R.string.language_keyboard_settings_title);
+ final Resources resources = context.getResources();
+ final String screenTitle = context.getString(R.string.language_keyboard_settings_title);
// Locale picker.
if (context.getAssets().getLocales().length > 1) {
@@ -795,116 +757,55 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
// Hard keyboards
InputManager inputManager = (InputManager) context.getSystemService(
Context.INPUT_SERVICE);
- if (resources.getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY) {
- boolean hasHardKeyboards = false;
-
- final int[] devices = InputDevice.getDeviceIds();
- for (int i = 0; i < devices.length; i++) {
- InputDevice device = InputDevice.getDevice(devices[i]);
- if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
- continue;
- }
-
- hasHardKeyboards = true;
-
- InputDeviceIdentifier identifier = device.getIdentifier();
- String keyboardLayoutDescriptor =
- inputManager.getCurrentKeyboardLayoutForInputDevice(identifier);
- KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
- inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
-
- String summary;
- if (keyboardLayout != null) {
- summary = keyboardLayout.toString();
- } else {
- summary = context.getString(R.string.keyboard_layout_default_label);
- }
+ boolean hasHardKeyboards = false;
- indexable = new SearchIndexableRaw(context);
- indexable.key = device.getName();
- indexable.title = device.getName();
- indexable.summaryOn = summary;
- indexable.summaryOff = summary;
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
+ final int[] devices = InputDevice.getDeviceIds();
+ for (int i = 0; i < devices.length; i++) {
+ InputDevice device = InputDevice.getDevice(devices[i]);
+ if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
+ continue;
}
- if (hasHardKeyboards) {
- // Hard keyboard category.
- indexable = new SearchIndexableRaw(context);
- indexable.key = "builtin_keyboard_settings";
- indexable.title = context.getString(
- R.string.builtin_keyboard_settings_title);
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
-
- // Auto replace.
- indexable = new SearchIndexableRaw(context);
- indexable.key = "auto_replace";
- indexable.title = context.getString(R.string.auto_replace);
- indexable.summaryOn = context.getString(R.string.auto_replace_summary);
- indexable.summaryOff = context.getString(R.string.auto_replace_summary);
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
-
- // Auto caps.
- indexable = new SearchIndexableRaw(context);
- indexable.key = "auto_caps";
- indexable.title = context.getString(R.string.auto_caps);
- indexable.summaryOn = context.getString(R.string.auto_caps_summary);
- indexable.summaryOff = context.getString(R.string.auto_caps_summary);
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
-
- // Auto punctuate.
- indexable = new SearchIndexableRaw(context);
- indexable.key = "auto_punctuate";
- indexable.title = context.getString(R.string.auto_punctuate);
- indexable.summaryOn = context.getString(R.string.auto_punctuate_summary);
- indexable.summaryOff = context.getString(R.string.auto_punctuate_summary);
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
- }
- }
+ hasHardKeyboards = true;
- // Voice recognizers.
- List<ResolveInfo> recognizers = context.getPackageManager()
- .queryIntentServices(new Intent(RecognitionService.SERVICE_INTERFACE),
- PackageManager.GET_META_DATA);
+ InputDeviceIdentifier identifier = device.getIdentifier();
+ String keyboardLayoutDescriptor =
+ inputManager.getCurrentKeyboardLayoutForInputDevice(identifier);
+ KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
+ inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
- final int recognizerCount = recognizers.size();
+ String summary;
+ if (keyboardLayout != null) {
+ summary = keyboardLayout.toString();
+ } else {
+ summary = context.getString(R.string.keyboard_layout_default_label);
+ }
- // Recognizer settings.
- if (recognizerCount > 0) {
indexable = new SearchIndexableRaw(context);
- indexable.key = "recognizer_settings";
- indexable.title = context.getString(R.string.recognizer_settings_title);
+ indexable.key = device.getName();
+ indexable.title = device.getName();
+ indexable.summaryOn = summary;
+ indexable.summaryOff = summary;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
- if (recognizerCount > 1) {
- // Recognizer chooser.
+ if (hasHardKeyboards) {
+ // Hard keyboard category.
indexable = new SearchIndexableRaw(context);
- indexable.key = "recognizer_title";
- indexable.title = context.getString(R.string.recognizer_title);
+ indexable.key = "builtin_keyboard_settings";
+ indexable.title = context.getString(
+ R.string.builtin_keyboard_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
- for (int i = 0; i < recognizerCount; i++) {
- ResolveInfo recognizer = recognizers.get(i);
-
- ServiceInfo serviceInfo = recognizer.serviceInfo;
- ComponentName componentName = new ComponentName(serviceInfo.packageName,
- serviceInfo.name);
-
- indexable = new SearchIndexableRaw(context);
- indexable.key = componentName.flattenToString();
- indexable.title = recognizer.loadLabel(context.getPackageManager()).toString();
- indexable.screenTitle = screenTitle;
- indexables.add(indexable);
- }
+ // Voice input
+ indexable = new SearchIndexableRaw(context);
+ indexable.key = "voice_input_settings";
+ indexable.title = context.getString(R.string.voice_input_settings);
+ indexable.screenTitle = screenTitle;
+ indexables.add(indexable);
// Text-to-speech.
TtsEngines ttsEngines = new TtsEngines(context);
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index 111f79b..5cf5d6a 100755
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -68,6 +68,7 @@ class InputMethodPreference extends SwitchPreference implements OnPreferenceClic
private final boolean mHasPriorityInSorting;
private final OnSavePreferenceListener mOnSaveListener;
private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
+ private final boolean mIsAllowedByOrganization;
private AlertDialog mDialog = null;
@@ -78,14 +79,18 @@ class InputMethodPreference extends SwitchPreference implements OnPreferenceClic
* @param imi The {@link InputMethodInfo} of this preference.
* @param isImeEnabler true if this preference is the IME enabler that has enable/disable
* switches for all available IMEs, not the list of enabled IMEs.
+ * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
+ owner.
* @param onSaveListener The listener called when this preference has been changed and needs
* to save the state to shared preference.
*/
InputMethodPreference(final Context context, final InputMethodInfo imi,
- final boolean isImeEnabler, final OnSavePreferenceListener onSaveListener) {
+ final boolean isImeEnabler, final boolean isAllowedByOrganization,
+ final OnSavePreferenceListener onSaveListener) {
super(context);
setPersistent(false);
mImi = imi;
+ mIsAllowedByOrganization = isAllowedByOrganization;
mOnSaveListener = onSaveListener;
if (!isImeEnabler) {
// Hide switch widget.
@@ -178,7 +183,7 @@ class InputMethodPreference extends SwitchPreference implements OnPreferenceClic
mImi, getContext());
// Only when this preference has a switch and an input method should be always enabled,
// this preference should be disabled to prevent accidentally disabling an input method.
- setEnabled(!(isAlwaysChecked && isImeEnabler()));
+ setEnabled(!((isAlwaysChecked && isImeEnabler()) || (!mIsAllowedByOrganization)));
setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
setSummary(getSummaryString());
}
@@ -189,6 +194,9 @@ class InputMethodPreference extends SwitchPreference implements OnPreferenceClic
private String getSummaryString() {
final Context context = getContext();
+ if (!mIsAllowedByOrganization) {
+ return context.getString(R.string.accessibility_feature_or_input_method_not_allowed);
+ }
final InputMethodManager imm = getInputMethodManager();
final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
final ArrayList<CharSequence> subtypeLabels = new ArrayList<>();
diff --git a/src/com/android/settings/location/DimmableIconPreference.java b/src/com/android/settings/location/DimmableIconPreference.java
new file mode 100644
index 0000000..acde1c1
--- /dev/null
+++ b/src/com/android/settings/location/DimmableIconPreference.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.location;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.preference.Preference;
+import android.util.AttributeSet;
+
+/**
+ * A preference item that can dim the icon when it's disabled, either directly or because its parent
+ * is disabled.
+ */
+public class DimmableIconPreference extends Preference {
+ private static final int ICON_ALPHA_ENABLED = 255;
+ private static final int ICON_ALPHA_DISABLED = 102;
+
+ public DimmableIconPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public DimmableIconPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public DimmableIconPreference(Context context) {
+ super(context);
+ }
+
+ private void dimIcon(boolean dimmed) {
+ Drawable icon = getIcon();
+ if (icon != null) {
+ icon.mutate().setAlpha(dimmed ? ICON_ALPHA_DISABLED : ICON_ALPHA_ENABLED);
+ setIcon(icon);
+ }
+ }
+
+ @Override
+ public void onParentChanged(Preference parent, boolean disableChild) {
+ dimIcon(disableChild);
+ super.onParentChanged(parent, disableChild);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ dimIcon(!enabled);
+ super.setEnabled(enabled);
+ }
+}
diff --git a/src/com/android/settings/location/InjectedSetting.java b/src/com/android/settings/location/InjectedSetting.java
index d8a3f49..5f4440a 100644
--- a/src/com/android/settings/location/InjectedSetting.java
+++ b/src/com/android/settings/location/InjectedSetting.java
@@ -23,7 +23,7 @@ import com.android.internal.annotations.Immutable;
import com.android.internal.util.Preconditions;
/**
- * Specifies a setting that is being injected into Settings > Location > Location services.
+ * Specifies a setting that is being injected into Settings &gt; Location &gt; Location services.
*
* @see android.location.SettingInjectorService
*/
diff --git a/src/com/android/settings/location/RecentLocationApps.java b/src/com/android/settings/location/RecentLocationApps.java
index 8e1ec05..e28f96b 100644
--- a/src/com/android/settings/location/RecentLocationApps.java
+++ b/src/com/android/settings/location/RecentLocationApps.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.IPackageManager;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Process;
@@ -30,6 +31,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -74,12 +77,35 @@ public class RecentLocationApps {
}
}
- private Preference createRecentLocationEntry(
+ /**
+ * Subclass of {@link Preference} to intercept views and allow content description to be set on
+ * them for accessibility purposes.
+ */
+ private static class AccessiblePreference extends DimmableIconPreference {
+ public CharSequence mContentDescription;
+
+ public AccessiblePreference(Context context, CharSequence contentDescription) {
+ super(context);
+ mContentDescription = contentDescription;
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ if (mContentDescription != null) {
+ final TextView titleView = (TextView) view.findViewById(android.R.id.title);
+ titleView.setContentDescription(mContentDescription);
+ }
+ }
+ }
+
+ private AccessiblePreference createRecentLocationEntry(
Drawable icon,
CharSequence label,
boolean isHighBattery,
+ CharSequence contentDescription,
Preference.OnPreferenceClickListener listener) {
- Preference pref = new Preference(mActivity);
+ AccessiblePreference pref = new AccessiblePreference(mActivity, contentDescription);
pref.setIcon(icon);
pref.setTitle(label);
if (isHighBattery) {
@@ -172,19 +198,29 @@ public class RecentLocationApps {
int uid = ops.getUid();
int userId = UserHandle.getUserId(uid);
- Preference preference = null;
+ AccessiblePreference preference = null;
try {
IPackageManager ipm = AppGlobals.getPackageManager();
ApplicationInfo appInfo =
ipm.getApplicationInfo(packageName, PackageManager.GET_META_DATA, userId);
+ if (appInfo == null) {
+ Log.w(TAG, "Null application info retrieved for package " + packageName
+ + ", userId " + userId);
+ return null;
+ }
+ Resources res = mActivity.getResources();
- Drawable icon = um.getBadgedDrawableForUser(
- mPackageManager.getApplicationIcon(appInfo), new UserHandle(userId));
+ final UserHandle userHandle = new UserHandle(userId);
+ Drawable appIcon = mPackageManager.getApplicationIcon(appInfo);
+ Drawable icon = um.getBadgedDrawableForUser(appIcon, userHandle);
+ CharSequence appLabel = mPackageManager.getApplicationLabel(appInfo);
+ CharSequence badgedAppLabel = um.getBadgedLabelForUser(appLabel.toString(), userHandle);
preference = createRecentLocationEntry(icon,
- mPackageManager.getApplicationLabel(appInfo), highBattery,
+ appLabel, highBattery, badgedAppLabel,
new PackageEntryClickedListener(packageName));
} catch (RemoteException e) {
- Log.w(TAG, "Error while retrieving application info", e);
+ Log.w(TAG, "Error while retrieving application info for package " + packageName
+ + ", userId " + userId, e);
}
return preference;
diff --git a/src/com/android/settings/location/SettingsInjector.java b/src/com/android/settings/location/SettingsInjector.java
index 5f8d030..edf67b8 100644
--- a/src/com/android/settings/location/SettingsInjector.java
+++ b/src/com/android/settings/location/SettingsInjector.java
@@ -247,7 +247,7 @@ class SettingsInjector {
* Adds an injected setting to the root.
*/
private Preference addServiceSetting(List<Preference> prefs, InjectedSetting info) {
- Preference pref = new Preference(mContext);
+ Preference pref = new DimmableIconPreference(mContext);
pref.setTitle(info.title);
pref.setSummary(null);
PackageManager pm = mContext.getPackageManager();
diff --git a/src/com/android/settings/net/UidDetail.java b/src/com/android/settings/net/UidDetail.java
index fd44d47..0b14254 100644
--- a/src/com/android/settings/net/UidDetail.java
+++ b/src/com/android/settings/net/UidDetail.java
@@ -20,6 +20,8 @@ import android.graphics.drawable.Drawable;
public class UidDetail {
public CharSequence label;
+ public CharSequence contentDescription;
public CharSequence[] detailLabels;
+ public CharSequence[] detailContentDescriptions;
public Drawable icon;
}
diff --git a/src/com/android/settings/net/UidDetailProvider.java b/src/com/android/settings/net/UidDetailProvider.java
index cd101c9..4b54137 100644
--- a/src/com/android/settings/net/UidDetailProvider.java
+++ b/src/com/android/settings/net/UidDetailProvider.java
@@ -16,8 +16,10 @@
package com.android.settings.net;
+import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -28,7 +30,9 @@ import android.net.ConnectivityManager;
import android.net.TrafficStats;
import android.os.UserManager;
import android.os.UserHandle;
+import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.Log;
import android.util.SparseArray;
import com.android.settings.R;
@@ -39,6 +43,7 @@ import com.android.settings.Utils;
* {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
*/
public class UidDetailProvider {
+ private static final String TAG = "DataUsage";
private final Context mContext;
private final SparseArray<UidDetail> mUidDetailCache;
@@ -148,28 +153,43 @@ public class UidDetailProvider {
final String[] packageNames = pm.getPackagesForUid(uid);
final int length = packageNames != null ? packageNames.length : 0;
try {
+ final int userId = UserHandle.getUserId(uid);
+ UserHandle userHandle = new UserHandle(userId);
+ IPackageManager ipm = AppGlobals.getPackageManager();
if (length == 1) {
- final ApplicationInfo info = pm.getApplicationInfo(packageNames[0], 0);
- detail.label = info.loadLabel(pm).toString();
- detail.icon = um.getBadgedDrawableForUser(info.loadIcon(pm),
- new UserHandle(UserHandle.getUserId(uid)));
+ final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
+ 0 /* no flags */, userId);
+ if (info != null) {
+ detail.label = info.loadLabel(pm).toString();
+ detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
+ new UserHandle(userId));
+ }
} else if (length > 1) {
detail.detailLabels = new CharSequence[length];
+ detail.detailContentDescriptions = new CharSequence[length];
for (int i = 0; i < length; i++) {
final String packageName = packageNames[i];
final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
- final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
-
- detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
- if (packageInfo.sharedUserLabel != 0) {
- detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
- packageInfo.applicationInfo).toString();
- detail.icon = um.getBadgedDrawableForUser(appInfo.loadIcon(pm),
- new UserHandle(UserHandle.getUserId(uid)));
+ final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
+ 0 /* no flags */, userId);
+
+ if (appInfo != null) {
+ detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
+ detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
+ detail.detailLabels[i], userHandle);
+ if (packageInfo.sharedUserLabel != 0) {
+ detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
+ packageInfo.applicationInfo).toString();
+ detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
+ }
}
}
}
+ detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
} catch (NameNotFoundException e) {
+ Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error while building UI detail for uid "+uid, e);
}
if (TextUtils.isEmpty(detail.label)) {
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 018b8ae..2fb95e4 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -21,10 +21,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
-import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
import com.android.settings.R;
/**
@@ -34,7 +34,7 @@ import com.android.settings.R;
*/
public class NfcEnabler implements Preference.OnPreferenceChangeListener {
private final Context mContext;
- private final CheckBoxPreference mCheckbox;
+ private final SwitchPreference mSwitch;
private final PreferenceScreen mAndroidBeam;
private final NfcAdapter mNfcAdapter;
private final IntentFilter mIntentFilter;
@@ -50,16 +50,16 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
}
};
- public NfcEnabler(Context context, CheckBoxPreference checkBoxPreference,
+ public NfcEnabler(Context context, SwitchPreference switchPreference,
PreferenceScreen androidBeam) {
mContext = context;
- mCheckbox = checkBoxPreference;
+ mSwitch = switchPreference;
mAndroidBeam = androidBeam;
mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
if (mNfcAdapter == null) {
// NFC is not supported
- mCheckbox.setEnabled(false);
+ mSwitch.setEnabled(false);
mAndroidBeam.setEnabled(false);
mIntentFilter = null;
return;
@@ -73,7 +73,7 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
}
handleNfcStateChanged(mNfcAdapter.getAdapterState());
mContext.registerReceiver(mReceiver, mIntentFilter);
- mCheckbox.setOnPreferenceChangeListener(this);
+ mSwitch.setOnPreferenceChangeListener(this);
}
public void pause() {
@@ -81,14 +81,14 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
return;
}
mContext.unregisterReceiver(mReceiver);
- mCheckbox.setOnPreferenceChangeListener(null);
+ mSwitch.setOnPreferenceChangeListener(null);
}
public boolean onPreferenceChange(Preference preference, Object value) {
// Turn NFC on/off
final boolean desiredState = (Boolean) value;
- mCheckbox.setEnabled(false);
+ mSwitch.setEnabled(false);
if (desiredState) {
mNfcAdapter.enable();
@@ -102,14 +102,14 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
private void handleNfcStateChanged(int newState) {
switch (newState) {
case NfcAdapter.STATE_OFF:
- mCheckbox.setChecked(false);
- mCheckbox.setEnabled(true);
+ mSwitch.setChecked(false);
+ mSwitch.setEnabled(true);
mAndroidBeam.setEnabled(false);
mAndroidBeam.setSummary(R.string.android_beam_disabled_summary);
break;
case NfcAdapter.STATE_ON:
- mCheckbox.setChecked(true);
- mCheckbox.setEnabled(true);
+ mSwitch.setChecked(true);
+ mSwitch.setEnabled(true);
mAndroidBeam.setEnabled(true);
if (mNfcAdapter.isNdefPushEnabled()) {
mAndroidBeam.setSummary(R.string.android_beam_on_summary);
@@ -118,13 +118,13 @@ public class NfcEnabler implements Preference.OnPreferenceChangeListener {
}
break;
case NfcAdapter.STATE_TURNING_ON:
- mCheckbox.setChecked(true);
- mCheckbox.setEnabled(false);
+ mSwitch.setChecked(true);
+ mSwitch.setEnabled(false);
mAndroidBeam.setEnabled(false);
break;
case NfcAdapter.STATE_TURNING_OFF:
- mCheckbox.setChecked(false);
- mCheckbox.setEnabled(false);
+ mSwitch.setChecked(false);
+ mSwitch.setEnabled(false);
mAndroidBeam.setEnabled(false);
break;
}
diff --git a/src/com/android/settings/nfc/PaymentDefaultDialog.java b/src/com/android/settings/nfc/PaymentDefaultDialog.java
index 6bc29e1..33ac947 100644
--- a/src/com/android/settings/nfc/PaymentDefaultDialog.java
+++ b/src/com/android/settings/nfc/PaymentDefaultDialog.java
@@ -34,6 +34,7 @@ public final class PaymentDefaultDialog extends AlertActivity implements
DialogInterface.OnClickListener {
public static final String TAG = "PaymentDefaultDialog";
+ private static final int PAYMENT_APP_MAX_CAPTION_LENGTH = 40;
private PaymentBackend mBackend;
private ComponentName mNewDefault;
@@ -109,12 +110,14 @@ public final class PaymentDefaultDialog extends AlertActivity implements
p.mTitle = getString(R.string.nfc_payment_set_default_label);
if (defaultPaymentApp == null) {
String formatString = getString(R.string.nfc_payment_set_default);
- String msg = String.format(formatString, requestedPaymentApp.caption);
+ String msg = String.format(formatString,
+ sanitizePaymentAppCaption(requestedPaymentApp.caption.toString()));
p.mMessage = msg;
} else {
String formatString = getString(R.string.nfc_payment_set_default_instead_of);
- String msg = String.format(formatString, requestedPaymentApp.caption,
- defaultPaymentApp.caption);
+ String msg = String.format(formatString,
+ sanitizePaymentAppCaption(requestedPaymentApp.caption.toString()),
+ sanitizePaymentAppCaption(defaultPaymentApp.caption.toString()));
p.mMessage = msg;
}
p.mPositiveButtonText = getString(R.string.yes);
@@ -126,4 +129,15 @@ public final class PaymentDefaultDialog extends AlertActivity implements
return true;
}
+ private String sanitizePaymentAppCaption(String input) {
+ String sanitizedString = input.replace('\n', ' ').replace('\r', ' ').trim();
+
+
+ if (sanitizedString.length() > PAYMENT_APP_MAX_CAPTION_LENGTH) {
+ return sanitizedString.substring(0, PAYMENT_APP_MAX_CAPTION_LENGTH);
+ }
+
+ return sanitizedString;
+ }
+
}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 6075748..efa43cd 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -36,6 +36,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.notification.NotificationAppList.AppRow;
@@ -134,6 +135,11 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
mPriority = (SwitchPreference) findPreference(KEY_PRIORITY);
mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
+ final boolean secure = new LockPatternUtils(getActivity()).isSecure();
+ if (!secure) {
+ getPreferenceScreen().removePreference(mSensitive);
+ }
+
mAppRow = NotificationAppList.loadAppRow(pm, info, mBackend);
if (intent.hasExtra(EXTRA_HAS_SETTINGS_INTENT)) {
// use settings intent from extra
@@ -149,7 +155,9 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
mBlock.setChecked(mAppRow.banned);
mPriority.setChecked(mAppRow.priority);
- mSensitive.setChecked(mAppRow.sensitive);
+ if (mSensitive != null) {
+ mSensitive.setChecked(mAppRow.sensitive);
+ }
mBlock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
@@ -167,13 +175,15 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
}
});
- mSensitive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean sensitive = (Boolean) newValue;
- return mBackend.setSensitive(pkg, uid, sensitive);
- }
- });
+ if (mSensitive != null) {
+ mSensitive.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean sensitive = (Boolean) newValue;
+ return mBackend.setSensitive(pkg, uid, sensitive);
+ }
+ });
+ }
}
private void toastAndFinish() {
diff --git a/src/com/android/settings/notification/NotificationAppList.java b/src/com/android/settings/notification/NotificationAppList.java
index 3879bef..7ca4b18 100644
--- a/src/com/android/settings/notification/NotificationAppList.java
+++ b/src/com/android/settings/notification/NotificationAppList.java
@@ -193,30 +193,6 @@ public class NotificationAppList extends PinnedHeaderListFragment
parent.getPaddingEnd() - eat, parent.getPaddingBottom());
}
- private boolean isSystemApp(PackageInfo pkg) {
- if (mSystemSignature == null) {
- mSystemSignature = new Signature[]{ getSystemSignature() };
- }
- return mSystemSignature[0] != null && mSystemSignature[0].equals(getFirstSignature(pkg));
- }
-
- private static Signature getFirstSignature(PackageInfo pkg) {
- if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
- return pkg.signatures[0];
- }
- return null;
- }
-
- private Signature getSystemSignature() {
- final PackageManager pm = mContext.getPackageManager();
- try {
- final PackageInfo sys = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
- return getFirstSignature(sys);
- } catch (NameNotFoundException e) {
- }
- return null;
- }
-
private static class ViewHolder {
ViewGroup row;
ImageView icon;
@@ -375,6 +351,7 @@ public class NotificationAppList extends PinnedHeaderListFragment
public boolean priority;
public boolean sensitive;
public boolean first; // first app in section
+ public boolean isSystem;
}
private static final Comparator<AppRow> mRowComparator = new Comparator<AppRow>() {
@@ -385,6 +362,7 @@ public class NotificationAppList extends PinnedHeaderListFragment
}
};
+
public static AppRow loadAppRow(PackageManager pm, PackageInfo pkg, Backend backend) {
final AppRow row = new AppRow();
row.pkg = pkg.packageName;
@@ -399,16 +377,28 @@ public class NotificationAppList extends PinnedHeaderListFragment
row.banned = backend.getNotificationsBanned(row.pkg, row.uid);
row.priority = backend.getHighPriority(row.pkg, row.uid);
row.sensitive = backend.getSensitive(row.pkg, row.uid);
+ row.isSystem = Utils.isSystemPackage(pm, pkg);
return row;
}
- public static void collectConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows) {
+ public static List<ResolveInfo> queryNotificationConfigActivities(PackageManager pm) {
if (DEBUG) Log.d(TAG, "APP_NOTIFICATION_PREFS_CATEGORY_INTENT is "
+ APP_NOTIFICATION_PREFS_CATEGORY_INTENT);
final List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
APP_NOTIFICATION_PREFS_CATEGORY_INTENT,
- PackageManager.MATCH_DEFAULT_ONLY);
- if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities");
+ 0 //PackageManager.MATCH_DEFAULT_ONLY
+ );
+ return resolveInfos;
+ }
+ public static void collectConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows) {
+ final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities(pm);
+ applyConfigActivities(pm, rows, resolveInfos);
+ }
+
+ public static void applyConfigActivities(PackageManager pm, ArrayMap<String, AppRow> rows,
+ List<ResolveInfo> resolveInfos) {
+ if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities"
+ + (resolveInfos.size() == 0 ? " ;_;" : ""));
for (ResolveInfo ri : resolveInfos) {
final ActivityInfo activityInfo = ri.activityInfo;
final ApplicationInfo appInfo = activityInfo.applicationInfo;
@@ -425,7 +415,7 @@ public class NotificationAppList extends PinnedHeaderListFragment
+ activityInfo.packageName);
continue;
}
- row.settingsIntent = new Intent(Intent.ACTION_MAIN)
+ row.settingsIntent = new Intent(APP_NOTIFICATION_PREFS_CATEGORY_INTENT)
.setClassName(activityInfo.packageName, activityInfo.name);
}
}
@@ -439,18 +429,41 @@ public class NotificationAppList extends PinnedHeaderListFragment
mRows.clear();
mSortedRows.clear();
- // collect all non-system apps
+ // collect all launchable apps, plus any packages that have notification settings
final PackageManager pm = mContext.getPackageManager();
- for (PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_SIGNATURES)) {
- if (pkg.applicationInfo == null || isSystemApp(pkg)) {
- if (DEBUG) Log.d(TAG, "Skipping " + pkg.packageName);
+ final List<ResolveInfo> resolvedApps = pm.queryIntentActivities(
+ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER),
+ PackageManager.MATCH_DEFAULT_ONLY
+ );
+ final List<ResolveInfo> resolvedConfigActivities
+ = queryNotificationConfigActivities(pm);
+ resolvedApps.addAll(resolvedConfigActivities);
+
+ for (ResolveInfo info : resolvedApps) {
+ String pkgName = info.activityInfo.packageName;
+ if (mRows.containsKey(pkgName)) {
+ // we already have this app, thanks
+ continue;
+ }
+
+ PackageInfo pkg = null;
+ try {
+ pkg = pm.getPackageInfo(pkgName,
+ PackageManager.GET_SIGNATURES);
+ } catch (NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Skipping (NNFE): " + pkg.packageName);
+ continue;
+ }
+ if (info.activityInfo.applicationInfo == null) {
+ if (DEBUG) Log.d(TAG, "Skipping (no applicationInfo): " + pkg.packageName);
continue;
}
final AppRow row = loadAppRow(pm, pkg, mBackend);
- mRows.put(row.pkg, row);
+ mRows.put(pkgName, row);
}
- // collect config activities
- collectConfigActivities(pm, mRows);
+
+ // add config activities to the list
+ applyConfigActivities(pm, mRows, resolvedConfigActivities);
// sort rows
mSortedRows.addAll(mRows.values());
Collections.sort(mSortedRows, mRowComparator);
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java
index 2b0fd5c..3094032 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/NotificationSettings.java
@@ -30,6 +30,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Vibrator;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceCategory;
@@ -40,6 +41,8 @@ import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.util.Log;
+import android.widget.SeekBar;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
@@ -75,6 +78,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
private Context mContext;
private PackageManager mPM;
private boolean mVoiceCapable;
+ private Vibrator mVibrator;
+ private VolumeSeekBarPreference mRingOrNotificationPreference;
private Preference mPhoneRingtonePreference;
private Preference mNotificationRingtonePreference;
@@ -82,6 +87,8 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
private TwoStatePreference mNotificationPulse;
private DropDownPreference mLockscreen;
private Preference mNotificationAccess;
+ private boolean mSecure;
+ private int mLockscreenSelectedValue;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -89,16 +96,25 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
mContext = getActivity();
mPM = mContext.getPackageManager();
mVoiceCapable = Utils.isVoiceCapable(mContext);
+ mSecure = new LockPatternUtils(getActivity()).isSecure();
+
+ mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
+ if (mVibrator != null && !mVibrator.hasVibrator()) {
+ mVibrator = null;
+ }
+
addPreferencesFromResource(R.xml.notification_settings);
final PreferenceCategory sound = (PreferenceCategory) findPreference(KEY_SOUND);
initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC);
initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM);
if (mVoiceCapable) {
- initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING);
+ mRingOrNotificationPreference =
+ initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING);
sound.removePreference(sound.findPreference(KEY_NOTIFICATION_VOLUME));
} else {
- initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION);
+ mRingOrNotificationPreference =
+ initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION);
sound.removePreference(sound.findPreference(KEY_RING_VOLUME));
}
initRingtones(sound);
@@ -130,10 +146,19 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
// === Volumes ===
- private void initVolumePreference(String key, int stream) {
+ private VolumeSeekBarPreference initVolumePreference(String key, int stream) {
final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key);
- volumePref.setStream(stream);
volumePref.setCallback(mVolumeCallback);
+ volumePref.setStream(stream);
+ return volumePref;
+ }
+
+ private void updateRingOrNotificationIcon(int progress) {
+ mRingOrNotificationPreference.showIcon(progress > 0
+ ? R.drawable.ring_notif
+ : (mVibrator == null
+ ? R.drawable.ring_notif_mute
+ : R.drawable.ring_notif_vibrate));
}
private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback {
@@ -151,6 +176,14 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
}
}
+ @Override
+ public void onStreamValueChanged(int stream, int progress) {
+ if (stream == AudioManager.STREAM_RING) {
+ mHandler.removeMessages(H.UPDATE_RINGER_ICON);
+ mHandler.obtainMessage(H.UPDATE_RINGER_ICON, progress, 0).sendToTarget();
+ }
+ }
+
public void stopSample() {
if (mCurrent != null) {
mCurrent.stopSample();
@@ -303,10 +336,13 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
return;
}
+
mLockscreen.addItem(R.string.lock_screen_notifications_summary_show,
R.string.lock_screen_notifications_summary_show);
- mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide,
- R.string.lock_screen_notifications_summary_hide);
+ if (mSecure) {
+ mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide,
+ R.string.lock_screen_notifications_summary_hide);
+ }
mLockscreen.addItem(R.string.lock_screen_notifications_summary_disable,
R.string.lock_screen_notifications_summary_disable);
updateLockscreenNotifications();
@@ -314,12 +350,16 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
@Override
public boolean onItemSelected(int pos, Object value) {
final int val = (Integer) value;
+ if (val == mLockscreenSelectedValue) {
+ return true;
+ }
final boolean enabled = val != R.string.lock_screen_notifications_summary_disable;
final boolean show = val == R.string.lock_screen_notifications_summary_show;
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
+ mLockscreenSelectedValue = val;
return true;
}
});
@@ -329,12 +369,12 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
if (mLockscreen == null) {
return;
}
- final boolean allowPrivate = getLockscreenAllowPrivateNotifications();
final boolean enabled = getLockscreenNotificationsEnabled();
- final int selectedVal = !enabled ? R.string.lock_screen_notifications_summary_disable :
+ final boolean allowPrivate = !mSecure || getLockscreenAllowPrivateNotifications();
+ mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable :
allowPrivate ? R.string.lock_screen_notifications_summary_show :
R.string.lock_screen_notifications_summary_hide;
- mLockscreen.setSelectedValue(selectedVal);
+ mLockscreen.setSelectedValue(mLockscreenSelectedValue);
}
private boolean getLockscreenNotificationsEnabled() {
@@ -415,6 +455,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
private static final int UPDATE_PHONE_RINGTONE = 1;
private static final int UPDATE_NOTIFICATION_RINGTONE = 2;
private static final int STOP_SAMPLE = 3;
+ private static final int UPDATE_RINGER_ICON = 4;
private H() {
super(Looper.getMainLooper());
@@ -432,6 +473,9 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
case STOP_SAMPLE:
mVolumeCallback.stopSample();
break;
+ case UPDATE_RINGER_ICON:
+ updateRingOrNotificationIcon(msg.arg1);
+ break;
}
}
}
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index 773f3af..2bfad1a 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -82,7 +82,7 @@ public class RedactionInterstitial extends SettingsActivity {
final boolean enabled = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
final boolean show = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1) != 0;
mShowAllButton.setChecked(enabled && show);
mRedactSensitiveButton.setChecked(enabled && !show);
mHideAllButton.setChecked(!enabled);
diff --git a/src/com/android/settings/notification/RedactionSettingsStandalone.java b/src/com/android/settings/notification/RedactionSettingsStandalone.java
new file mode 100644
index 0000000..26c05c1
--- /dev/null
+++ b/src/com/android/settings/notification/RedactionSettingsStandalone.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.notification;
+
+import com.android.settings.R;
+
+import android.content.Intent;
+import com.android.settings.SettingsActivity;
+import com.android.settings.notification.RedactionInterstitial.RedactionInterstitialFragment;
+
+/** Wrapper to allow external activites to jump directly to the {@link RedactionInterstitial} */
+public class RedactionSettingsStandalone extends SettingsActivity {
+
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, RedactionInterstitialFragment.class.getName())
+ .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
+ .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
+ .putExtra(EXTRA_PREFS_SET_NEXT_TEXT, getString(
+ R.string.app_notifications_dialog_done));
+ return modIntent;
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ return RedactionInterstitialFragment.class.getName().equals(fragmentName);
+ }
+}
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 11a83a7..f94e6a1 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -26,6 +26,7 @@ import android.preference.SeekBarVolumizer;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
+import android.widget.ImageView;
import android.widget.SeekBar;
import com.android.settings.R;
@@ -39,6 +40,7 @@ public class VolumeSeekBarPreference extends SeekBarPreference
private SeekBar mSeekBar;
private SeekBarVolumizer mVolumizer;
private Callback mCallback;
+ private ImageView mIconView;
public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
@@ -93,9 +95,35 @@ public class VolumeSeekBarPreference extends SeekBarPreference
};
final Uri sampleUri = mStream == AudioManager.STREAM_MUSIC ? getMediaVolumeUri() : null;
if (mVolumizer == null) {
- mVolumizer = new SeekBarVolumizer(getContext(), mStream, sampleUri, sbvc);
+ mVolumizer = new SeekBarVolumizer(getContext(), mStream, sampleUri, sbvc) {
+ // we need to piggyback on SBV's SeekBar listener to update our icon
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress,
+ boolean fromTouch) {
+ super.onProgressChanged(seekBar, progress, fromTouch);
+ mCallback.onStreamValueChanged(mStream, progress);
+ }
+ };
}
mVolumizer.setSeekBar(mSeekBar);
+ mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
+ mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress());
+ }
+
+ // during initialization, this preference is the SeekBar listener
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress,
+ boolean fromTouch) {
+ super.onProgressChanged(seekBar, progress, fromTouch);
+ mCallback.onStreamValueChanged(mStream, progress);
+ }
+
+ public void showIcon(int resId) {
+ // Instead of using setIcon, which will trigger listeners, this just decorates the
+ // preference temporarily with a new icon.
+ if (mIconView != null) {
+ mIconView.setImageResource(resId);
+ }
}
private Uri getMediaVolumeUri() {
@@ -106,5 +134,6 @@ public class VolumeSeekBarPreference extends SeekBarPreference
public interface Callback {
void onSampleStarting(SeekBarVolumizer sbv);
+ void onStreamValueChanged(int stream, int progress);
}
}
diff --git a/src/com/android/settings/notification/ZenModeConditionSelection.java b/src/com/android/settings/notification/ZenModeConditionSelection.java
index 4b1c229..610baba 100644
--- a/src/com/android/settings/notification/ZenModeConditionSelection.java
+++ b/src/com/android/settings/notification/ZenModeConditionSelection.java
@@ -54,14 +54,14 @@ public class ZenModeConditionSelection extends RadioGroup {
b.setChecked(true);
}
- private RadioButton newRadioButton(Object tag) {
+ private RadioButton newRadioButton(Condition condition) {
final RadioButton button = new RadioButton(mContext);
- button.setTag(tag);
+ button.setTag(condition);
button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
- handleSubscribe((Uri)button.getTag());
+ handleSubscribe((Condition) button.getTag());
}
}
});
@@ -95,7 +95,7 @@ public class ZenModeConditionSelection extends RadioGroup {
RadioButton v = (RadioButton) findViewWithTag(c.id);
if (c.state == Condition.STATE_TRUE || c.state == Condition.STATE_UNKNOWN) {
if (v == null) {
- v = newRadioButton(c.id);
+ v = newRadioButton(c);
}
}
if (v != null) {
@@ -105,10 +105,10 @@ public class ZenModeConditionSelection extends RadioGroup {
}
}
- protected void handleSubscribe(Uri id) {
- if (DEBUG) Log.d(TAG, "handleSubscribe " + id);
+ protected void handleSubscribe(Condition c) {
+ if (DEBUG) Log.d(TAG, "handleSubscribe " + c);
try {
- mNoMan.setZenModeCondition(id);
+ mNoMan.setZenModeCondition(c);
} catch (RemoteException e) {
// noop
}
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 65d825b..db60dfe 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -181,6 +181,16 @@ public class Index {
nonIndexableKeys = new HashMap<String, List<String>>();
}
+ public UpdateData(UpdateData other) {
+ dataToUpdate = new ArrayList<SearchIndexableData>(other.dataToUpdate);
+ dataToDelete = new ArrayList<SearchIndexableData>(other.dataToDelete);
+ nonIndexableKeys = new HashMap<String, List<String>>(other.nonIndexableKeys);
+ }
+
+ public UpdateData copy() {
+ return new UpdateData(this);
+ }
+
public void clear() {
dataToUpdate.clear();
dataToDelete.clear();
@@ -286,7 +296,7 @@ public class Index {
}
}
- public boolean update() {
+ public void update() {
final Intent intent = new Intent(SearchIndexablesContract.PROVIDER_INTERFACE);
List<ResolveInfo> list =
mContext.getPackageManager().queryIntentContentProviders(intent, 0);
@@ -304,7 +314,7 @@ public class Index {
addNonIndexablesKeysFromRemoteProvider(packageName, authority);
}
- return updateInternal();
+ updateInternal();
}
private boolean addIndexablesFromRemoteProvider(String packageName, String authority) {
@@ -443,11 +453,10 @@ public class Index {
}
}
- private boolean updateFromRemoteProvider(String packageName, String authority) {
- if (!addIndexablesFromRemoteProvider(packageName, authority)) {
- return false;
+ private void updateFromRemoteProvider(String packageName, String authority) {
+ if (addIndexablesFromRemoteProvider(packageName, authority)) {
+ updateInternal();
}
- return updateInternal();
}
/**
@@ -457,9 +466,8 @@ public class Index {
* @param rebuild true means that you want to delete the data from the Index first.
* @param includeInSearchResults true means that you want the bit "enabled" set so that the
* data will be seen included into the search results
- * @return true of the Index update has been successful.
*/
- public boolean updateFromClassNameResource(String className, boolean rebuild,
+ public void updateFromClassNameResource(String className, boolean rebuild,
boolean includeInSearchResults) {
if (className == null) {
throw new IllegalArgumentException("class name cannot be null!");
@@ -467,7 +475,7 @@ public class Index {
final SearchIndexableResource res = SearchIndexableResources.getResourceByName(className);
if (res == null ) {
Log.e(LOG_TAG, "Cannot find SearchIndexableResources for class name: " + className);
- return false;
+ return;
}
res.context = mContext;
res.enabled = includeInSearchResults;
@@ -476,15 +484,14 @@ public class Index {
}
addIndexableData(res);
mDataToProcess.forceUpdate = true;
- boolean result = updateInternal();
+ updateInternal();
res.enabled = false;
- return result;
}
- public boolean updateFromSearchIndexableData(SearchIndexableData data) {
+ public void updateFromSearchIndexableData(SearchIndexableData data) {
addIndexableData(data);
mDataToProcess.forceUpdate = true;
- return updateInternal();
+ updateInternal();
}
private SQLiteDatabase getReadableDatabase() {
@@ -510,21 +517,12 @@ public class Index {
SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
}
- private boolean updateInternal() {
+ private void updateInternal() {
synchronized (mDataToProcess) {
final UpdateIndexTask task = new UpdateIndexTask();
- task.execute(mDataToProcess);
- try {
- final boolean result = task.get();
- mDataToProcess.clear();
- return result;
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Cannot update index", e);
- return false;
- } catch (ExecutionException e) {
- Log.e(LOG_TAG, "Cannot update index", e);
- return false;
- }
+ UpdateData copy = mDataToProcess.copy();
+ task.execute(copy);
+ mDataToProcess.clear();
}
}
@@ -1027,8 +1025,14 @@ public class Index {
return;
}
+ // The DocID should contains more than the title string itself (you may have two settings
+ // with the same title). So we need to use a combination of the title and the screenTitle.
+ StringBuilder sb = new StringBuilder(updatedTitle);
+ sb.append(screenTitle);
+ int docId = sb.toString().hashCode();
+
ContentValues values = new ContentValues();
- values.put(IndexColumns.DOCID, updatedTitle.hashCode());
+ values.put(IndexColumns.DOCID, docId);
values.put(IndexColumns.LOCALE, locale);
values.put(IndexColumns.DATA_RANK, rank);
values.put(IndexColumns.DATA_TITLE, updatedTitle);
@@ -1143,7 +1147,7 @@ public class Index {
/**
* A private class for updating the Index database
*/
- private class UpdateIndexTask extends AsyncTask<UpdateData, Integer, Boolean> {
+ private class UpdateIndexTask extends AsyncTask<UpdateData, Integer, Void> {
@Override
protected void onPreExecute() {
@@ -1152,15 +1156,13 @@ public class Index {
}
@Override
- protected void onPostExecute(Boolean aBoolean) {
- super.onPostExecute(aBoolean);
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
mIsAvailable.set(true);
}
@Override
- protected Boolean doInBackground(UpdateData... params) {
- boolean result = false;
-
+ protected Void doInBackground(UpdateData... params) {
final List<SearchIndexableData> dataToUpdate = params[0].dataToUpdate;
final List<SearchIndexableData> dataToDelete = params[0].dataToDelete;
final Map<String, List<String>> nonIndexableKeys = params[0].nonIndexableKeys;
@@ -1180,11 +1182,11 @@ public class Index {
forceUpdate);
}
database.setTransactionSuccessful();
- result = true;
} finally {
database.endTransaction();
}
- return result;
+
+ return null;
}
private boolean processDataToUpdate(SQLiteDatabase database, String localeStr,
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 44717c1..2c76002 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -30,7 +30,6 @@ import com.android.settings.WallpaperTypeSettings;
import com.android.settings.WirelessSettings;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.bluetooth.MessageAccessSettings;
import com.android.settings.deviceinfo.Memory;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -43,6 +42,7 @@ import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.sim.SimSettings;
import com.android.settings.users.UserSettings;
+import com.android.settings.voice.VoiceInputSettings;
import com.android.settings.wifi.AdvancedWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
@@ -93,7 +93,6 @@ public final class Ranking {
// BT
sRankMap.put(BluetoothSettings.class.getName(), RANK_BT);
- sRankMap.put(MessageAccessSettings.class.getName(), RANK_BT);
// SIM Cards
sRankMap.put(SimSettings.class.getName(), RANK_SIM);
@@ -139,6 +138,7 @@ public final class Ranking {
// IMEs
sRankMap.put(InputMethodAndLanguageSettings.class.getName(), RANK_IME);
+ sRankMap.put(VoiceInputSettings.class.getName(), RANK_IME);
// Privacy
sRankMap.put(PrivacySettings.class.getName(), RANK_PRIVACY);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index a3d2b8d..105ce7e 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -18,7 +18,6 @@ package com.android.settings.search;
import android.provider.SearchIndexableResource;
-import com.android.settings.ChooseLockGeneric;
import com.android.settings.DataUsageSummary;
import com.android.settings.DateTimeSettings;
import com.android.settings.DevelopmentSettings;
@@ -33,7 +32,6 @@ import com.android.settings.WallpaperTypeSettings;
import com.android.settings.WirelessSettings;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.bluetooth.MessageAccessSettings;
import com.android.settings.deviceinfo.Memory;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -46,6 +44,7 @@ import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.sim.SimSettings;
import com.android.settings.users.UserSettings;
+import com.android.settings.voice.VoiceInputSettings;
import com.android.settings.wifi.AdvancedWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
@@ -92,17 +91,10 @@ public final class SearchIndexableResources {
sResMap.put(SimSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(SimSettings.class.getName()),
- R.xml.sim_settings,
+ NO_DATA_RES_ID,
SimSettings.class.getName(),
R.drawable.ic_sim_sd));
- sResMap.put(MessageAccessSettings.class.getName(),
- new SearchIndexableResource(
- Ranking.getRankForClassName(MessageAccessSettings.class.getName()),
- NO_DATA_RES_ID,
- MessageAccessSettings.class.getName(),
- R.drawable.ic_settings_bluetooth2));
-
sResMap.put(DataUsageSummary.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(DataUsageSummary.class.getName()),
@@ -208,14 +200,6 @@ public final class SearchIndexableResources {
SecuritySettings.class.getName(),
R.drawable.ic_settings_security));
- sResMap.put(ChooseLockGeneric.ChooseLockGenericFragment.class.getName(),
- new SearchIndexableResource(
- Ranking.getRankForClassName(
- ChooseLockGeneric.ChooseLockGenericFragment.class.getName()),
- R.xml.security_settings_picker,
- ChooseLockGeneric.ChooseLockGenericFragment.class.getName(),
- R.drawable.ic_settings_security));
-
sResMap.put(ScreenPinningSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(ScreenPinningSettings.class.getName()),
@@ -230,6 +214,13 @@ public final class SearchIndexableResources {
InputMethodAndLanguageSettings.class.getName(),
R.drawable.ic_settings_language));
+ sResMap.put(VoiceInputSettings.class.getName(),
+ new SearchIndexableResource(
+ Ranking.getRankForClassName(VoiceInputSettings.class.getName()),
+ NO_DATA_RES_ID,
+ VoiceInputSettings.class.getName(),
+ R.drawable.ic_settings_language));
+
sResMap.put(PrivacySettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(PrivacySettings.class.getName()),
diff --git a/src/com/android/settings/sim/SimSettings.java b/src/com/android/settings/sim/SimSettings.java
index 2e1c0f5..abfeccb 100644
--- a/src/com/android/settings/sim/SimSettings.java
+++ b/src/com/android/settings/sim/SimSettings.java
@@ -16,6 +16,7 @@
package com.android.settings.sim;
+import android.provider.SearchIndexableResource;
import com.android.settings.R;
import android.app.AlertDialog;
@@ -55,6 +56,7 @@ import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
import com.android.settings.notification.DropDownPreference;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
@@ -86,17 +88,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
private SubInfoRecord mCalls = null;
private SubInfoRecord mSMS = null;
- /**
- * Return whether or not the user should have a SIM Cards option in Settings.
- * TODO: Change back to returning true if count is greater than one after testing.
- * TODO: See bug 16533525.
- */
- public static boolean showSimCardScreen(Context context) {
- final TelephonyManager tm =
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-
- return tm.getSimCount() > 0;
- }
+ private int mNumSims;
public SimSettings() {
super(DISALLOW_CONFIG_SIM);
@@ -107,7 +99,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
super.onCreate(bundle);
if (mSubInfoList == null) {
- mSubInfoList = SubscriptionManager.getActivatedSubInfoList(getActivity());
+ mSubInfoList = SubscriptionManager.getActiveSubInfoList();
}
createPreferences();
@@ -124,10 +116,14 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
final int numSlots = tm.getSimCount();
mAvailableSubInfos = new ArrayList<SubInfoRecord>(numSlots);
+ mNumSims = 0;
for (int i = 0; i < numSlots; ++i) {
final SubInfoRecord sir = findRecordBySlotId(i);
simCards.addPreference(new SimPreference(getActivity(), sir, i));
mAvailableSubInfos.add(sir);
+ if (sir != null) {
+ mNumSims++;
+ }
}
updateActivitesCategory();
@@ -139,7 +135,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
}
private void updateSimSlotValues() {
- SubscriptionManager.getAllSubInfoList(getActivity());
+ SubscriptionManager.getAllSubInfoList();
final PreferenceCategory simCards = (PreferenceCategory)findPreference(SIM_CARD_CATEGORY);
final PreferenceScreen prefScreen = getPreferenceScreen();
@@ -201,10 +197,11 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
private void updateSmsValues() {
final DropDownPreference simPref = (DropDownPreference) findPreference(KEY_SMS);
- final SubInfoRecord sir = findRecordBySubId(SubscriptionManager.getPreferredSmsSubId());
+ final SubInfoRecord sir = findRecordBySubId(SubscriptionManager.getDefaultSmsSubId());
if (sir != null) {
simPref.setSelectedItem(sir.mSlotId + 1);
}
+ simPref.setEnabled(mNumSims > 1);
}
private void updateCellularDataValues() {
@@ -213,6 +210,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
if (sir != null) {
simPref.setSelectedItem(sir.mSlotId);
}
+ simPref.setEnabled(mNumSims > 1);
}
private void updateCallValues() {
@@ -221,6 +219,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
if (sir != null) {
simPref.setSelectedItem(sir.mSlotId + 1);
}
+ simPref.setEnabled(mNumSims > 1);
}
@Override
@@ -273,8 +272,6 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
// SubscriptionManager.setDefaultSMSSubId(subId);
}
- updateAllOptions();
-
return true;
}
});
@@ -347,16 +344,17 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
final Spinner displayNumbers =
(Spinner)dialogLayout.findViewById(R.id.display_numbers);
- SubscriptionManager.setDisplayNumberFormat(getActivity(),
+ SubscriptionManager.setDisplayNumberFormat(
displayNumbers.getSelectedItemPosition() == 0
? SubscriptionManager.DISPLAY_NUMBER_LAST
: SubscriptionManager.DISPLAY_NUMBER_FIRST, mSubInfoRecord.mSubId);
mSubInfoRecord.mDisplayName = nameText.getText().toString();
- SubscriptionManager.setDisplayName(getActivity(), mSubInfoRecord.mDisplayName,
+ SubscriptionManager.setDisplayName(mSubInfoRecord.mDisplayName,
mSubInfoRecord.mSubId);
updateAllOptions();
+ update();
}
});
@@ -370,4 +368,26 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
builder.create().show();
}
}
+
+ /**
+ * For search
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ ArrayList<SearchIndexableResource> result =
+ new ArrayList<SearchIndexableResource>();
+
+ if (Utils.showSimCardTile(context)) {
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.sim_settings;
+ result.add(sir);
+ }
+
+ return result;
+ }
+ };
+
}
diff --git a/src/com/android/settings/tts/TtsEngineSettingsFragment.java b/src/com/android/settings/tts/TtsEngineSettingsFragment.java
index c8531fa..2449353 100644
--- a/src/com/android/settings/tts/TtsEngineSettingsFragment.java
+++ b/src/com/android/settings/tts/TtsEngineSettingsFragment.java
@@ -140,7 +140,7 @@ public class TtsEngineSettingsFragment extends SettingsPreferenceFragment implem
mLocalePreference.setEntries(entries);
mLocalePreference.setEntryValues(entryValues);
- mLocalePreference.setValue(value.toString());
+ mLocalePreference.setValue(value != null ? value.toString() : null);
mLocalePreference.setEnabled(entries.length > 0);
}
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 0518f56..9eee4ac 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -159,34 +159,17 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
private boolean panelOpen;
private boolean immutable;
private List<Preference> mChildren = new ArrayList<Preference>();
- private final ColorFilter grayscaleFilter;
AppRestrictionsPreference(Context context, OnClickListener listener) {
super(context);
setLayoutResource(R.layout.preference_app_restrictions);
this.listener = listener;
-
- ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.setSaturation(0f);
- float[] matrix = colorMatrix.getArray();
- matrix[18] = 0.5f;
- grayscaleFilter = new ColorMatrixColorFilter(colorMatrix);
}
private void setSettingsEnabled(boolean enable) {
hasSettings = enable;
}
- @Override
- public void setChecked(boolean checked) {
- if (checked) {
- getIcon().setColorFilter(null);
- } else {
- getIcon().setColorFilter(grayscaleFilter);
- }
- super.setChecked(checked);
- }
-
void setRestrictions(ArrayList<RestrictionEntry> restrictions) {
this.restrictions = restrictions;
}
@@ -246,6 +229,8 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
final Switch toggle = (Switch) widget.getChildAt(0);
toggle.setEnabled(!isImmutable());
toggle.setTag(this);
+ toggle.setClickable(true);
+ toggle.setFocusable(true);
toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 7dc83ef..f5ea6aa 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -418,9 +418,11 @@ public class UserSettings extends SettingsPreferenceFragment
int userId = newUserInfo.id;
UserHandle user = new UserHandle(userId);
mUserManager.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
- mUserManager.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user);
+ // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise
+ // the putIntForUser() will fail.
Secure.putIntForUser(getContentResolver(),
Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF, userId);
+ mUserManager.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user);
Bitmap bitmap = createBitmapFromDrawable(
USER_DRAWABLES[userId % UserSettings.USER_DRAWABLES.length]);
mUserManager.setUserIcon(userId, bitmap);
@@ -630,14 +632,14 @@ public class UserSettings extends SettingsPreferenceFragment
Dialog dlg = new AlertDialog.Builder(context)
.setTitle(R.string.user_exit_guest_confirm_title)
.setMessage(R.string.user_exit_guest_confirm_message)
- .setPositiveButton(android.R.string.yes,
+ .setPositiveButton(R.string.user_exit_guest_dialog_remove,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
exitGuest();
}
})
- .setNegativeButton(android.R.string.no, null)
+ .setNegativeButton(android.R.string.cancel, null)
.create();
return dlg;
}
@@ -741,6 +743,10 @@ public class UserSettings extends SettingsPreferenceFragment
final boolean voiceCapable = Utils.isVoiceCapable(context);
final ArrayList<Integer> missingIcons = new ArrayList<Integer>();
for (UserInfo user : users) {
+ if (user.isManagedProfile()) {
+ // Managed profiles appear under Accounts Settings instead
+ continue;
+ }
Preference pref;
if (user.id == UserHandle.myUserId()) {
pref = mMePreference;
@@ -773,19 +779,11 @@ public class UserSettings extends SettingsPreferenceFragment
if (!isInitialized(user)) {
if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_not_set_up);
- } else if (user.isManagedProfile()) {
- pref.setSummary(R.string.user_summary_managed_profile_not_set_up);
} else {
pref.setSummary(R.string.user_summary_not_set_up);
}
} else if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_profile);
- } else if (user.isManagedProfile()) {
- if (user.isEnabled()) {
- pref.setSummary(R.string.user_summary_managed_profile);
- } else {
- pref.setSummary(R.string.user_summary_managed_profile_not_enabled);
- }
}
if (user.iconPath != null) {
if (mUserIcons.get(user.id) == null) {
@@ -794,6 +792,8 @@ public class UserSettings extends SettingsPreferenceFragment
} else {
setPhotoId(pref, user);
}
+ } else {
+ pref.setIcon(getEncircledDefaultAvatar());
}
}
@@ -807,7 +807,19 @@ public class UserSettings extends SettingsPreferenceFragment
mUserListCategory.addPreference(pref);
}
- if (!mIsGuest) {
+ boolean showGuestPreference = !mIsGuest;
+ // If user has DISALLOW_ADD_USER don't allow creating a guest either.
+ if (showGuestPreference && mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
+ showGuestPreference = false;
+ // If guest already exists, no user creation needed.
+ for (UserInfo user : users) {
+ if (user.isGuest()) {
+ showGuestPreference = true;
+ break;
+ }
+ }
+ }
+ if (showGuestPreference) {
// Add a virtual Guest user for guest defaults
Preference pref = new UserPreference(getActivity(), null,
UserPreference.USERID_GUEST_DEFAULTS,
@@ -825,7 +837,7 @@ public class UserSettings extends SettingsPreferenceFragment
if (missingIcons.size() > 0) {
loadIconsAsync(missingIcons);
}
- boolean moreUsers = mUserManager.getMaxSupportedUsers() > users.size();
+ boolean moreUsers = mUserManager.canAddMoreUsers();
mAddUser.setEnabled(moreUsers);
}
@@ -841,6 +853,9 @@ public class UserSettings extends SettingsPreferenceFragment
protected Void doInBackground(List<Integer>... values) {
for (int userId : values[0]) {
Bitmap bitmap = mUserManager.getUserIcon(userId);
+ if (bitmap == null) {
+ bitmap = createBitmapFromDrawable(R.drawable.ic_avatar_default_1);
+ }
mUserIcons.append(userId, bitmap);
}
return null;
@@ -911,7 +926,7 @@ public class UserSettings extends SettingsPreferenceFragment
if (!isInitialized(user)) {
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_SETUP_USER, user.id, user.serialNumber));
- } else if (!user.isManagedProfile()) {
+ } else {
switchUserNow(userId);
}
}
@@ -936,6 +951,10 @@ public class UserSettings extends SettingsPreferenceFragment
}
}
// No guest user. Create one.
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)) {
+ Log.i(TAG, "Blocking guest creation because it is restricted");
+ return;
+ }
UserInfo guestUser = mUserManager.createGuest(getActivity(),
getResources().getString(R.string.user_guest));
if (guestUser != null) {
diff --git a/src/com/android/settings/voice/VoiceInputSettings.java b/src/com/android/settings/voice/VoiceInputSettings.java
index 309c6e9..262f145 100644
--- a/src/com/android/settings/voice/VoiceInputSettings.java
+++ b/src/com/android/settings/voice/VoiceInputSettings.java
@@ -16,18 +16,33 @@
package com.android.settings.voice;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.preference.Preference;
import android.provider.Settings;
+import android.service.voice.VoiceInteractionService;
+import android.service.voice.VoiceInteractionServiceInfo;
+import android.speech.RecognitionService;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.voice.VoiceInputPreference.RadioButtonGroupState;
import android.os.Bundle;
import android.preference.PreferenceCategory;
import android.widget.Checkable;
+import java.util.ArrayList;
+import java.util.List;
+
public class VoiceInputSettings extends SettingsPreferenceFragment implements
- Preference.OnPreferenceClickListener, RadioButtonGroupState {
+ Preference.OnPreferenceClickListener, RadioButtonGroupState, Indexable {
private static final String TAG = "VoiceInputSettings";
private static final boolean DBG = false;
@@ -145,7 +160,7 @@ public class VoiceInputSettings extends SettingsPreferenceFragment implements
VoiceInputHelper.RecognizerInfo info = mHelper.mAvailableRecognizerInfos.get(i);
if (info.key.equals(key)) {
Settings.Secure.putString(getActivity().getContentResolver(),
- Settings.Secure.VOICE_INTERACTION_SERVICE, null);
+ Settings.Secure.VOICE_INTERACTION_SERVICE, "");
Settings.Secure.putString(getActivity().getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE, key);
return;
@@ -160,4 +175,68 @@ public class VoiceInputSettings extends SettingsPreferenceFragment implements
}
return true;
}
+
+ // For Search
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+
+ @Override
+ public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+ boolean enabled) {
+
+ List<SearchIndexableRaw> indexables = new ArrayList<>();
+
+ final String screenTitle = context.getString(R.string.voice_input_settings_title);
+
+ SearchIndexableRaw indexable = new SearchIndexableRaw(context);
+ indexable.key = "voice_service_preference_section_title";
+ indexable.title = context.getString(R.string.voice_service_preference_section_title);
+ indexable.screenTitle = screenTitle;
+ indexables.add(indexable);
+
+ final List<ResolveInfo> voiceInteractions =
+ context.getPackageManager().queryIntentServices(
+ new Intent(VoiceInteractionService.SERVICE_INTERFACE),
+ PackageManager.GET_META_DATA);
+
+ final int countInteractions = voiceInteractions.size();
+ for (int i = 0; i < countInteractions; i++) {
+ ResolveInfo info = voiceInteractions.get(i);
+ VoiceInteractionServiceInfo visInfo = new VoiceInteractionServiceInfo(
+ context.getPackageManager(), info.serviceInfo);
+ if (visInfo.getParseError() != null) {
+ continue;
+ }
+ indexables.add(getSearchIndexableRaw(context, info, screenTitle));
+ }
+
+ final List<ResolveInfo> recognitions =
+ context.getPackageManager().queryIntentServices(
+ new Intent(RecognitionService.SERVICE_INTERFACE),
+ PackageManager.GET_META_DATA);
+
+ final int countRecognitions = recognitions.size();
+ for (int i = 0; i < countRecognitions; i++) {
+ ResolveInfo info = recognitions.get(i);
+ indexables.add(getSearchIndexableRaw(context, info, screenTitle));
+ }
+
+ return indexables;
+ }
+
+ private SearchIndexableRaw getSearchIndexableRaw(Context context,
+ ResolveInfo info, String screenTitle) {
+
+ ServiceInfo serviceInfo = info.serviceInfo;
+ ComponentName componentName = new ComponentName(serviceInfo.packageName,
+ serviceInfo.name);
+
+ SearchIndexableRaw indexable = new SearchIndexableRaw(context);
+ indexable.key = componentName.flattenToString();
+ indexable.title = info.loadLabel(context.getPackageManager()).toString();
+ indexable.screenTitle = screenTitle;
+
+ return indexable;
+ }
+ };
}
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index 5be9046..7516392 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -16,13 +16,11 @@
package com.android.settings.vpn2;
-import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -31,13 +29,10 @@ import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.os.UserManager;
-import android.os.Process;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
-import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -49,14 +44,13 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
+import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.Spinner;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
@@ -64,10 +58,6 @@ import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.UserSpinnerAdapter;
-import com.android.settings.UserSpinnerAdapter.UserDetails;
-import com.android.settings.Utils;
-
import com.google.android.collect.Lists;
import java.util.ArrayList;
@@ -76,12 +66,11 @@ import java.util.List;
public class VpnSettings extends SettingsPreferenceFragment implements
Handler.Callback, Preference.OnPreferenceClickListener,
- DialogInterface.OnClickListener, DialogInterface.OnDismissListener, OnItemSelectedListener {
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private static final String TAG = "VpnSettings";
private static final String TAG_LOCKDOWN = "lockdown";
- private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
private static final String EXTRA_PICK_LOCKDOWN = "android.net.vpn.PICK_LOCKDOWN";
// TODO: migrate to using DialogFragment when editing
@@ -102,7 +91,6 @@ public class VpnSettings extends SettingsPreferenceFragment implements
private String mSelectedKey;
private boolean mUnavailable;
- private UserSpinnerAdapter mProfileSpinnerAdapter;
@Override
public void onCreate(Bundle savedState) {
@@ -130,39 +118,6 @@ public class VpnSettings extends SettingsPreferenceFragment implements
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- Context context = getActivity();
- mProfileSpinnerAdapter = Utils.createUserSpinnerAdapter(mUm, getActivity());
- if (mProfileSpinnerAdapter != null) {
- Spinner spinner = (Spinner) getActivity().getLayoutInflater().inflate(
- R.layout.spinner_view, null);
-
- spinner.setAdapter(mProfileSpinnerAdapter);
- spinner.setOnItemSelectedListener(this);
- setPinnedHeaderView(spinner);
- }
- }
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- UserHandle selectedUser = mProfileSpinnerAdapter.getUserHandle(position);
- if (selectedUser.getIdentifier() != UserHandle.myUserId()) {
- Intent intent = new Intent(ACTION_VPN_SETTINGS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Activity activity = getActivity();
- activity.startActivityAsUser(intent, selectedUser);
- activity.finish();
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // Nothing to do
- }
-
- @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.vpn, menu);
@@ -537,7 +492,7 @@ public class VpnSettings extends SettingsPreferenceFragment implements
private static class TitleAdapter extends ArrayAdapter<CharSequence> {
public TitleAdapter(Context context, List<CharSequence> objects) {
- super(context, com.android.internal.R.layout.select_dialog_singlechoice_holo,
+ super(context, com.android.internal.R.layout.select_dialog_singlechoice_material,
android.R.id.text1, objects);
}
}
diff --git a/src/com/android/settings/widget/SetupWizardIllustration.java b/src/com/android/settings/widget/SetupWizardIllustration.java
index dcc4c65..717ec35 100644
--- a/src/com/android/settings/widget/SetupWizardIllustration.java
+++ b/src/com/android/settings/widget/SetupWizardIllustration.java
@@ -20,9 +20,11 @@ package com.android.settings.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
+import android.view.Gravity;
+import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
import com.android.settings.R;
@@ -42,7 +44,8 @@ public class SetupWizardIllustration extends FrameLayout {
private float mBaselineGridSize;
private Drawable mBackground;
private Drawable mForeground;
- private int mForegroundHeight = 0;
+ private final Rect mViewBounds = new Rect();
+ private final Rect mForegroundBounds = new Rect();
private float mScale = 1.0f;
private float mAspectRatio = 0.0f;
@@ -91,6 +94,12 @@ public class SetupWizardIllustration extends FrameLayout {
}
@Override
+ public void onResolveDrawables(int layoutDirection) {
+ mBackground.setLayoutDirection(layoutDirection);
+ mForeground.setLayoutDirection(layoutDirection);
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mAspectRatio != 0.0f) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
@@ -98,6 +107,7 @@ public class SetupWizardIllustration extends FrameLayout {
illustrationHeight -= illustrationHeight % mBaselineGridSize;
setPaddingRelative(0, illustrationHeight, 0, 0);
}
+ setOutlineProvider(ViewOutlineProvider.BOUNDS);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@@ -106,25 +116,25 @@ public class SetupWizardIllustration extends FrameLayout {
final int layoutWidth = right - left;
final int layoutHeight = bottom - top;
if (mForeground != null) {
- final float intrinsicWidth = mForeground.getIntrinsicWidth();
- final float intrinsicHeight = mForeground.getIntrinsicHeight();
- if (intrinsicWidth <= 0 || intrinsicHeight <= 0) {
- Log.e(TAG, "Foreground drawable intrinsic size must be defined and positive");
- mForeground = null;
- mForegroundHeight = 0;
- mScale = 1.0f;
- } else {
- // Scale the foreground to fill the width of the view
- mScale = layoutWidth / intrinsicWidth;
- mForegroundHeight = (int) (intrinsicHeight * mScale);
- mForeground.setBounds(0, 0, layoutWidth, mForegroundHeight);
+ int intrinsicWidth = mForeground.getIntrinsicWidth();
+ int intrinsicHeight = mForeground.getIntrinsicHeight();
+ final int layoutDirection = getLayoutDirection();
+
+ mViewBounds.set(0, 0, layoutWidth, layoutHeight);
+ if (mAspectRatio != 0f) {
+ mScale = layoutWidth / (float) intrinsicWidth;
+ intrinsicWidth = layoutWidth;
+ intrinsicHeight = (int) (intrinsicHeight * mScale);
}
+ Gravity.apply(Gravity.FILL_HORIZONTAL | Gravity.TOP, intrinsicWidth, intrinsicHeight,
+ mViewBounds, mForegroundBounds, layoutDirection);
+ mForeground.setBounds(mForegroundBounds);
}
if (mBackground != null) {
// Scale the bounds by mScale to compensate for the scale done to the canvas before
// drawing.
mBackground.setBounds(0, 0, (int) Math.ceil(layoutWidth / mScale),
- (int) Math.ceil((layoutHeight - mForegroundHeight) / mScale));
+ (int) Math.ceil((layoutHeight - mForegroundBounds.height()) / mScale));
}
super.onLayout(changed, left, top, right, bottom);
}
@@ -134,7 +144,7 @@ public class SetupWizardIllustration extends FrameLayout {
if (mBackground != null) {
canvas.save();
// Draw the background filling parts not covered by the illustration
- canvas.translate(0, mForegroundHeight);
+ canvas.translate(0, mForegroundBounds.height());
// Scale the background so its size matches the foreground
canvas.scale(mScale, mScale, 0, 0);
mBackground.draw(canvas);
diff --git a/src/com/android/settings/widget/SwitchBar.java b/src/com/android/settings/widget/SwitchBar.java
index e24d83f..c15ac41 100644
--- a/src/com/android/settings/widget/SwitchBar.java
+++ b/src/com/android/settings/widget/SwitchBar.java
@@ -124,7 +124,7 @@ public class SwitchBar extends LinearLayout implements CompoundButton.OnCheckedC
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
mTextView.setEnabled(enabled);
- mSwitch.setEnabled(false);
+ mSwitch.setEnabled(enabled);
}
public final ToggleSwitch getSwitch() {
diff --git a/src/com/android/settings/wifi/AccessPoint.java b/src/com/android/settings/wifi/AccessPoint.java
index b3fafa4..ac818a7 100644
--- a/src/com/android/settings/wifi/AccessPoint.java
+++ b/src/com/android/settings/wifi/AccessPoint.java
@@ -20,6 +20,7 @@ import com.android.settings.R;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
@@ -266,14 +267,21 @@ class AccessPoint extends Preference {
Drawable drawable = getIcon();
if (drawable == null) {
- drawable = context.getTheme().obtainStyledAttributes(
- wifi_signal_attributes).getDrawable(0);
- setIcon(drawable);
+ // To avoid a drawing race condition, we first set the state (SECURE/NONE) and then
+ // set the icon (drawable) to that state's drawable.
+ StateListDrawable sld = (StateListDrawable) context.getTheme()
+ .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0);
+ // If sld is null then we are indexing and therefore do not have access to
+ // (nor need to display) the drawable.
+ if (sld != null) {
+ sld.setState((security != SECURITY_NONE) ? STATE_SECURED : STATE_NONE);
+ drawable = sld.getCurrent();
+ setIcon(drawable);
+ }
}
if (drawable != null) {
drawable.setLevel(level);
- drawable.setState((security != SECURITY_NONE) ? STATE_SECURED : STATE_NONE);
}
}
}
@@ -452,7 +460,7 @@ class AccessPoint extends Preference {
if (result.seen == 0)
continue;
- if (result.status != ScanResult.ENABLED)
+ if (result.autoJoinStatus != ScanResult.ENABLED)
numBlackListed++;
if (result.frequency > LOWER_FREQ_5GHZ
@@ -520,6 +528,10 @@ class AccessPoint extends Preference {
final Context context = getContext();
updateIcon(getLevel(), context);
+ // Force new summary
+ setSummary(null);
+
+ // Update to new summary
StringBuilder summary = new StringBuilder();
if (mState != null) { // This is the active connection
@@ -550,21 +562,6 @@ class AccessPoint extends Preference {
if (mConfig != null) { // Is saved network
summary.append(context.getString(R.string.wifi_remembered));
}
-
- if (security != SECURITY_NONE) {
- String securityStrFormat;
- if (summary.length() == 0) {
- securityStrFormat = context.getString(R.string.wifi_secured_first_item);
- } else {
- securityStrFormat = context.getString(R.string.wifi_secured_second_item);
- }
- }
-
- }
-
- // This is a workaround, see bug report...
- if (summary.length() < 1) {
- summary.append(" ");
}
if (WifiSettings.mVerboseLogging > 0) {
@@ -591,7 +588,11 @@ class AccessPoint extends Preference {
}
}
- setSummary(summary.toString());
+ if (summary.length() > 0) {
+ setSummary(summary.toString());
+ } else {
+ showSummary = false;
+ }
}
/**
diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java
index b7316d0..dfb86cc 100644
--- a/src/com/android/settings/wifi/AdvancedWifiSettings.java
+++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java
@@ -20,6 +20,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppManager;
+import android.net.NetworkScorerAppManager.NetworkScorerAppData;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WpsInfo;
@@ -29,6 +32,7 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.security.Credentials;
@@ -40,6 +44,8 @@ import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
+import java.util.Collection;
+
public class AdvancedWifiSettings extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener {
@@ -49,15 +55,15 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
private static final String KEY_FREQUENCY_BAND = "frequency_band";
private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
private static final String KEY_SLEEP_POLICY = "sleep_policy";
- private static final String KEY_POOR_NETWORK_DETECTION = "wifi_poor_network_detection";
private static final String KEY_SCAN_ALWAYS_AVAILABLE = "wifi_scan_always_available";
private static final String KEY_INSTALL_CREDENTIALS = "install_credentials";
+ private static final String KEY_WIFI_ASSISTANT = "wifi_assistant";
private static final String KEY_WIFI_DIRECT = "wifi_direct";
private static final String KEY_WPS_PUSH = "wps_push_button";
private static final String KEY_WPS_PIN = "wps_pin_entry";
- private static final String KEY_SUSPEND_OPTIMIZATIONS = "suspend_optimizations";
private WifiManager mWifiManager;
+ private NetworkScoreManager mNetworkScoreManager;
private IntentFilter mFilter;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -84,6 +90,8 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
mFilter = new IntentFilter();
mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mNetworkScoreManager =
+ (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE);
}
@Override
@@ -102,27 +110,14 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
}
private void initPreferences() {
- CheckBoxPreference notifyOpenNetworks =
- (CheckBoxPreference) findPreference(KEY_NOTIFY_OPEN_NETWORKS);
+ SwitchPreference notifyOpenNetworks =
+ (SwitchPreference) findPreference(KEY_NOTIFY_OPEN_NETWORKS);
notifyOpenNetworks.setChecked(Settings.Global.getInt(getContentResolver(),
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled());
- CheckBoxPreference poorNetworkDetection =
- (CheckBoxPreference) findPreference(KEY_POOR_NETWORK_DETECTION);
- if (poorNetworkDetection != null) {
- if (Utils.isWifiOnly(getActivity())) {
- getPreferenceScreen().removePreference(poorNetworkDetection);
- } else {
- poorNetworkDetection.setChecked(Global.getInt(getContentResolver(),
- Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
- WifiManager.DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED ?
- 1 : 0) == 1);
- }
- }
-
- CheckBoxPreference scanAlwaysAvailable =
- (CheckBoxPreference) findPreference(KEY_SCAN_ALWAYS_AVAILABLE);
+ SwitchPreference scanAlwaysAvailable =
+ (SwitchPreference) findPreference(KEY_SCAN_ALWAYS_AVAILABLE);
scanAlwaysAvailable.setChecked(Global.getInt(getContentResolver(),
Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1);
@@ -133,7 +128,22 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
Preference pref = findPreference(KEY_INSTALL_CREDENTIALS);
pref.setIntent(intent);
- Intent wifiDirectIntent = new Intent(getActivity(),
+ final Context context = getActivity();
+ NetworkScorerAppData scorer = WifiSettings.getWifiAssistantApp(context);
+ SwitchPreference wifiAssistant = (SwitchPreference)findPreference(KEY_WIFI_ASSISTANT);
+ if (scorer != null) {
+ final boolean checked = NetworkScorerAppManager.getActiveScorer(context) != null;
+ wifiAssistant.setSummary(getResources().getString(
+ R.string.wifi_automatically_manage_summary, scorer.mScorerName));
+ wifiAssistant.setOnPreferenceChangeListener(this);
+ wifiAssistant.setChecked(checked);
+ } else {
+ if (wifiAssistant != null) {
+ getPreferenceScreen().removePreference(wifiAssistant);
+ }
+ }
+
+ Intent wifiDirectIntent = new Intent(context,
com.android.settings.Settings.WifiP2pSettingsActivity.class);
Preference wifiDirectPref = findPreference(KEY_WIFI_DIRECT);
wifiDirectPref.setIntent(wifiDirectIntent);
@@ -142,7 +152,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
Preference wpsPushPref = findPreference(KEY_WPS_PUSH);
wpsPushPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference arg0) {
- WpsDialog wpsDialog = new WpsDialog(getActivity(), WpsInfo.PBC);
+ WpsDialog wpsDialog = new WpsDialog(context, WpsInfo.PBC);
wpsDialog.show();
return true;
}
@@ -152,17 +162,12 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
Preference wpsPinPref = findPreference(KEY_WPS_PIN);
wpsPinPref.setOnPreferenceClickListener(new OnPreferenceClickListener(){
public boolean onPreferenceClick(Preference arg0) {
- WpsDialog wpsDialog = new WpsDialog(getActivity(), WpsInfo.DISPLAY);
+ WpsDialog wpsDialog = new WpsDialog(context, WpsInfo.DISPLAY);
wpsDialog.show();
return true;
}
});
- CheckBoxPreference suspendOptimizations =
- (CheckBoxPreference) findPreference(KEY_SUSPEND_OPTIMIZATIONS);
- suspendOptimizations.setChecked(Global.getInt(getContentResolver(),
- Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
-
ListPreference frequencyPref = (ListPreference) findPreference(KEY_FREQUENCY_BAND);
if (mWifiManager.isDualBandSupported()) {
@@ -183,7 +188,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
ListPreference sleepPolicyPref = (ListPreference) findPreference(KEY_SLEEP_POLICY);
if (sleepPolicyPref != null) {
- if (Utils.isWifiOnly(getActivity())) {
+ if (Utils.isWifiOnly(context)) {
sleepPolicyPref.setEntries(R.array.wifi_sleep_policy_entries_wifi_only);
}
sleepPolicyPref.setOnPreferenceChangeListener(this);
@@ -228,19 +233,11 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
if (KEY_NOTIFY_OPEN_NETWORKS.equals(key)) {
Global.putInt(getContentResolver(),
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
- ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
- } else if (KEY_POOR_NETWORK_DETECTION.equals(key)) {
- Global.putInt(getContentResolver(),
- Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
- ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
- } else if (KEY_SUSPEND_OPTIMIZATIONS.equals(key)) {
- Global.putInt(getContentResolver(),
- Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED,
- ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
+ ((SwitchPreference) preference).isChecked() ? 1 : 0);
} else if (KEY_SCAN_ALWAYS_AVAILABLE.equals(key)) {
Global.putInt(getContentResolver(),
Global.WIFI_SCAN_ALWAYS_AVAILABLE,
- ((CheckBoxPreference) preference).isChecked() ? 1 : 0);
+ ((SwitchPreference) preference).isChecked() ? 1 : 0);
} else {
return super.onPreferenceTreeClick(screen, preference);
}
@@ -249,6 +246,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final Context context = getActivity();
String key = preference.getKey();
if (KEY_FREQUENCY_BAND.equals(key)) {
@@ -257,10 +255,32 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
mWifiManager.setFrequencyBand(value, true);
updateFrequencyBandSummary(preference, value);
} catch (NumberFormatException e) {
- Toast.makeText(getActivity(), R.string.wifi_setting_frequency_band_error,
+ Toast.makeText(context, R.string.wifi_setting_frequency_band_error,
Toast.LENGTH_SHORT).show();
return false;
}
+ } else if (KEY_WIFI_ASSISTANT.equals(key)) {
+ if (((Boolean)newValue).booleanValue() == false) {
+ mNetworkScoreManager.setActiveScorer(null);
+ return true;
+ }
+
+ NetworkScorerAppData wifiAssistant = WifiSettings.getWifiAssistantApp(context);
+ Intent intent = new Intent();
+ if (wifiAssistant.mConfigurationActivityClassName != null) {
+ // App has a custom configuration activity; launch that.
+ // This custom activity will be responsible for launching the system
+ // dialog.
+ intent.setClassName(wifiAssistant.mPackageName,
+ wifiAssistant.mConfigurationActivityClassName);
+ } else {
+ // Fall back on the system dialog.
+ intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
+ intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
+ wifiAssistant.mPackageName);
+ }
+
+ startActivity(intent);
}
if (KEY_SLEEP_POLICY.equals(key)) {
@@ -270,7 +290,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
Integer.parseInt(stringValue));
updateSleepPolicySummary(preference, stringValue);
} catch (NumberFormatException e) {
- Toast.makeText(getActivity(), R.string.wifi_setting_sleep_policy_error,
+ Toast.makeText(context, R.string.wifi_setting_sleep_policy_error,
Toast.LENGTH_SHORT).show();
return false;
}
@@ -280,18 +300,19 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
}
private void refreshWifiInfo() {
+ final Context context = getActivity();
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS);
String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
- : getActivity().getString(R.string.status_unavailable));
+ : context.getString(R.string.status_unavailable));
wifiMacAddressPref.setSelectable(false);
Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
- String ipAddress = Utils.getWifiIpAddresses(getActivity());
+ String ipAddress = Utils.getWifiIpAddresses(context);
wifiIpAddressPref.setSummary(ipAddress == null ?
- getActivity().getString(R.string.status_unavailable) : ipAddress);
+ context.getString(R.string.status_unavailable) : ipAddress);
wifiIpAddressPref.setSelectable(false);
}
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index a91d153..10c86dc 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -53,6 +53,9 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
private Bundle mAccessPointSavedState;
private AccessPoint mSelectedAccessPoint;
+ // Instance state key
+ private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,6 +72,13 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+
+ if (savedInstanceState != null) {
+ if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {
+ mAccessPointSavedState =
+ savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);
+ }
+ }
}
private void initPreferences() {
@@ -150,6 +160,11 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case WifiSettings.WIFI_DIALOG_ID:
+ if (mDlgAccessPoint == null) { // For re-launch from saved state
+ mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState);
+ // Reset the saved access point data
+ mAccessPointSavedState = null;
+ }
mSelectedAccessPoint = mDlgAccessPoint;
mDialog = new WifiDialog(getActivity(), this, mDlgAccessPoint, false);
return mDialog;
@@ -159,6 +174,20 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ // If the dialog is showing, save its state.
+ if (mDialog != null && mDialog.isShowing()) {
+ if (mDlgAccessPoint != null) {
+ mAccessPointSavedState = new Bundle();
+ mDlgAccessPoint.saveWifiState(mAccessPointSavedState);
+ outState.putBundle(SAVE_DIALOG_ACCESS_POINT_STATE, mAccessPointSavedState);
+ }
+ }
+ }
+
+ @Override
public void onClick(DialogInterface dialogInterface, int button) {
if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) {
mWifiManager.forget(mSelectedAccessPoint.networkId, null);
diff --git a/src/com/android/settings/wifi/WifiApEnabler.java b/src/com/android/settings/wifi/WifiApEnabler.java
index 9a3b49d..fc34f3b 100644
--- a/src/com/android/settings/wifi/WifiApEnabler.java
+++ b/src/com/android/settings/wifi/WifiApEnabler.java
@@ -33,7 +33,7 @@ import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.preference.CheckBoxPreference;
+import android.preference.SwitchPreference;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -41,7 +41,7 @@ import android.widget.Toast;
public class WifiApEnabler {
private final Context mContext;
- private final CheckBoxPreference mCheckBox;
+ private final SwitchPreference mSwitch;
private final CharSequence mOriginalSummary;
private WifiManager mWifiManager;
@@ -66,17 +66,17 @@ public class WifiApEnabler {
ConnectivityManager.EXTRA_ERRORED_TETHER);
updateTetherState(available.toArray(), active.toArray(), errored.toArray());
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
- enableWifiCheckBox();
+ enableWifiSwitch();
}
}
};
- public WifiApEnabler(Context context, CheckBoxPreference checkBox) {
+ public WifiApEnabler(Context context, SwitchPreference switchPreference) {
mContext = context;
- mCheckBox = checkBox;
- mOriginalSummary = checkBox.getSummary();
- checkBox.setPersistent(false);
+ mSwitch = switchPreference;
+ mOriginalSummary = switchPreference.getSummary();
+ switchPreference.setPersistent(false);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -90,21 +90,21 @@ public class WifiApEnabler {
public void resume() {
mContext.registerReceiver(mReceiver, mIntentFilter);
- enableWifiCheckBox();
+ enableWifiSwitch();
}
public void pause() {
mContext.unregisterReceiver(mReceiver);
}
- private void enableWifiCheckBox() {
+ private void enableWifiSwitch() {
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
if(!isAirplaneMode) {
- mCheckBox.setEnabled(true);
+ mSwitch.setEnabled(true);
} else {
- mCheckBox.setSummary(mOriginalSummary);
- mCheckBox.setEnabled(false);
+ mSwitch.setSummary(mOriginalSummary);
+ mSwitch.setEnabled(false);
}
}
@@ -122,9 +122,9 @@ public class WifiApEnabler {
if (mWifiManager.setWifiApEnabled(null, enable)) {
/* Disable here, enabled on receiving success broadcast */
- mCheckBox.setEnabled(false);
+ mSwitch.setEnabled(false);
} else {
- mCheckBox.setSummary(R.string.wifi_error);
+ mSwitch.setSummary(R.string.wifi_error);
}
/**
@@ -147,7 +147,7 @@ public class WifiApEnabler {
public void updateConfigSummary(WifiConfiguration wifiConfig) {
String s = mContext.getString(
com.android.internal.R.string.wifi_tether_configure_ssid_default);
- mCheckBox.setSummary(String.format(
+ mSwitch.setSummary(String.format(
mContext.getString(R.string.wifi_tether_enabled_subtext),
(wifiConfig == null) ? s : wifiConfig.SSID));
}
@@ -173,38 +173,38 @@ public class WifiApEnabler {
WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
updateConfigSummary(wifiConfig);
} else if (wifiErrored) {
- mCheckBox.setSummary(R.string.wifi_error);
+ mSwitch.setSummary(R.string.wifi_error);
}
}
private void handleWifiApStateChanged(int state) {
switch (state) {
case WifiManager.WIFI_AP_STATE_ENABLING:
- mCheckBox.setSummary(R.string.wifi_tether_starting);
- mCheckBox.setEnabled(false);
+ mSwitch.setSummary(R.string.wifi_tether_starting);
+ mSwitch.setEnabled(false);
break;
case WifiManager.WIFI_AP_STATE_ENABLED:
/**
* Summary on enable is handled by tether
* broadcast notice
*/
- mCheckBox.setChecked(true);
+ mSwitch.setChecked(true);
/* Doesnt need the airplane check */
- mCheckBox.setEnabled(true);
+ mSwitch.setEnabled(true);
break;
case WifiManager.WIFI_AP_STATE_DISABLING:
- mCheckBox.setSummary(R.string.wifi_tether_stopping);
- mCheckBox.setEnabled(false);
+ mSwitch.setSummary(R.string.wifi_tether_stopping);
+ mSwitch.setEnabled(false);
break;
case WifiManager.WIFI_AP_STATE_DISABLED:
- mCheckBox.setChecked(false);
- mCheckBox.setSummary(mOriginalSummary);
- enableWifiCheckBox();
+ mSwitch.setChecked(false);
+ mSwitch.setSummary(mOriginalSummary);
+ enableWifiSwitch();
break;
default:
- mCheckBox.setChecked(false);
- mCheckBox.setSummary(R.string.wifi_error);
- enableWifiCheckBox();
+ mSwitch.setChecked(false);
+ mSwitch.setSummary(R.string.wifi_error);
+ enableWifiSwitch();
}
}
}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index fc2276a..3b07b9f 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -24,11 +24,11 @@ import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
@@ -61,6 +61,7 @@ import com.android.settings.ProxySelector;
import com.android.settings.R;
import java.net.InetAddress;
+import java.net.Inet4Address;
import java.util.Iterator;
/**
@@ -137,7 +138,8 @@ public class WifiConfigController implements TextWatcher,
private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED;
private ProxySettings mProxySettings = ProxySettings.UNASSIGNED;
- private LinkProperties mLinkProperties = new LinkProperties();
+ private ProxyInfo mHttpProxy = null;
+ private StaticIpConfiguration mStaticIpConfiguration = null;
private String[] mLevels;
private boolean mEdit;
@@ -216,13 +218,15 @@ public class WifiConfigController implements TextWatcher,
if (config.getIpAssignment() == IpAssignment.STATIC) {
mIpSettingsSpinner.setSelection(STATIC_IP);
showAdvancedFields = true;
+ // Display IP address.
+ StaticIpConfiguration staticConfig = config.getStaticIpConfiguration();
+ if (staticConfig != null && staticConfig.ipAddress != null) {
+ addRow(group, R.string.wifi_ip_address,
+ staticConfig.ipAddress.getAddress().getHostAddress());
+ }
} else {
mIpSettingsSpinner.setSelection(DHCP);
}
- //Display IP addresses
- for(InetAddress a : config.getLinkProperties().getAddresses()) {
- addRow(group, R.string.wifi_ip_address, a.getHostAddress());
- }
if (config.getProxySettings() == ProxySettings.STATIC) {
@@ -462,19 +466,20 @@ public class WifiConfigController implements TextWatcher,
}
config.setIpConfiguration(
- new IpConfiguration(mIpAssignment, mProxySettings, mLinkProperties));
+ new IpConfiguration(mIpAssignment, mProxySettings,
+ mStaticIpConfiguration, mHttpProxy));
return config;
}
private boolean ipAndProxyFieldsAreValid() {
- mLinkProperties.clear();
mIpAssignment = (mIpSettingsSpinner != null &&
mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
IpAssignment.STATIC : IpAssignment.DHCP;
if (mIpAssignment == IpAssignment.STATIC) {
- int result = validateIpConfigFields(mLinkProperties);
+ mStaticIpConfiguration = new StaticIpConfiguration();
+ int result = validateIpConfigFields(mStaticIpConfiguration);
if (result != 0) {
return false;
}
@@ -482,6 +487,7 @@ public class WifiConfigController implements TextWatcher,
final int selectedPosition = mProxySettingsSpinner.getSelectedItemPosition();
mProxySettings = ProxySettings.NONE;
+ mHttpProxy = null;
if (selectedPosition == PROXY_STATIC && mProxyHostView != null) {
mProxySettings = ProxySettings.STATIC;
String host = mProxyHostView.getText().toString();
@@ -496,8 +502,7 @@ public class WifiConfigController implements TextWatcher,
result = R.string.proxy_error_invalid_port;
}
if (result == 0) {
- ProxyInfo proxyProperties= new ProxyInfo(host, port, exclusionList);
- mLinkProperties.setHttpProxy(proxyProperties);
+ mHttpProxy = new ProxyInfo(host, port, exclusionList);
} else {
return false;
}
@@ -511,22 +516,27 @@ public class WifiConfigController implements TextWatcher,
if (uri == null) {
return false;
}
- ProxyInfo proxyInfo = new ProxyInfo(uri);
- mLinkProperties.setHttpProxy(proxyInfo);
+ mHttpProxy = new ProxyInfo(uri);
}
return true;
}
- private int validateIpConfigFields(LinkProperties linkProperties) {
+ private Inet4Address getIPv4Address(String text) {
+ try {
+ return (Inet4Address) NetworkUtils.numericToInetAddress(text);
+ } catch (IllegalArgumentException|ClassCastException e) {
+ return null;
+ }
+ }
+
+ private int validateIpConfigFields(StaticIpConfiguration staticIpConfiguration) {
if (mIpAddressView == null) return 0;
String ipAddr = mIpAddressView.getText().toString();
if (TextUtils.isEmpty(ipAddr)) return R.string.wifi_ip_settings_invalid_ip_address;
- InetAddress inetAddr = null;
- try {
- inetAddr = NetworkUtils.numericToInetAddress(ipAddr);
- } catch (IllegalArgumentException e) {
+ Inet4Address inetAddr = getIPv4Address(ipAddr);
+ if (inetAddr == null) {
return R.string.wifi_ip_settings_invalid_ip_address;
}
@@ -536,7 +546,7 @@ public class WifiConfigController implements TextWatcher,
if (networkPrefixLength < 0 || networkPrefixLength > 32) {
return R.string.wifi_ip_settings_invalid_network_prefix_length;
}
- linkProperties.addLinkAddress(new LinkAddress(inetAddr, networkPrefixLength));
+ staticIpConfiguration.ipAddress = new LinkAddress(inetAddr, networkPrefixLength);
} catch (NumberFormatException e) {
// Set the hint as default after user types in ip address
mNetworkPrefixLengthView.setText(mConfigUi.getContext().getString(
@@ -555,13 +565,11 @@ public class WifiConfigController implements TextWatcher,
} catch (java.net.UnknownHostException u) {
}
} else {
- InetAddress gatewayAddr = null;
- try {
- gatewayAddr = NetworkUtils.numericToInetAddress(gateway);
- } catch (IllegalArgumentException e) {
+ InetAddress gatewayAddr = getIPv4Address(gateway);
+ if (gatewayAddr == null) {
return R.string.wifi_ip_settings_invalid_gateway;
}
- linkProperties.addRoute(new RouteInfo(gatewayAddr));
+ staticIpConfiguration.gateway = gatewayAddr;
}
String dns = mDns1View.getText().toString();
@@ -571,22 +579,20 @@ public class WifiConfigController implements TextWatcher,
//If everything else is valid, provide hint as a default option
mDns1View.setText(mConfigUi.getContext().getString(R.string.wifi_dns1_hint));
} else {
- try {
- dnsAddr = NetworkUtils.numericToInetAddress(dns);
- } catch (IllegalArgumentException e) {
+ dnsAddr = getIPv4Address(dns);
+ if (dnsAddr == null) {
return R.string.wifi_ip_settings_invalid_dns;
}
- linkProperties.addDnsServer(dnsAddr);
+ staticIpConfiguration.dnsServers.add(dnsAddr);
}
if (mDns2View.length() > 0) {
dns = mDns2View.getText().toString();
- try {
- dnsAddr = NetworkUtils.numericToInetAddress(dns);
- } catch (IllegalArgumentException e) {
+ dnsAddr = getIPv4Address(dns);
+ if (dnsAddr == null) {
return R.string.wifi_ip_settings_invalid_dns;
}
- linkProperties.addDnsServer(dnsAddr);
+ staticIpConfiguration.dnsServers.add(dnsAddr);
}
return 0;
}
@@ -797,28 +803,26 @@ public class WifiConfigController implements TextWatcher,
mDns2View.addTextChangedListener(this);
}
if (config != null) {
- LinkProperties linkProperties = config.getLinkProperties();
- Iterator<LinkAddress> iterator = linkProperties.getLinkAddresses().iterator();
- if (iterator.hasNext()) {
- LinkAddress linkAddress = iterator.next();
- mIpAddressView.setText(linkAddress.getAddress().getHostAddress());
- mNetworkPrefixLengthView.setText(Integer.toString(linkAddress
- .getNetworkPrefixLength()));
- }
+ StaticIpConfiguration staticConfig = config.getStaticIpConfiguration();
+ if (staticConfig != null) {
+ if (staticConfig.ipAddress != null) {
+ mIpAddressView.setText(
+ staticConfig.ipAddress.getAddress().getHostAddress());
+ mNetworkPrefixLengthView.setText(Integer.toString(staticConfig.ipAddress
+ .getNetworkPrefixLength()));
+ }
- for (RouteInfo route : linkProperties.getRoutes()) {
- if (route.isDefaultRoute()) {
- mGatewayView.setText(route.getGateway().getHostAddress());
- break;
+ if (staticConfig.gateway != null) {
+ mGatewayView.setText(staticConfig.gateway.getHostAddress());
}
- }
- Iterator<InetAddress> dnsIterator = linkProperties.getDnsServers().iterator();
- if (dnsIterator.hasNext()) {
- mDns1View.setText(dnsIterator.next().getHostAddress());
- }
- if (dnsIterator.hasNext()) {
- mDns2View.setText(dnsIterator.next().getHostAddress());
+ Iterator<InetAddress> dnsIterator = staticConfig.dnsServers.iterator();
+ if (dnsIterator.hasNext()) {
+ mDns1View.setText(dnsIterator.next().getHostAddress());
+ }
+ if (dnsIterator.hasNext()) {
+ mDns2View.setText(dnsIterator.next().getHostAddress());
+ }
}
}
} else {
@@ -848,7 +852,7 @@ public class WifiConfigController implements TextWatcher,
mProxyExclusionListView.addTextChangedListener(this);
}
if (config != null) {
- ProxyInfo proxyProperties = config.getLinkProperties().getHttpProxy();
+ ProxyInfo proxyProperties = config.getHttpProxy();
if (proxyProperties != null) {
mProxyHostView.setText(proxyProperties.getHost());
mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
@@ -865,7 +869,7 @@ public class WifiConfigController implements TextWatcher,
mProxyPacView.addTextChangedListener(this);
}
if (config != null) {
- ProxyInfo proxyInfo = config.getLinkProperties().getHttpProxy();
+ ProxyInfo proxyInfo = config.getHttpProxy();
if (proxyInfo != null) {
mProxyPacView.setText(proxyInfo.getPacFileUrl().toString());
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index e83cb06..50789b8 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -27,7 +27,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.location.LocationManager;
@@ -42,6 +41,7 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WpsInfo;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -50,6 +50,7 @@ import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -100,12 +101,7 @@ public class WifiSettings extends RestrictedSettingsFragment
private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
- private static final String KEY_ASSISTANT_DISMISS_TIME = "wifi_assistant_dismiss_time";
- private static final String KEY_ASSISTANT_START_TIME = "wifi_assistant_start_time";
-
- private static final long MILI_SECONDS_30_DAYS = 30L * 24L * 60L * 60L * 1000L;
- private static final long MILI_SECONDS_90_DAYS = MILI_SECONDS_30_DAYS * 3L;
- private static final long MILI_SECONDS_180_DAYS = MILI_SECONDS_90_DAYS * 2L;
+ private static final String KEY_ASSISTANT_DISMISS_PLATFORM = "assistant_dismiss_platform";
public static final int WIFI_DIALOG_ID = 1;
/* package */ static final int WPS_PBC_DIALOG_ID = 2;
@@ -129,7 +125,6 @@ public class WifiSettings extends RestrictedSettingsFragment
private WifiManager.ActionListener mConnectListener;
private WifiManager.ActionListener mSaveListener;
private WifiManager.ActionListener mForgetListener;
- private boolean mP2pSupported;
private WifiEnabler mWifiEnabler;
// An access point being editted is stored here.
@@ -156,7 +151,7 @@ public class WifiSettings extends RestrictedSettingsFragment
private boolean mDlgEdit;
private AccessPoint mDlgAccessPoint;
private Bundle mAccessPointSavedState;
- private Preference mWifiAssistantPreference;
+ private View mWifiAssistantCard;
private NetworkScorerAppData mWifiAssistantApp;
/** verbose logging flag. this flag is set thru developer debugging options
@@ -165,52 +160,6 @@ public class WifiSettings extends RestrictedSettingsFragment
/* End of "used in Wifi Setup context" */
- /** Holds the Wifi Assistant Card. */
- private class WifiAssistantPreference extends Preference {
- public WifiAssistantPreference() {
- super(getActivity());
- setLayoutResource(R.layout.wifi_assistant_card);
- }
-
- @Override
- public void onBindView(View view) {
- super.onBindView(view);
- Button setup = (Button)view.findViewById(R.id.setup);
- Button noThanks = (Button)view.findViewById(R.id.no_thanks_button);
-
- if (setup != null && noThanks != null) {
- setup.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- if (mWifiAssistantApp.mConfigurationActivityClassName != null) {
- // App has a custom configuration activity; launch that.
- // This custom activity will be responsible for launching the system
- // dialog.
- intent.setClassName(mWifiAssistantApp.mPackageName,
- mWifiAssistantApp.mConfigurationActivityClassName);
- } else {
- // Fall back on the system dialog.
- intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
- intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
- mWifiAssistantApp.mPackageName);
- }
- startActivityForResult(intent, REQUEST_ENABLE_WIFI_ASSISTANT);
- }
- });
-
- noThanks.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- setWifiAssistantTimeout();
- getPreferenceScreen().removePreference(WifiAssistantPreference.this);
- mWifiAssistantApp = null;
- }
- });
- }
- }
- }
-
/** A restricted multimap for use in constructAccessPoints */
private static class Multimap<K,V> {
private final HashMap<K,List<V>> store = new HashMap<K,List<V>>();
@@ -285,7 +234,7 @@ public class WifiSettings extends RestrictedSettingsFragment
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- handleEvent(context, intent);
+ handleEvent(intent);
}
};
@@ -296,7 +245,6 @@ public class WifiSettings extends RestrictedSettingsFragment
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- mP2pSupported = getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mConnectListener = new WifiManager.ActionListener() {
@@ -347,7 +295,7 @@ public class WifiSettings extends RestrictedSettingsFragment
if (savedInstanceState != null) {
mDlgEdit = savedInstanceState.getBoolean(SAVE_DIALOG_EDIT_MODE);
if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {
- mAccessPointSavedState =
+ mAccessPointSavedState =
savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);
}
}
@@ -373,8 +321,7 @@ public class WifiSettings extends RestrictedSettingsFragment
prepareWifiAssistantCard();
- mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
- getListView().setEmptyView(mEmptyView);
+ mEmptyView = initEmptyView();
registerForContextMenu(getListView());
setHasOptionsMenu(true);
}
@@ -383,8 +330,8 @@ public class WifiSettings extends RestrictedSettingsFragment
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (requestCode == REQUEST_ENABLE_WIFI_ASSISTANT) {
if (resultCode == Activity.RESULT_OK) {
- setWifiAssistantTimeout();
- getPreferenceScreen().removePreference(mWifiAssistantPreference);
+ disableWifiAssistantCardUntilPlatformUpgrade();
+ getListView().removeHeaderView(mWifiAssistantCard);
mWifiAssistantApp = null;
}
} else {
@@ -706,8 +653,9 @@ public class WifiSettings extends RestrictedSettingsFragment
addMessagePreference(R.string.wifi_empty_list_wifi_on);
}
+ getListView().removeHeaderView(mWifiAssistantCard);
if (mWifiAssistantApp != null) {
- getPreferenceScreen().addPreference(mWifiAssistantPreference);
+ getListView().addHeaderView(mWifiAssistantCard);
}
for (AccessPoint accessPoint : accessPoints) {
@@ -732,64 +680,106 @@ public class WifiSettings extends RestrictedSettingsFragment
}
}
- private boolean prepareWifiAssistantCard() {
- if (mWifiAssistantPreference == null) {
- mWifiAssistantPreference = new WifiAssistantPreference();
+ /**
+ * Returns the Network Scorer for the Wifi Assistant App.
+ */
+ public static NetworkScorerAppData getWifiAssistantApp(Context context) {
+ Collection<NetworkScorerAppData> scorers =
+ NetworkScorerAppManager.getAllValidScorers(context);
+
+ if (scorers.isEmpty()) {
+ return null;
}
+ // TODO: b/13780935 - Implement proper scorer selection. Rather than pick the first
+ // scorer on the system, we should allow the user to select one.
+ return scorers.iterator().next();
+ }
+
+ private void prepareWifiAssistantCard() {
if (getActivity() instanceof WifiPickerActivity) {
- return false;
+ return;
}
if (NetworkScorerAppManager.getActiveScorer(getActivity()) != null) {
// A scorer is already enabled; don't show the card.
- return false;
+ return;
}
Collection<NetworkScorerAppData> scorers =
NetworkScorerAppManager.getAllValidScorers(getActivity());
if (scorers.isEmpty()) {
// No scorers are available to enable; don't show the card.
- return false;
+ return;
}
SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
- long lastTimeoutEndTime = sharedPreferences.getLong(KEY_ASSISTANT_START_TIME, 0);
- long dismissTime = sharedPreferences.getLong(KEY_ASSISTANT_DISMISS_TIME, 0);
-
- boolean shouldShow = ((System.currentTimeMillis() - lastTimeoutEndTime) > dismissTime);
- if (shouldShow) {
- // TODO: b/13780935 - Implement proper scorer selection. Rather than pick the first
- // scorer on the system, we should allow the user to select one.
- mWifiAssistantApp = scorers.iterator().next();
+ int lastDismissPlatform = sharedPreferences.getInt(KEY_ASSISTANT_DISMISS_PLATFORM, 0);
+
+ if (Build.VERSION.SDK_INT <= lastDismissPlatform) {
+ // User has dismissed the Wi-Fi assistant card on this SDK release. Suppress the card
+ // until the next major platform upgrade.
+ return;
+ }
+
+ // TODO: b/13780935 - Implement proper scorer selection. Rather than pick the first
+ // scorer on the system, we should allow the user to select one.
+ mWifiAssistantApp = scorers.iterator().next();
+
+ if (mWifiAssistantCard == null) {
+ mWifiAssistantCard = LayoutInflater.from(getActivity())
+ .inflate(R.layout.wifi_assistant_card, getListView(), false);
+ Button setup = (Button) mWifiAssistantCard.findViewById(R.id.setup);
+ Button noThanks = (Button) mWifiAssistantCard.findViewById(R.id.no_thanks_button);
+
+ if (setup != null && noThanks != null) {
+ setup.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent();
+ if (mWifiAssistantApp.mConfigurationActivityClassName != null) {
+ // App has a custom configuration activity; launch that.
+ // This custom activity will be responsible for launching the system
+ // dialog.
+ intent.setClassName(mWifiAssistantApp.mPackageName,
+ mWifiAssistantApp.mConfigurationActivityClassName);
+ } else {
+ // Fall back on the system dialog.
+ intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
+ intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
+ mWifiAssistantApp.mPackageName);
+ }
+ startActivityForResult(intent, REQUEST_ENABLE_WIFI_ASSISTANT);
+ }
+ });
+
+ noThanks.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ disableWifiAssistantCardUntilPlatformUpgrade();
+ getListView().removeHeaderView(mWifiAssistantCard);
+ mWifiAssistantApp = null;
+ }
+ });
+ }
}
- return shouldShow;
}
- private void setWifiAssistantTimeout() {
+ private void disableWifiAssistantCardUntilPlatformUpgrade() {
SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
SharedPreferences.Editor editor = sharedPreferences.edit();
- long dismissTime = sharedPreferences.getLong(KEY_ASSISTANT_DISMISS_TIME, 0);
-
- if (dismissTime == 0) {
- dismissTime = MILI_SECONDS_30_DAYS;
- } else if (dismissTime == MILI_SECONDS_30_DAYS) {
- dismissTime = MILI_SECONDS_90_DAYS;
- } else if (dismissTime == MILI_SECONDS_90_DAYS) {
- dismissTime = MILI_SECONDS_180_DAYS;
- } else if (dismissTime == MILI_SECONDS_180_DAYS) {
- dismissTime = java.lang.Long.MAX_VALUE;
- }
-
- editor.putLong(KEY_ASSISTANT_DISMISS_TIME, dismissTime);
- editor.putLong(KEY_ASSISTANT_START_TIME, System.currentTimeMillis());
+ editor.putInt(KEY_ASSISTANT_DISMISS_PLATFORM, Build.VERSION.SDK_INT);
editor.apply();
}
+ protected TextView initEmptyView() {
+ TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
+ getListView().setEmptyView(emptyView);
+ return emptyView;
+ }
+
private void setOffMessage() {
if (mEmptyView != null) {
- mEmptyView.setCompoundDrawablesWithIntrinsicBounds(0,
- R.drawable.ic_wifi_emptystate, 0, 0);
mEmptyView.setText(R.string.wifi_empty_list_wifi_off);
if (android.provider.Settings.Global.getInt(getActivity().getContentResolver(),
android.provider.Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1) {
@@ -823,7 +813,13 @@ public class WifiSettings extends RestrictedSettingsFragment
final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
if (configs != null) {
- savedNetworksExist = (configs.size() > 0);
+ // Update "Saved Networks" menu option.
+ if (savedNetworksExist != (configs.size() > 0)) {
+ savedNetworksExist = !savedNetworksExist;
+ if (context instanceof Activity) {
+ ((Activity) context).invalidateOptionsMenu();
+ }
+ }
for (WifiConfiguration config : configs) {
AccessPoint accessPoint = new AccessPoint(context, config);
if (lastInfo != null && lastState != null) {
@@ -861,7 +857,7 @@ public class WifiSettings extends RestrictedSettingsFragment
return accessPoints;
}
- private void handleEvent(Context context, Intent intent) {
+ private void handleEvent(Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index b52aaa7..c4a5c96 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -18,18 +18,19 @@ package com.android.settings.wifi;
import android.content.Intent;
import android.content.res.TypedArray;
+import android.database.DataSetObserver;
import android.net.wifi.WifiConfiguration;
import android.os.Bundle;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.ImageButton;
+import android.widget.AbsListView.LayoutParams;
+import android.widget.ListAdapter;
import android.widget.ListView;
-import android.widget.PopupMenu;
-import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.TextView;
import com.android.settings.R;
@@ -47,6 +48,11 @@ public class WifiSettingsForSetupWizard extends WifiSettings {
// show a text regarding data charges when wifi connection is required during setup wizard
protected static final String EXTRA_SHOW_WIFI_REQUIRED_INFO = "wifi_show_wifi_required_info";
+ private View mAddOtherNetworkItem;
+ private ListAdapter mAdapter;
+ private TextView mEmptyFooter;
+ private boolean mListLastEmpty = false;
+
@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -60,9 +66,9 @@ public class WifiSettingsForSetupWizard extends WifiSettings {
list.addHeaderView(header, null, false);
}
- final View other = inflater.inflate(R.layout.setup_wifi_add_network, list, false);
- list.addFooterView(other, null, true);
- other.setOnClickListener(new OnClickListener() {
+ mAddOtherNetworkItem = inflater.inflate(R.layout.setup_wifi_add_network, list, false);
+ list.addFooterView(mAddOtherNetworkItem, null, true);
+ mAddOtherNetworkItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mWifiManager.isWifiEnabled()) {
@@ -92,6 +98,15 @@ public class WifiSettingsForSetupWizard extends WifiSettings {
if (hasNextButton()) {
getNextButton().setVisibility(View.GONE);
}
+
+ mAdapter = getPreferenceScreen().getRootAdapter();
+ mAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ updateFooter();
+ }
+ });
}
@Override
@@ -133,4 +148,30 @@ public class WifiSettingsForSetupWizard extends WifiSettings {
activity.networkSelected();
super.connect(networkId);
}
+
+ @Override
+ protected TextView initEmptyView() {
+ mEmptyFooter = new TextView(getActivity());
+ mEmptyFooter.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT));
+ mEmptyFooter.setGravity(Gravity.CENTER);
+ mEmptyFooter.setCompoundDrawablesWithIntrinsicBounds(0,
+ R.drawable.ic_wifi_emptystate, 0,0);
+ return mEmptyFooter;
+ }
+
+ protected void updateFooter() {
+ final boolean isEmpty = mAdapter.isEmpty();
+ if (isEmpty != mListLastEmpty) {
+ final ListView list = getListView();
+ if (isEmpty) {
+ list.removeFooterView(mAddOtherNetworkItem);
+ list.addFooterView(mEmptyFooter, null, false);
+ } else {
+ list.removeFooterView(mEmptyFooter);
+ list.addFooterView(mAddOtherNetworkItem, null, true);
+ }
+ mListLastEmpty = isEmpty;
+ }
+ }
}
diff --git a/src/com/android/settings/wifi/WifiSetupActivity.java b/src/com/android/settings/wifi/WifiSetupActivity.java
index 3dd7a03..5452a03 100644
--- a/src/com/android/settings/wifi/WifiSetupActivity.java
+++ b/src/com/android/settings/wifi/WifiSetupActivity.java
@@ -218,6 +218,7 @@ public class WifiSetupActivity extends WifiPickerActivity
final Intent nextIntent = new Intent(ACTION_NEXT);
nextIntent.putExtra(EXTRA_SCRIPT_URI, intent.getStringExtra(EXTRA_SCRIPT_URI));
nextIntent.putExtra(EXTRA_ACTION_ID, intent.getStringExtra(EXTRA_ACTION_ID));
+ nextIntent.putExtra(EXTRA_THEME, intent.getStringExtra(EXTRA_THEME));
nextIntent.putExtra(EXTRA_RESULT_CODE, resultCode);
startActivityForResult(nextIntent, NEXT_REQUEST);
}
diff --git a/src/com/android/settings/wifi/WpsDialog.java b/src/com/android/settings/wifi/WpsDialog.java
index 662d477..d0b116b 100644
--- a/src/com/android/settings/wifi/WpsDialog.java
+++ b/src/com/android/settings/wifi/WpsDialog.java
@@ -57,7 +57,7 @@ public class WpsDialog extends AlertDialog {
private static final int WPS_TIMEOUT_S = 120;
private WifiManager mWifiManager;
- private WifiManager.WpsListener mWpsListener;
+ private WifiManager.WpsCallback mWpsListener;
private int mWpsSetup;
private final IntentFilter mFilter;
@@ -81,8 +81,9 @@ public class WpsDialog extends AlertDialog {
mContext = context;
mWpsSetup = wpsSetup;
- class WpsListener implements WifiManager.WpsListener {
- public void onStartSuccess(String pin) {
+ class WpsListener extends WifiManager.WpsCallback {
+
+ public void onStarted(String pin) {
if (pin != null) {
updateDialog(DialogState.WPS_START, String.format(
mContext.getString(R.string.wifi_wps_onstart_pin), pin));
@@ -91,12 +92,13 @@ public class WpsDialog extends AlertDialog {
R.string.wifi_wps_onstart_pbc));
}
}
- public void onCompletion() {
+
+ public void onSucceeded() {
updateDialog(DialogState.WPS_COMPLETE,
mContext.getString(R.string.wifi_wps_complete));
}
- public void onFailure(int reason) {
+ public void onFailed(int reason) {
String msg;
switch (reason) {
case WifiManager.WPS_OVERLAP_ERROR: