summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/ButtonBarHandler.java2
-rw-r--r--src/com/android/settings/ChooseLockGeneric.java41
-rw-r--r--src/com/android/settings/ChooseLockPassword.java17
-rw-r--r--src/com/android/settings/ChooseLockPattern.java6
-rw-r--r--src/com/android/settings/ConfirmLockPassword.java14
-rw-r--r--src/com/android/settings/ConfirmLockPattern.java5
-rw-r--r--src/com/android/settings/CreateShortcut.java1
-rw-r--r--src/com/android/settings/CryptKeeper.java69
-rw-r--r--src/com/android/settings/CryptKeeperSettings.java3
-rw-r--r--src/com/android/settings/DataUsageSummary.java17
-rw-r--r--src/com/android/settings/DevelopmentSettings.java51
-rw-r--r--src/com/android/settings/DeviceAdminAdd.java37
-rw-r--r--src/com/android/settings/DisplaySettings.java71
-rw-r--r--src/com/android/settings/DreamSettings.java1
-rw-r--r--src/com/android/settings/EventLogTags.logtags6
-rw-r--r--src/com/android/settings/HomeSettings.java3
-rw-r--r--src/com/android/settings/MasterClear.java3
-rw-r--r--src/com/android/settings/NfcLockFragment.java125
-rw-r--r--src/com/android/settings/NotificationSettings.java255
-rw-r--r--src/com/android/settings/PairNfcDevice.java161
-rw-r--r--src/com/android/settings/ProxySelector.java61
-rw-r--r--src/com/android/settings/SecuritySettings.java50
-rw-r--r--src/com/android/settings/Settings.java1149
-rw-r--r--src/com/android/settings/SettingsActivity.java1872
-rw-r--r--src/com/android/settings/SettingsPreferenceFragment.java31
-rw-r--r--src/com/android/settings/SoundSettings.java11
-rw-r--r--src/com/android/settings/SubSettings.java5
-rw-r--r--src/com/android/settings/TrustedCredentialsSettings.java63
-rw-r--r--src/com/android/settings/UserDictionarySettings.java5
-rw-r--r--src/com/android/settings/Utils.java11
-rw-r--r--src/com/android/settings/WallpaperTypeSettings.java51
-rw-r--r--src/com/android/settings/WirelessSettings.java23
-rw-r--r--src/com/android/settings/ZenModeListPreference.java130
-rw-r--r--src/com/android/settings/ZenModeSettings.java294
-rw-r--r--src/com/android/settings/accessibility/AccessibilitySettings.java140
-rw-r--r--src/com/android/settings/accessibility/CaptionPropertiesFragment.java98
-rw-r--r--src/com/android/settings/accessibility/EdgeTypePreference.java6
-rw-r--r--src/com/android/settings/accessibility/PresetPreference.java5
-rw-r--r--src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java65
-rw-r--r--src/com/android/settings/accessibility/ToggleContrastPreferenceFragment.java121
-rw-r--r--src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java114
-rw-r--r--src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java100
-rw-r--r--src/com/android/settings/accessibility/ToggleInversionPreferenceFragment.java105
-rw-r--r--src/com/android/settings/accounts/AccountPreferenceBase.java1
-rw-r--r--src/com/android/settings/accounts/AddAccountSettings.java1
-rw-r--r--src/com/android/settings/accounts/ManageAccountsSettings.java6
-rw-r--r--src/com/android/settings/accounts/SyncSettingsActivity.java10
-rw-r--r--src/com/android/settings/applications/AppOpsCategory.java6
-rw-r--r--src/com/android/settings/applications/AppOpsDetails.java6
-rwxr-xr-xsrc/com/android/settings/applications/InstalledAppDetails.java6
-rw-r--r--src/com/android/settings/applications/InstalledAppDetailsTop.java24
-rw-r--r--src/com/android/settings/applications/ManageApplications.java10
-rw-r--r--src/com/android/settings/applications/ProcStatsEntry.java35
-rw-r--r--src/com/android/settings/applications/ProcessStatsDetail.java2
-rw-r--r--src/com/android/settings/applications/ProcessStatsUi.java87
-rw-r--r--src/com/android/settings/applications/RunningProcessesView.java8
-rw-r--r--src/com/android/settings/bluetooth/BluetoothAdvertisingEnabler.java47
-rw-r--r--src/com/android/settings/bluetooth/BluetoothAdvertisingFragment.java103
-rwxr-xr-xsrc/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java46
-rw-r--r--src/com/android/settings/bluetooth/BluetoothEnabler.java8
-rw-r--r--src/com/android/settings/bluetooth/BluetoothLocalDevicePreference.java46
-rw-r--r--src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java4
-rwxr-xr-xsrc/com/android/settings/bluetooth/BluetoothSettings.java106
-rw-r--r--src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java2
-rw-r--r--src/com/android/settings/bluetooth/LocalBluetoothAdapter.java11
-rw-r--r--src/com/android/settings/bluetooth/LocalBluetoothManager.java9
-rw-r--r--src/com/android/settings/bluetooth/LocalBluetoothPreferences.java17
-rw-r--r--src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java100
-rw-r--r--src/com/android/settings/bluetooth/RequestPermissionActivity.java86
-rw-r--r--src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java16
-rwxr-xr-xsrc/com/android/settings/bluetooth/Utils.java18
-rw-r--r--src/com/android/settings/dashboard/DashboardSummary.java291
-rw-r--r--src/com/android/settings/deviceinfo/Memory.java6
-rw-r--r--src/com/android/settings/deviceinfo/Status.java27
-rw-r--r--src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java4
-rw-r--r--src/com/android/settings/fuelgauge/BatteryEntry.java304
-rw-r--r--src/com/android/settings/fuelgauge/BatteryHistoryChart.java8
-rw-r--r--src/com/android/settings/fuelgauge/BatterySipper.java242
-rw-r--r--src/com/android/settings/fuelgauge/BatteryStatsHelper.java836
-rw-r--r--src/com/android/settings/fuelgauge/PowerGaugePreference.java9
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageDetail.java227
-rw-r--r--src/com/android/settings/fuelgauge/PowerUsageSummary.java105
-rw-r--r--src/com/android/settings/indexer/Index.java524
-rw-r--r--src/com/android/settings/indexer/IndexDatabaseHelper.java171
-rw-r--r--src/com/android/settings/indexer/Indexable.java52
-rw-r--r--src/com/android/settings/indexer/IndexableData.java45
-rw-r--r--src/com/android/settings/indexer/IndexableRef.java46
-rw-r--r--src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java6
-rw-r--r--src/com/android/settings/inputmethod/InputMethodPreference.java16
-rw-r--r--src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java2
-rw-r--r--src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java6
-rw-r--r--src/com/android/settings/location/LocationSettings.java90
-rw-r--r--src/com/android/settings/location/LocationSettingsBase.java55
-rw-r--r--src/com/android/settings/location/RecentLocationApps.java6
-rw-r--r--src/com/android/settings/location/SettingsInjector.java7
-rw-r--r--src/com/android/settings/nfc/AndroidBeam.java6
-rw-r--r--src/com/android/settings/print/PrintJobSettingsFragment.java2
-rw-r--r--src/com/android/settings/print/PrintServiceSettingsFragment.java77
-rw-r--r--src/com/android/settings/quicklaunch/QuickLaunchSettings.java53
-rw-r--r--src/com/android/settings/tts/TextToSpeechSettings.java20
-rw-r--r--src/com/android/settings/tts/TtsEnginePreference.java12
-rw-r--r--src/com/android/settings/tts/TtsEngineSettingsFragment.java16
-rw-r--r--src/com/android/settings/users/RestrictionUtils.java4
-rw-r--r--src/com/android/settings/users/UserSettings.java10
-rwxr-xr-xsrc/com/android/settings/wfd/WifiDisplaySettings.java6
-rw-r--r--src/com/android/settings/wifi/AccessPoint.java7
-rw-r--r--src/com/android/settings/wifi/AdvancedWifiSettings.java3
-rw-r--r--src/com/android/settings/wifi/WifiPickerActivity.java5
-rw-r--r--src/com/android/settings/wifi/WifiSettings.java166
-rw-r--r--src/com/android/settings/wifi/p2p/WifiP2pSettings.java60
110 files changed, 6086 insertions, 3665 deletions
diff --git a/src/com/android/settings/ButtonBarHandler.java b/src/com/android/settings/ButtonBarHandler.java
index d61da1336..85e39d1a1 100644
--- a/src/com/android/settings/ButtonBarHandler.java
+++ b/src/com/android/settings/ButtonBarHandler.java
@@ -19,7 +19,7 @@ import android.widget.Button;
/**
* Interface letting {@link SettingsPreferenceFragment} access to bottom bar inside
- * {@link android.preference.PreferenceActivity}.
+ * {@link SettingsActivity}.
*/
public interface ButtonBarHandler {
public boolean hasNextButton();
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 49de36686..9c9fab1ff 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -17,7 +17,6 @@
package com.android.settings;
import android.app.Activity;
-import android.app.Fragment;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
@@ -28,7 +27,6 @@ import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.security.KeyStore;
import android.util.EventLog;
@@ -38,13 +36,12 @@ import android.view.ViewGroup;
import android.widget.ListView;
import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.ConfirmLockPattern.ConfirmLockPatternFragment;
import java.util.List;
import libcore.util.MutableBoolean;
-public class ChooseLockGeneric extends PreferenceActivity {
+public class ChooseLockGeneric extends SettingsActivity {
@Override
public Intent getIntent() {
@@ -229,20 +226,7 @@ public class ChooseLockGeneric extends PreferenceActivity {
private int upgradeQuality(int quality, MutableBoolean allowBiometric) {
quality = upgradeQualityForDPM(quality);
quality = upgradeQualityForKeyStore(quality);
- int encryptionQuality = upgradeQualityForEncryption(quality);
- if (encryptionQuality > quality) {
- //The first case checks whether biometric is allowed, prior to the user making
- //their selection from the list
- if (allowBiometric != null) {
- allowBiometric.value = quality <=
- DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
- } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
- //When the user has selected biometric we shouldn't change that due to
- //encryption
- return quality;
- }
- }
- return encryptionQuality;
+ return quality;
}
private int upgradeQualityForDPM(int quality) {
@@ -254,27 +238,6 @@ public class ChooseLockGeneric extends PreferenceActivity {
return quality;
}
- /**
- * Mix in "encryption minimums" to any given quality value. This prevents users
- * from downgrading the pattern/pin/password to a level below the minimums.
- *
- * ASSUMPTION: Setting quality is sufficient (e.g. minimum lengths will be set
- * appropriately.)
- */
- private int upgradeQualityForEncryption(int quality) {
- // Don't upgrade quality for secondary users. Encryption requirements don't apply.
- if (!Process.myUserHandle().equals(UserHandle.OWNER)) return quality;
- int encryptionStatus = mDPM.getStorageEncryptionStatus();
- boolean encrypted = (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE)
- || (encryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING);
- if (encrypted) {
- if (quality < CryptKeeperSettings.MIN_PASSWORD_QUALITY) {
- quality = CryptKeeperSettings.MIN_PASSWORD_QUALITY;
- }
- }
- return quality;
- }
-
private int upgradeQualityForKeyStore(int quality) {
if (!mKeyStore.isEmpty()) {
if (quality < CredentialStorage.MIN_PASSWORD_QUALITY) {
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index f43738f04..4d102a46c 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -19,7 +19,6 @@ package com.android.settings;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
import android.app.Activity;
import android.app.Fragment;
@@ -29,7 +28,6 @@ import android.inputmethodservice.KeyboardView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.preference.PreferenceActivity;
import android.text.Editable;
import android.text.InputType;
import android.text.Selection;
@@ -41,13 +39,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
-import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class ChooseLockPassword extends PreferenceActivity {
+public class ChooseLockPassword extends SettingsActivity {
public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters";
@@ -79,7 +76,7 @@ public class ChooseLockPassword extends PreferenceActivity {
//WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_choose_your_password_header);
- showBreadCrumbs(msg, msg);
+ setTitle(msg);
}
public static class ChooseLockPasswordFragment extends Fragment
@@ -137,9 +134,6 @@ public class ChooseLockPassword extends PreferenceActivity {
R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_continue_label);
- /**
- * @param headerMessage The message displayed at the top.
- */
Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
this.alphaHint = hintInAlpha;
this.numericHint = hintInNumeric;
@@ -235,13 +229,12 @@ public class ChooseLockPassword extends PreferenceActivity {
updateStage(mUiStage);
}
}
- // Update the breadcrumb (title) if this is embedded in a PreferenceActivity
- if (activity instanceof PreferenceActivity) {
- final PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
+ if (activity instanceof SettingsActivity) {
+ final SettingsActivity sa = (SettingsActivity) activity;
int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
: R.string.lockpassword_choose_your_pin_header;
CharSequence title = getText(id);
- preferenceActivity.showBreadCrumbs(title, title);
+ sa.setTitle(title);
}
return view;
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 328312c2f..5a939aac5 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -22,7 +22,6 @@ import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
import static com.android.internal.widget.LockPatternView.DisplayMode;
@@ -30,7 +29,6 @@ import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -49,7 +47,7 @@ import java.util.List;
* - asks for confirmation / restart
* - saves chosen password when confirmed
*/
-public class ChooseLockPattern extends PreferenceActivity {
+public class ChooseLockPattern extends SettingsActivity {
/**
* Used by the choose lock pattern wizard to indicate the wizard is
* finished, and each activity in the wizard should finish.
@@ -80,7 +78,7 @@ public class ChooseLockPattern extends PreferenceActivity {
// requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_choose_your_pattern_header);
- showBreadCrumbs(msg, msg);
+ setTitle(msg);
}
@Override
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index d7402daff..72da15674 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -19,7 +19,6 @@ package com.android.settings;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
import android.app.Activity;
import android.app.Fragment;
@@ -27,7 +26,6 @@ import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
-import android.preference.PreferenceActivity;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
@@ -36,13 +34,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class ConfirmLockPassword extends PreferenceActivity {
+public class ConfirmLockPassword extends SettingsActivity {
@Override
public Intent getIntent() {
@@ -65,7 +62,7 @@ public class ConfirmLockPassword extends PreferenceActivity {
//WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_confirm_your_password_header);
- showBreadCrumbs(msg, msg);
+ setTitle(msg);
}
public static class ConfirmLockPasswordFragment extends Fragment implements OnClickListener,
@@ -127,13 +124,12 @@ public class ConfirmLockPassword extends PreferenceActivity {
mPasswordEntry.setInputType(isAlpha ? currentType
: (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
- // Update the breadcrumb (title) if this is embedded in a PreferenceActivity
- if (activity instanceof PreferenceActivity) {
- final PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
+ if (activity instanceof SettingsActivity) {
+ final SettingsActivity sa = (SettingsActivity) activity;
int id = isAlpha ? R.string.lockpassword_confirm_your_password_header
: R.string.lockpassword_confirm_your_pin_header;
CharSequence title = getText(id);
- preferenceActivity.showBreadCrumbs(title, title);
+ sa.setTitle(title);
}
return view;
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index 3a1f06c33..81b325b7c 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -27,7 +27,6 @@ import android.content.Intent;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.widget.TextView;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,7 +40,7 @@ import java.util.List;
* Sets an activity result of {@link Activity#RESULT_OK} when the user
* successfully confirmed their pattern.
*/
-public class ConfirmLockPattern extends PreferenceActivity {
+public class ConfirmLockPattern extends SettingsActivity {
/**
* Names of {@link CharSequence} fields within the originating {@link Intent}
@@ -65,7 +64,7 @@ public class ConfirmLockPattern extends PreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CharSequence msg = getText(R.string.lockpassword_confirm_your_pattern_header);
- showBreadCrumbs(msg, msg);
+ setTitle(msg);
}
@Override
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index f71df1d6f..0bf265f5f 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -19,7 +19,6 @@ package com.android.settings;
import android.app.LauncherActivity;
import android.content.Intent;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 23ec70ede..d974d005d 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -34,6 +34,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.IMountService;
+import android.os.storage.StorageManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.Editable;
@@ -60,6 +61,9 @@ import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+import com.android.internal.widget.LockPatternView.Cell;
import java.util.List;
@@ -113,6 +117,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
private int mCooldown;
PowerManager.WakeLock mWakeLock;
private EditText mPasswordEntry;
+ private LockPatternView mLockPatternView;
/** Number of calls to {@link #notifyUser()} to ignore before notifying. */
private int mNotificationCountdown = 0;
@@ -175,7 +180,9 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
final TextView status = (TextView) findViewById(R.id.status);
status.setText(R.string.try_again);
// Reenable the password entry
- mPasswordEntry.setEnabled(true);
+ if (mPasswordEntry != null) {
+ mPasswordEntry.setEnabled(true);
+ }
}
}
}
@@ -354,7 +361,21 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
setContentView(R.layout.crypt_keeper_progress);
encryptionProgressInit();
} else if (mValidationComplete || isDebugView(FORCE_VIEW_PASSWORD)) {
- setContentView(R.layout.crypt_keeper_password_entry);
+ final IMountService service = getMountService();
+ int type = StorageManager.CRYPT_TYPE_PASSWORD;
+ try {
+ type = service.getPasswordType();
+ } catch (Exception e) {
+ Log.e(TAG, "Error while getting type - showing default dialog" + e);
+ }
+
+ if(type == StorageManager.CRYPT_TYPE_PIN) {
+ setContentView(R.layout.crypt_keeper_pin_entry);
+ } else if (type == StorageManager.CRYPT_TYPE_PATTERN) {
+ setContentView(R.layout.crypt_keeper_pattern_entry);
+ } else {
+ setContentView(R.layout.crypt_keeper_password_entry);
+ }
passwordEntryInit();
} else if (!mValidationRequested) {
// We're supposed to be encrypted, but no validation has been done.
@@ -503,14 +524,44 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
}
}
- private void passwordEntryInit() {
+ protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
+ new LockPatternView.OnPatternListener() {
+
+ @Override
+ public void onPatternStart() {
+ }
+
+ @Override
+ public void onPatternCleared() {
+ }
+
+ @Override
+ public void onPatternDetected(List<LockPatternView.Cell> pattern) {
+ new DecryptTask().execute(LockPatternUtils.patternToString(pattern));
+ }
+
+ @Override
+ public void onPatternCellAdded(List<Cell> pattern) {
+ }
+ };
+
+ private void passwordEntryInit() {
+ // Password/pin case
mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
- mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.requestFocus();
- // Become quiet when the user interacts with the Edit text screen.
- mPasswordEntry.setOnKeyListener(this);
- mPasswordEntry.setOnTouchListener(this);
- mPasswordEntry.addTextChangedListener(this);
+ if (mPasswordEntry != null){
+ mPasswordEntry.setOnEditorActionListener(this);
+ mPasswordEntry.requestFocus();
+ // Become quiet when the user interacts with the Edit text screen.
+ mPasswordEntry.setOnKeyListener(this);
+ mPasswordEntry.setOnTouchListener(this);
+ mPasswordEntry.addTextChangedListener(this);
+ }
+
+ // Pattern case
+ mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
+ if (mLockPatternView != null) {
+ mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
+ }
// Disable the Emergency call button if the device has no voice telephone capability
final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/CryptKeeperSettings.java
index 58d97a82f..cedf53034 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/CryptKeeperSettings.java
@@ -30,7 +30,6 @@ import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -201,6 +200,6 @@ public class CryptKeeperSettings extends Fragment {
preference.setFragment(CryptKeeperConfirm.class.getName());
preference.setTitle(R.string.crypt_keeper_confirm_title);
preference.getExtras().putString("password", password);
- ((PreferenceActivity) getActivity()).onPreferenceStartFragment(null, preference);
+ ((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference);
}
}
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index db1ae29db..396c76a31 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -87,8 +87,6 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -548,8 +546,8 @@ public class DataUsageSummary extends Fragment {
return true;
}
case R.id.data_usage_menu_metered: {
- final PreferenceActivity activity = (PreferenceActivity) getActivity();
- activity.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
+ final SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
R.string.data_usage_metered_title, null, this, 0);
return true;
}
@@ -575,11 +573,6 @@ public class DataUsageSummary extends Fragment {
TrafficStats.closeQuietly(mStatsSession);
- if (this.isRemoving()) {
- getFragmentManager()
- .popBackStack(TAG_APP_DETAILS, FragmentManager.POP_BACK_STACK_INCLUSIVE);
- }
-
super.onDestroy();
}
@@ -886,14 +879,16 @@ public class DataUsageSummary extends Fragment {
private boolean getDataRoaming() {
final ContentResolver resolver = getActivity().getContentResolver();
- return Settings.Global.getInt(resolver, Settings.Global.DATA_ROAMING, 0) != 0;
+ return android.provider.Settings.Global.getInt(resolver,
+ android.provider.Settings.Global.DATA_ROAMING, 0) != 0;
}
private void setDataRoaming(boolean enabled) {
// TODO: teach telephony DataConnectionTracker to watch and apply
// updates when changed.
final ContentResolver resolver = getActivity().getContentResolver();
- Settings.Global.putInt(resolver, Settings.Global.DATA_ROAMING, enabled ? 1 : 0);
+ android.provider.Settings.Global.putInt(resolver,
+ android.provider.Settings.Global.DATA_ROAMING, enabled ? 1 : 0);
mMenuDataRoaming.setChecked(enabled);
}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index d971bd224..15d5a5fc3 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -59,6 +59,7 @@ import android.view.Gravity;
import android.view.HardwareRenderer;
import android.view.IWindowManager;
import android.view.View;
+import android.view.accessibility.AccessibilityManager;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
@@ -113,6 +114,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
private static final String SHOW_TOUCHES_KEY = "show_touches";
private static final String SHOW_SCREEN_UPDATES_KEY = "show_screen_updates";
private static final String DISABLE_OVERLAYS_KEY = "disable_overlays";
+ private static final String SIMULATE_COLOR_SPACE = "simulate_color_space";
private static final String SHOW_CPU_USAGE_KEY = "show_cpu_usage";
private static final String FORCE_HARDWARE_UI_KEY = "force_hw_ui";
private static final String FORCE_MSAA_KEY = "force_msaa";
@@ -139,6 +141,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
+ private static final String PROCESS_STATS = "proc_stats";
+
private static final String TAG_CONFIRM_ENFORCE = "confirm_enforce";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -192,12 +196,15 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
private ListPreference mAnimatorDurationScale;
private ListPreference mOverlayDisplayDevices;
private ListPreference mOpenGLTraces;
+ private ListPreference mSimulateColorSpace;
private CheckBoxPreference mImmediatelyDestroyActivities;
private ListPreference mAppProcessLimit;
private CheckBoxPreference mShowAllANRs;
+ private PreferenceScreen mProcessStats;
+
private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
private final ArrayList<CheckBoxPreference> mResetCbPrefs
= new ArrayList<CheckBoxPreference>();
@@ -243,6 +250,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
debugDebuggingCategory.removePreference(mClearAdbKeys);
}
}
+ mAllPrefs.add(mClearAdbKeys);
mEnableTerminal = findAndInitCheckboxPref(ENABLE_TERMINAL);
if (!isPackageInstalled(getActivity(), TERMINAL_APP_PACKAGE)) {
debugDebuggingCategory.removePreference(mEnableTerminal);
@@ -296,11 +304,13 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
mAnimatorDurationScale = addListPreference(ANIMATOR_DURATION_SCALE_KEY);
mOverlayDisplayDevices = addListPreference(OVERLAY_DISPLAY_DEVICES_KEY);
mOpenGLTraces = addListPreference(OPENGL_TRACES_KEY);
+ mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
mImmediatelyDestroyActivities = (CheckBoxPreference) findPreference(
IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
mAllPrefs.add(mImmediatelyDestroyActivities);
mResetCbPrefs.add(mImmediatelyDestroyActivities);
+
mAppProcessLimit = addListPreference(APP_PROCESS_LIMIT_KEY);
mShowAllANRs = (CheckBoxPreference) findPreference(
@@ -319,6 +329,9 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
mAllPrefs.add(hdcpChecking);
removePreferenceForProduction(hdcpChecking);
}
+
+ mProcessStats = (PreferenceScreen) findPreference(PROCESS_STATS);
+ mAllPrefs.add(mProcessStats);
}
private ListPreference addListPreference(String prefKey) {
@@ -497,6 +510,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
updateBugreportOptions();
updateForceRtlOptions();
updateWifiDisplayCertificationOptions();
+ updateSimulateColorSpace();
}
private void resetDangerousOptions() {
@@ -933,6 +947,40 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
pokeSystemProperties();
}
+ private void updateSimulateColorSpace() {
+ final ContentResolver cr = getContentResolver();
+ final boolean enabled = Settings.Secure.getInt(
+ cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) != 0;
+ if (enabled) {
+ final String mode = Integer.toString(Settings.Secure.getInt(
+ cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER,
+ AccessibilityManager.DALTONIZER_DISABLED));
+ mSimulateColorSpace.setValue(mode);
+ final int index = mSimulateColorSpace.findIndexOfValue(mode);
+ if (index < 0) {
+ // We're using a mode controlled by accessibility preferences.
+ mSimulateColorSpace.setSummary(getString(R.string.daltonizer_type_overridden,
+ getString(R.string.accessibility_display_daltonizer_preference_title)));
+ } else {
+ mSimulateColorSpace.setSummary("%s");
+ }
+ } else {
+ mSimulateColorSpace.setValue(
+ Integer.toString(AccessibilityManager.DALTONIZER_DISABLED));
+ }
+ }
+
+ private void writeSimulateColorSpace(Object value) {
+ final ContentResolver cr = getContentResolver();
+ final int newMode = Integer.parseInt(value.toString());
+ if (newMode < 0) {
+ Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0);
+ } else {
+ Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 1);
+ Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, newMode);
+ }
+ }
+
private void updateForceRtlOptions() {
updateCheckBox(mForceRtlLayout, Settings.Global.getInt(getActivity().getContentResolver(),
Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0);
@@ -1311,6 +1359,9 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
} else if (preference == mAppProcessLimit) {
writeAppProcessLimitOptions(newValue);
return true;
+ } else if (preference == mSimulateColorSpace) {
+ writeSimulateColorSpace(newValue);
+ return true;
}
return false;
}
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index 623403800..8bfdf927c 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -38,6 +38,7 @@ import android.os.Handler;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.text.TextUtils.TruncateAt;
+import android.util.EventLog;
import android.util.Log;
import android.view.Display;
import android.view.View;
@@ -55,19 +56,19 @@ import java.util.List;
public class DeviceAdminAdd extends Activity {
static final String TAG = "DeviceAdminAdd";
-
+
static final int DIALOG_WARNING = 1;
private static final int MAX_ADD_MSG_LINES_PORTRAIT = 5;
private static final int MAX_ADD_MSG_LINES_LANDSCAPE = 2;
private static final int MAX_ADD_MSG_LINES = 15;
-
+
Handler mHandler;
-
+
DevicePolicyManager mDPM;
DeviceAdminInfo mDeviceAdmin;
CharSequence mAddMsgText;
-
+
ImageView mAdminIcon;
TextView mAdminName;
TextView mAdminDescription;
@@ -78,19 +79,19 @@ public class DeviceAdminAdd extends Activity {
ViewGroup mAdminPolicies;
Button mActionButton;
Button mCancelButton;
-
+
final ArrayList<View> mAddingPolicies = new ArrayList<View>();
final ArrayList<View> mActivePolicies = new ArrayList<View>();
-
+
boolean mAdding;
boolean mRefreshing;
-
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mHandler = new Handler(getMainLooper());
-
+
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
@@ -98,7 +99,7 @@ public class DeviceAdminAdd extends Activity {
finish();
return;
}
-
+
ComponentName cn = (ComponentName)getIntent().getParcelableExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (cn == null) {
@@ -163,7 +164,7 @@ public class DeviceAdminAdd extends Activity {
finish();
return;
}
-
+
// This admin already exists, an we have two options at this point. If new policy
// bits are set, show the user the new list. If nothing has changed, simply return
// "OK" immediately.
@@ -189,7 +190,7 @@ public class DeviceAdminAdd extends Activity {
mAddMsgText = getIntent().getCharSequenceExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION);
setContentView(R.layout.device_admin_add);
-
+
mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
mAdminName = (TextView)findViewById(R.id.admin_name);
mAdminDescription = (TextView)findViewById(R.id.admin_description);
@@ -210,6 +211,8 @@ public class DeviceAdminAdd extends Activity {
mCancelButton = (Button) findViewById(R.id.cancel_button);
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
+ EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
finish();
}
});
@@ -220,6 +223,8 @@ public class DeviceAdminAdd extends Activity {
try {
mDPM.setActiveAdmin(mDeviceAdmin.getComponent(), mRefreshing);
setResult(Activity.RESULT_OK);
+ EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_ACTIVATED_BY_USER,
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
} catch (RuntimeException e) {
// Something bad happened... could be that it was
// already set, though.
@@ -264,13 +269,13 @@ public class DeviceAdminAdd extends Activity {
}
});
}
-
+
@Override
protected void onResume() {
super.onResume();
updateInterface();
}
-
+
@Override
protected Dialog onCreateDialog(int id, Bundle args) {
switch (id) {
@@ -291,17 +296,17 @@ public class DeviceAdminAdd extends Activity {
}
default:
return super.onCreateDialog(id, args);
-
+
}
}
-
+
static void setViewVisibility(ArrayList<View> views, int visibility) {
final int N = views.size();
for (int i=0; i<N; i++) {
views.get(i).setVisibility(visibility);
}
}
-
+
void updateInterface() {
mAdminIcon.setImageDrawable(mDeviceAdmin.loadIcon(getPackageManager()));
mAdminName.setText(mDeviceAdmin.loadLabel(getPackageManager()));
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index b0c944d23..afe5b6819 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -25,7 +25,9 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
@@ -36,9 +38,6 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
-import com.android.internal.view.RotationPolicy;
-import com.android.settings.DreamSettings;
-
import java.util.ArrayList;
public class DisplaySettings extends SettingsPreferenceFragment implements
@@ -49,47 +48,26 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
- private static final String KEY_ACCELEROMETER = "accelerometer";
private static final String KEY_FONT_SIZE = "font_size";
- private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
private static final String KEY_SCREEN_SAVER = "screensaver";
private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
- private CheckBoxPreference mAccelerometer;
private WarnedListPreference mFontSizePref;
- private CheckBoxPreference mNotificationPulse;
private final Configuration mCurConfig = new Configuration();
+ private final Handler mHandler = new Handler();
private ListPreference mScreenTimeoutPreference;
private Preference mScreenSaverPreference;
- private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
- new RotationPolicy.RotationPolicyListener() {
- @Override
- public void onChange() {
- updateAccelerometerRotationCheckbox();
- }
- };
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ContentResolver resolver = getActivity().getContentResolver();
+ final ContentResolver resolver = getActivity().getContentResolver();
addPreferencesFromResource(R.xml.display_settings);
- mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
- mAccelerometer.setPersistent(false);
- if (!RotationPolicy.isRotationSupported(getActivity())
- || RotationPolicy.isRotationLockToggleSupported(getActivity())) {
- // If rotation lock is supported, then we do not provide this option in
- // Display settings. However, is still available in Accessibility settings,
- // if the device supports rotation.
- getPreferenceScreen().removePreference(mAccelerometer);
- }
-
mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);
if (mScreenSaverPreference != null
&& getResources().getBoolean(
@@ -108,20 +86,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
mFontSizePref = (WarnedListPreference) findPreference(KEY_FONT_SIZE);
mFontSizePref.setOnPreferenceChangeListener(this);
mFontSizePref.setOnPreferenceClickListener(this);
- mNotificationPulse = (CheckBoxPreference) findPreference(KEY_NOTIFICATION_PULSE);
- if (mNotificationPulse != null
- && getResources().getBoolean(
- com.android.internal.R.bool.config_intrusiveNotificationLed) == false) {
- getPreferenceScreen().removePreference(mNotificationPulse);
- } else {
- try {
- mNotificationPulse.setChecked(Settings.System.getInt(resolver,
- Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
- mNotificationPulse.setOnPreferenceChangeListener(this);
- } catch (SettingNotFoundException snfe) {
- Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
- }
- }
}
private void updateTimeoutPreferenceDescription(long currentTimeout) {
@@ -226,21 +190,10 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
public void onResume() {
super.onResume();
- RotationPolicy.registerRotationPolicyListener(getActivity(),
- mRotationPolicyListener);
-
updateState();
}
@Override
- public void onPause() {
- super.onPause();
-
- RotationPolicy.unregisterRotationPolicyListener(getActivity(),
- mRotationPolicyListener);
- }
-
- @Override
public Dialog onCreateDialog(int dialogId) {
if (dialogId == DLG_GLOBAL_CHANGE_WARNING) {
return Utils.buildGlobalChangeWarningDialog(getActivity(),
@@ -255,7 +208,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
}
private void updateState() {
- updateAccelerometerRotationCheckbox();
readFontSizePreference(mFontSizePref);
updateScreenSaverSummary();
}
@@ -267,12 +219,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
}
}
- private void updateAccelerometerRotationCheckbox() {
- if (getActivity() == null) return;
-
- mAccelerometer.setChecked(!RotationPolicy.isRotationLocked(getActivity()));
- }
-
public void writeFontSizePreference(Object objValue) {
try {
mCurConfig.fontScale = Float.parseFloat(objValue.toString());
@@ -284,15 +230,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
- if (preference == mAccelerometer) {
- RotationPolicy.setRotationLockForAccessibility(
- getActivity(), !mAccelerometer.isChecked());
- } else if (preference == mNotificationPulse) {
- boolean value = mNotificationPulse.isChecked();
- Settings.System.putInt(getContentResolver(), Settings.System.NOTIFICATION_LIGHT_PULSE,
- value ? 1 : 0);
- return true;
- }
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
diff --git a/src/com/android/settings/DreamSettings.java b/src/com/android/settings/DreamSettings.java
index cb91f397a..f4e251ec3 100644
--- a/src/com/android/settings/DreamSettings.java
+++ b/src/com/android/settings/DreamSettings.java
@@ -26,7 +26,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
diff --git a/src/com/android/settings/EventLogTags.logtags b/src/com/android/settings/EventLogTags.logtags
index 3e87c5369..b21623c11 100644
--- a/src/com/android/settings/EventLogTags.logtags
+++ b/src/com/android/settings/EventLogTags.logtags
@@ -4,3 +4,9 @@ option java_package com.android.settings
# log the type of screen lock when user sets lock screen
90200 lock_screen_type (type|3)
+
+# log whether user accepted and activated device admin
+90201 exp_det_device_admin_activated_by_user (app_signature|3)
+
+# log whether user declined activation of device admin
+90202 exp_det_device_admin_declined_by_user (app_signature|3)
diff --git a/src/com/android/settings/HomeSettings.java b/src/com/android/settings/HomeSettings.java
index eb659e27e..8697062fd 100644
--- a/src/com/android/settings/HomeSettings.java
+++ b/src/com/android/settings/HomeSettings.java
@@ -23,7 +23,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -138,7 +137,7 @@ public class HomeSettings extends SettingsPreferenceFragment {
if (mPrefs.size() < 2) {
if (mShowNotice) {
mShowNotice = false;
- Settings.requestHomeNotice();
+ SettingsActivity.requestHomeNotice();
}
finishFragment();
}
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 262aca37e..eaf29c6e7 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -31,7 +31,6 @@ import android.os.Environment;
import android.os.SystemProperties;
import android.os.UserManager;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -115,7 +114,7 @@ public class MasterClear extends Fragment {
preference.setFragment(MasterClearConfirm.class.getName());
preference.setTitle(R.string.master_clear_confirm_title);
preference.getExtras().putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());
- ((PreferenceActivity) getActivity()).onPreferenceStartFragment(null, preference);
+ ((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference);
}
/**
diff --git a/src/com/android/settings/NfcLockFragment.java b/src/com/android/settings/NfcLockFragment.java
new file mode 100644
index 000000000..b7bf6f768
--- /dev/null
+++ b/src/com/android/settings/NfcLockFragment.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 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.AlertDialog;
+import android.content.DialogInterface;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcUnlock;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+
+import android.preference.PreferenceCategory;
+import android.util.Log;
+import com.android.internal.widget.LockPatternUtils;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+import static android.preference.Preference.OnPreferenceClickListener;
+
+public class NfcLockFragment extends SettingsPreferenceFragment {
+
+ private static final String NFC_PAIRING = "nfc_pairing";
+ private static final String NFC_UNLOCK_ENABLED = "nfc_unlock_enabled";
+ private static final String TAGS_CATEGORY = "nfc_unlock_tags_category";
+ private static final String TAG_FORMAT = "Tag # %d";
+
+ private NfcUnlock mNfcUnlock;
+ private LockPatternUtils mLockPatternUtils;
+ private NfcAdapter mNfcAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mNfcUnlock = NfcUnlock.getInstance(NfcAdapter.getDefaultAdapter(getActivity()));
+ mLockPatternUtils = new LockPatternUtils(getActivity());
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
+ addPreferencesFromResource(R.xml.security_settings_nfc_unlock);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ boolean prefsEnabled = (mLockPatternUtils.isLockPasswordEnabled() ||
+ mLockPatternUtils.isLockPatternEnabled()) && mNfcAdapter.isEnabled();
+ CheckBoxPreference unlockPref = (CheckBoxPreference) findPreference(NFC_UNLOCK_ENABLED);
+ unlockPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mNfcUnlock.setNfcUnlockEnabled((Boolean) newValue);
+ return true;
+ }
+ });
+ Preference pairingPref = findPreference(NFC_PAIRING);
+ unlockPref.setEnabled(prefsEnabled);
+ pairingPref.setEnabled(prefsEnabled);
+
+ long[] tagRegistryTimes = mNfcUnlock.getTagRegistryTimes();
+ unlockPref.setChecked(mNfcUnlock.getNfcUnlockEnabled());
+
+ final PreferenceCategory pairedTags = (PreferenceCategory) findPreference(TAGS_CATEGORY);
+ pairedTags.setEnabled(prefsEnabled);
+
+ loadTagList(tagRegistryTimes, pairedTags);
+ }
+
+ private void loadTagList(long[] tagRegistryTimes, final PreferenceCategory pairedTags) {
+ pairedTags.removeAll();
+
+ for (int i = 0; i < tagRegistryTimes.length; i++) {
+
+ final Preference thisPreference = new Preference(getActivity());
+ final long timestamp = tagRegistryTimes[i];
+
+ thisPreference.setTitle(String.format(TAG_FORMAT, i));
+ thisPreference.setSummary(
+ DateFormat.getDateTimeInstance().format(new Date(tagRegistryTimes[i])));
+ thisPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+
+ AlertDialog.Builder deleteDialogBuilder = new AlertDialog.Builder(getActivity());
+
+ deleteDialogBuilder.setTitle(thisPreference.getTitle());
+ deleteDialogBuilder.setItems(new String[] {"Delete"},
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == 0) {
+ if (mNfcUnlock.deregisterTag(timestamp)) {
+ loadTagList(mNfcUnlock.getTagRegistryTimes(),
+ pairedTags);
+ }
+ }
+ }
+ });
+
+
+ deleteDialogBuilder.show();
+
+ return true;
+ }
+ });
+
+
+ pairedTags.addPreference(thisPreference);
+ }
+ }
+}
diff --git a/src/com/android/settings/NotificationSettings.java b/src/com/android/settings/NotificationSettings.java
new file mode 100644
index 000000000..c8ba39a00
--- /dev/null
+++ b/src/com/android/settings/NotificationSettings.java
@@ -0,0 +1,255 @@
+/*
+ * 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.ContentResolver;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.media.RingtoneManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.util.Log;
+
+public class NotificationSettings extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener, OnPreferenceClickListener {
+ private static final String TAG = "NotificationSettings";
+
+ private static final String KEY_NOTIFICATION_SOUND = "notification_sound";
+ private static final String KEY_ZEN_MODE = "zen_mode";
+ private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
+ private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "toggle_lock_screen_notifications";
+ private static final String KEY_HEADS_UP = "heads_up";
+ private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
+
+ private static final String KEY_SECURITY_CATEGORY = "category_security";
+ private static final String KEY_TWEAKS_CATEGORY = "category_tweaks"; // power toys, eng only
+
+ private static final int MSG_UPDATE_SOUND_SUMMARY = 2;
+
+ private PackageManager mPM;
+
+ private Preference mNotificationSoundPreference;
+ private Preference mNotificationAccess;
+ private CheckBoxPreference mLockscreenNotifications;
+ private CheckBoxPreference mHeadsUp;
+ private CheckBoxPreference mNotificationPulse;
+
+ private final Runnable mRingtoneLookupRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mNotificationSoundPreference != null) {
+ final CharSequence summary = SoundSettings.updateRingtoneName(
+ getActivity(), RingtoneManager.TYPE_NOTIFICATION);
+ if (summary != null) {
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_UPDATE_SOUND_SUMMARY, summary));
+ }
+ }
+ }
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_SOUND_SUMMARY:
+ mNotificationSoundPreference.setSummary((CharSequence) msg.obj);
+ break;
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final ContentResolver resolver = getActivity().getContentResolver();
+
+ mPM = getActivity().getPackageManager();
+
+ addPreferencesFromResource(R.xml.notification_settings);
+
+ final PreferenceScreen root = getPreferenceScreen();
+ final PreferenceGroup securityCategory = (PreferenceGroup)
+ root.findPreference(KEY_SECURITY_CATEGORY);
+
+ PreferenceGroup tweaksCategory = (PreferenceGroup)
+ root.findPreference(KEY_TWEAKS_CATEGORY);
+
+ if (tweaksCategory != null
+ && !(Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug"))) {
+ root.removePreference(tweaksCategory);
+ tweaksCategory = null;
+ }
+
+ mNotificationSoundPreference = findPreference(KEY_NOTIFICATION_SOUND);
+
+ mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
+ refreshNotificationListeners();
+
+ mLockscreenNotifications
+ = (CheckBoxPreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
+ if (mLockscreenNotifications != null) {
+ if (!getDeviceLockscreenNotificationsEnabled()) {
+ if (securityCategory != null) {
+ securityCategory.removePreference(mLockscreenNotifications);
+ }
+ } else {
+ mLockscreenNotifications.setChecked(getLockscreenAllowPrivateNotifications());
+ }
+ }
+
+ mHeadsUp = (CheckBoxPreference) findPreference(KEY_HEADS_UP);
+ if (mHeadsUp != null) {
+ updateHeadsUpMode(resolver);
+ mHeadsUp.setOnPreferenceChangeListener(this);
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED),
+ false, new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateHeadsUpMode(resolver);
+ }
+ });
+ }
+ mNotificationPulse = (CheckBoxPreference) findPreference(KEY_NOTIFICATION_PULSE);
+
+ if (mNotificationPulse != null
+ && getResources().getBoolean(
+ com.android.internal.R.bool.config_intrusiveNotificationLed) == false) {
+ getPreferenceScreen().removePreference(mNotificationPulse);
+ } else {
+ try {
+ mNotificationPulse.setChecked(Settings.System.getInt(resolver,
+ Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
+ mNotificationPulse.setOnPreferenceChangeListener(this);
+ } catch (Settings.SettingNotFoundException snfe) {
+ Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
+ }
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ refreshNotificationListeners();
+ lookupRingtoneNames();
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ final String key = preference.getKey();
+
+ if (KEY_LOCK_SCREEN_NOTIFICATIONS.equals(key)) {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+ mLockscreenNotifications.isChecked() ? 1 : 0);
+ } else if (KEY_HEADS_UP.equals(key)) {
+ setHeadsUpMode(getContentResolver(), mHeadsUp.isChecked());
+ } else if (KEY_NOTIFICATION_PULSE.equals(key)) {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.NOTIFICATION_LIGHT_PULSE,
+ mNotificationPulse.isChecked() ? 1 : 0);
+ } else {
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ return false;
+ }
+
+ // === Heads-up notifications ===
+
+ private void updateHeadsUpMode(ContentResolver resolver) {
+ mHeadsUp.setChecked(Settings.Global.HEADS_UP_ON == Settings.Global.getInt(resolver,
+ Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HEADS_UP_OFF));
+ }
+
+ private void setHeadsUpMode(ContentResolver resolver, boolean value) {
+ Settings.Global.putInt(resolver, Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+ value ? Settings.Global.HEADS_UP_ON : Settings.Global.HEADS_UP_OFF);
+ }
+
+ // === Lockscreen (public / private) notifications ===
+
+ private boolean getDeviceLockscreenNotificationsEnabled() {
+ return 0 != Settings.Global.getInt(getContentResolver(),
+ Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+ }
+
+ private boolean getLockscreenAllowPrivateNotifications() {
+ return 0 != Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
+ }
+
+ // === Notification listeners ===
+
+ private int getNumEnabledNotificationListeners() {
+ final String flat = Settings.Secure.getString(getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+ if (flat == null || "".equals(flat)) return 0;
+ final String[] components = flat.split(":");
+ return components.length;
+ }
+
+ private void refreshNotificationListeners() {
+ if (mNotificationAccess != null) {
+ final PreferenceGroup securityCategory
+ = (PreferenceGroup) getPreferenceScreen().findPreference(KEY_SECURITY_CATEGORY);
+
+ final int total = NotificationAccessSettings.getListenersCount(mPM);
+ if (total == 0) {
+ if (securityCategory != null) {
+ securityCategory.removePreference(mNotificationAccess);
+ }
+ } else {
+ final int n = getNumEnabledNotificationListeners();
+ if (n == 0) {
+ mNotificationAccess.setSummary(getResources().getString(
+ R.string.manage_notification_access_summary_zero));
+ } else {
+ mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
+ R.plurals.manage_notification_access_summary_nonzero,
+ n, n)));
+ }
+ }
+ }
+ }
+
+ // === Ringtone ===
+
+ private void lookupRingtoneNames() {
+ new Thread(mRingtoneLookupRunnable).start();
+ }
+}
diff --git a/src/com/android/settings/PairNfcDevice.java b/src/com/android/settings/PairNfcDevice.java
new file mode 100644
index 000000000..7c75b9f61
--- /dev/null
+++ b/src/com/android/settings/PairNfcDevice.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2013 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.app.AlertDialog;
+import android.app.PendingIntent;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcUnlock;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.view.Menu;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class PairNfcDevice extends Activity {
+ private static String TAG = PairNfcDevice.class.getName();
+
+ private TextView mStatusText;
+ private ImageView mStatusImage;
+
+ private PendingIntent mPendingIntent;
+ private NfcAdapter mAdapter;
+
+ private Handler mHandler = new Handler();
+ private PowerManager.WakeLock mWakeLock;
+
+ private NfcUnlock mNfcUnlock;
+
+ // If pairing fails, we immediately get a new intent that would not leave time for the user to
+ // read the error message. So we'll just drop it and the user has to try again.
+ // TEST
+ private boolean mWaitingForDeviceDelayed;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_nfc_pairing);
+
+ mStatusText = (TextView) findViewById(R.id.status_text);
+ mStatusImage = (ImageView) findViewById(R.id.status_image);
+
+ mAdapter = NfcAdapter.getDefaultAdapter(this);
+ mPendingIntent = PendingIntent.getActivity(
+ this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
+
+ mNfcUnlock = NfcUnlock.getInstance(mAdapter);
+
+ setWaitingForDeviceMode();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ return false;
+ }
+
+ public void onPause() {
+ super.onPause();
+ mAdapter.disableForegroundDispatch(this);
+ if (mWakeLock != null) {
+ mWakeLock.release();
+ }
+ }
+
+ public void onResume() {
+ super.onResume();
+
+ if (!mAdapter.isEnabled()) {
+ // We need the user to start NFC.
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+ dialogBuilder.setMessage(R.string.enable_nfc);
+ dialogBuilder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
+ }
+ });
+ dialogBuilder.show();
+ }
+
+ mAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
+
+ if (mWakeLock == null) {
+ PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, TAG);
+ }
+ mWakeLock.acquire();
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
+ if (!mWaitingForDeviceDelayed) {
+ processTag(tag);
+ }
+ }
+
+ private void processTag(Tag tag) {
+ if (mNfcUnlock.registerTag(tag)) {
+ setPairingSucceededMode();
+ } else {
+ setPairingFailedMode();
+ }
+ }
+
+ private void setWaitingForDeviceModeDelayed(int delayInMs) {
+ mWaitingForDeviceDelayed = true;
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mWaitingForDeviceDelayed = false;
+ setWaitingForDeviceMode();
+ }
+ }, delayInMs);
+ }
+
+ private void setWaitingForDeviceMode() {
+ mStatusImage.setImageResource(R.drawable.no_ring_detected);
+ mStatusText.setText(R.string.status_no_ring_detected);
+ }
+
+ private void setPairingFailedMode() {
+ setErrorMode(R.string.status_error_pairing_failed);
+ }
+
+ private void setPairingSucceededMode() {
+ mStatusImage.setImageResource(R.drawable.ring_paired);
+ mStatusText.setText(R.string.status_device_paired);
+
+ // Automatically quit.
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ }, 1000);
+ }
+
+ private void setErrorMode(int errorMsgResourceId) {
+ mStatusText.setText(errorMsgResourceId);
+ setWaitingForDeviceModeDelayed(2500);
+ }
+}
diff --git a/src/com/android/settings/ProxySelector.java b/src/com/android/settings/ProxySelector.java
index 21e717a4a..052ea0abb 100644
--- a/src/com/android/settings/ProxySelector.java
+++ b/src/com/android/settings/ProxySelector.java
@@ -45,8 +45,6 @@ import android.widget.EditText;
import android.widget.TextView;
import java.net.InetSocketAddress;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class ProxySelector extends Fragment implements DialogCreatable {
private static final String TAG = "ProxySelector";
@@ -58,22 +56,6 @@ public class ProxySelector extends Fragment implements DialogCreatable {
Button mClearButton;
Button mDefaultButton;
- // Allows underscore char to supports proxies that do not
- // follow the spec
- private static final String HC = "a-zA-Z0-9\\_";
-
- // Matches blank input, ips, and domain names
- private static final String HOSTNAME_REGEXP =
- "^$|^[" + HC + "]+(\\-[" + HC + "]+)*(\\.[" + HC + "]+(\\-[" + HC + "]+)*)*$";
- private static final Pattern HOSTNAME_PATTERN;
- private static final String EXCLUSION_REGEXP =
- "$|^(\\*)?\\.?[" + HC + "]+(\\-[" + HC + "]+)*(\\.[" + HC + "]+(\\-[" + HC + "]+)*)*$";
- private static final Pattern EXCLUSION_PATTERN;
- static {
- HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
- EXCLUSION_PATTERN = Pattern.compile(EXCLUSION_REGEXP);
- }
-
private static final int ERROR_DIALOG_ID = 0;
private SettingsDialogFragment mDialogFragment;
@@ -203,35 +185,24 @@ public class ProxySelector extends Fragment implements DialogCreatable {
* @return 0 on success, string resource ID on failure
*/
public static int validate(String hostname, String port, String exclList) {
- Matcher match = HOSTNAME_PATTERN.matcher(hostname);
- String exclListArray[] = exclList.split(",");
-
- if (!match.matches()) return R.string.proxy_error_invalid_host;
-
- for (String excl : exclListArray) {
- Matcher m = EXCLUSION_PATTERN.matcher(excl);
- if (!m.matches()) return R.string.proxy_error_invalid_exclusion_list;
- }
-
- if (hostname.length() > 0 && port.length() == 0) {
- return R.string.proxy_error_empty_port;
- }
-
- if (port.length() > 0) {
- if (hostname.length() == 0) {
+ switch (Proxy.validate(hostname, port, exclList)) {
+ case Proxy.PROXY_VALID:
+ return 0;
+ case Proxy.PROXY_HOSTNAME_EMPTY:
return R.string.proxy_error_empty_host_set_port;
- }
- int portVal = -1;
- try {
- portVal = Integer.parseInt(port);
- } catch (NumberFormatException ex) {
+ case Proxy.PROXY_HOSTNAME_INVALID:
+ return R.string.proxy_error_invalid_host;
+ case Proxy.PROXY_PORT_EMPTY:
+ return R.string.proxy_error_empty_port;
+ case Proxy.PROXY_PORT_INVALID:
return R.string.proxy_error_invalid_port;
- }
- if (portVal <= 0 || portVal > 0xFFFF) {
- return R.string.proxy_error_invalid_port;
- }
+ case Proxy.PROXY_EXCLLIST_INVALID:
+ return R.string.proxy_error_invalid_exclusion_list;
+ default:
+ // should neven happen
+ Log.e(TAG, "Unknown proxy settings error");
+ return -1;
}
- return 0;
}
/**
@@ -245,7 +216,7 @@ public class ProxySelector extends Fragment implements DialogCreatable {
int port = 0;
int result = validate(hostname, portStr, exclList);
- if (result > 0) {
+ if (result != 0) {
showDialog(ERROR_DIALOG_ID);
return false;
}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index e4dcea1db..c4f0c7f42 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.nfc.NfcUnlock;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -57,6 +58,7 @@ public class SecuritySettings extends RestrictedSettingsFragment
// Lock Settings
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
+ private static final String KEY_NFC_UNLOCK_SET_OR_CHANGE = "nfc_unlock_set_or_change";
private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING =
"biometric_weak_improve_matching";
private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness";
@@ -82,7 +84,6 @@ public class SecuritySettings extends RestrictedSettingsFragment
private static final String KEY_TOGGLE_VERIFY_APPLICATIONS = "toggle_verify_applications";
private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
- private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
private PackageManager mPM;
@@ -106,8 +107,6 @@ public class SecuritySettings extends RestrictedSettingsFragment
private CheckBoxPreference mPowerButtonInstantlyLocks;
private CheckBoxPreference mEnableKeyguardWidgets;
- private Preference mNotificationAccess;
-
private boolean mIsPrimary;
public SecuritySettings() {
@@ -225,6 +224,19 @@ public class SecuritySettings extends RestrictedSettingsFragment
}
}
+ // don't display NFC unlock settings if the prop is not enabled
+ if (!NfcUnlock.getPropertyEnabled()) {
+ PreferenceGroup securityCategory =
+ (PreferenceGroup) root.findPreference(KEY_SECURITY_CATEGORY);
+
+ if (securityCategory != null) {
+ Preference preference = root.findPreference(KEY_NFC_UNLOCK_SET_OR_CHANGE);
+ if (preference != null) {
+ securityCategory.removePreference(preference);
+ }
+ }
+ }
+
// Append the rest of the settings
addPreferencesFromResource(R.xml.security_settings_misc);
@@ -313,41 +325,14 @@ public class SecuritySettings extends RestrictedSettingsFragment
}
}
- mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
- if (mNotificationAccess != null) {
- final int total = NotificationAccessSettings.getListenersCount(mPM);
- if (total == 0) {
- if (deviceAdminCategory != null) {
- deviceAdminCategory.removePreference(mNotificationAccess);
- }
- } else {
- final int n = getNumEnabledNotificationListeners();
- if (n == 0) {
- mNotificationAccess.setSummary(getResources().getString(
- R.string.manage_notification_access_summary_zero));
- } else {
- mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
- R.plurals.manage_notification_access_summary_nonzero,
- n, n)));
- }
- }
- }
-
if (shouldBePinProtected(RESTRICTIONS_PIN_SET)) {
protectByRestrictions(mToggleAppInstallation);
protectByRestrictions(mToggleVerifyApps);
protectByRestrictions(mResetCredentials);
protectByRestrictions(root.findPreference(KEY_CREDENTIALS_INSTALL));
}
- return root;
- }
- private int getNumEnabledNotificationListeners() {
- final String flat = Settings.Secure.getString(getContentResolver(),
- Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
- if (flat == null || "".equals(flat)) return 0;
- final String[] components = flat.split(":");
- return components.length;
+ return root;
}
private boolean isNonMarketAppsAllowed() {
@@ -520,6 +505,9 @@ public class SecuritySettings extends RestrictedSettingsFragment
if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
+ } else if (KEY_NFC_UNLOCK_SET_OR_CHANGE.equals(key)) {
+ startFragment(this, "com.android.settings.NfcLockFragment",
+ SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
} else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f6f49b86e..0d5839b2d 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,1105 +16,78 @@
package com.android.settings;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.OnAccountsUpdateListener;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.nfc.NfcAdapter;
-import android.os.Bundle;
-import android.os.INetworkManagementService;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceFragment;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.settings.accessibility.AccessibilitySettings;
-import com.android.settings.accessibility.CaptionPropertiesFragment;
-import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
-import com.android.settings.accounts.AccountSyncSettings;
-import com.android.settings.accounts.AuthenticatorHelper;
-import com.android.settings.accounts.ManageAccountsSettings;
import com.android.settings.applications.AppOpsSummary;
-import com.android.settings.applications.ManageApplications;
-import com.android.settings.applications.ProcessStatsUi;
-import com.android.settings.bluetooth.BluetoothEnabler;
-import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.deviceinfo.Memory;
-import com.android.settings.deviceinfo.UsbSettings;
-import com.android.settings.fuelgauge.PowerUsageSummary;
-import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
-import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
-import com.android.settings.inputmethod.SpellCheckersSettings;
-import com.android.settings.inputmethod.UserDictionaryList;
-import com.android.settings.location.LocationSettings;
-import com.android.settings.nfc.AndroidBeam;
-import com.android.settings.nfc.PaymentSettings;
-import com.android.settings.print.PrintJobSettingsFragment;
-import com.android.settings.print.PrintServiceSettingsFragment;
-import com.android.settings.print.PrintSettingsFragment;
-import com.android.settings.tts.TextToSpeechSettings;
-import com.android.settings.users.UserSettings;
-import com.android.settings.vpn2.VpnSettings;
-import com.android.settings.wfd.WifiDisplaySettings;
-import com.android.settings.wifi.AdvancedWifiSettings;
-import com.android.settings.wifi.WifiEnabler;
-import com.android.settings.wifi.WifiSettings;
-import com.android.settings.wifi.p2p.WifiP2pSettings;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
/**
- * Top-level settings activity to handle single pane and double pane UI layout.
+ * Top-level Settings activity
*/
-public class Settings extends PreferenceActivity
- implements ButtonBarHandler, OnAccountsUpdateListener {
-
- private static final String LOG_TAG = "Settings";
-
- private static final String META_DATA_KEY_HEADER_ID =
- "com.android.settings.TOP_LEVEL_HEADER_ID";
- private static final String META_DATA_KEY_FRAGMENT_CLASS =
- "com.android.settings.FRAGMENT_CLASS";
- private static final String META_DATA_KEY_PARENT_TITLE =
- "com.android.settings.PARENT_FRAGMENT_TITLE";
- private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
- "com.android.settings.PARENT_FRAGMENT_CLASS";
-
- private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
-
- private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
- private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
-
- static final int DIALOG_ONLY_ONE_HOME = 1;
-
- private static boolean sShowNoHomeNotice = false;
-
- private String mFragmentClass;
- private int mTopLevelHeaderId;
- private Header mFirstHeader;
- private Header mCurrentHeader;
- private Header mParentHeader;
- private boolean mInLocalHeaderSwitch;
-
- // Show only these settings for restricted users
- private int[] SETTINGS_FOR_RESTRICTED = {
- R.id.wireless_section,
- R.id.wifi_settings,
- R.id.bluetooth_settings,
- R.id.data_usage_settings,
- R.id.wireless_settings,
- R.id.device_section,
- R.id.sound_settings,
- R.id.display_settings,
- R.id.storage_settings,
- R.id.application_settings,
- R.id.battery_settings,
- R.id.personal_section,
- R.id.location_settings,
- R.id.security_settings,
- R.id.language_settings,
- R.id.user_settings,
- R.id.account_settings,
- R.id.account_add,
- R.id.system_section,
- R.id.date_time_settings,
- R.id.about_settings,
- R.id.accessibility_settings,
- R.id.print_settings,
- R.id.nfc_payment_settings,
- R.id.home_settings
- };
-
- private SharedPreferences mDevelopmentPreferences;
- private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
-
- // TODO: Update Call Settings based on airplane mode state.
-
- protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
-
- private AuthenticatorHelper mAuthenticatorHelper;
- private Header mLastHeader;
- private boolean mListeningToAccountUpdates;
-
- private boolean mBatteryPresent = true;
- private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
- boolean batteryPresent = Utils.isBatteryPresent(intent);
-
- if (mBatteryPresent != batteryPresent) {
- mBatteryPresent = batteryPresent;
- invalidateHeaders();
- }
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
- getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
- }
-
- mAuthenticatorHelper = new AuthenticatorHelper();
- mAuthenticatorHelper.updateAuthDescriptions(this);
- mAuthenticatorHelper.onAccountsUpdated(this, null);
-
- mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
- Context.MODE_PRIVATE);
-
- getMetaData();
- mInLocalHeaderSwitch = true;
- super.onCreate(savedInstanceState);
- mInLocalHeaderSwitch = false;
-
- if (!onIsHidingHeaders() && onIsMultiPane()) {
- highlightHeader(mTopLevelHeaderId);
- // Force the title so that it doesn't get overridden by a direct launch of
- // a specific settings screen.
- setTitle(R.string.settings_label);
- }
-
- // Retrieve any saved state
- if (savedInstanceState != null) {
- mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
- mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
- }
-
- // If the current header was saved, switch to it
- if (savedInstanceState != null && mCurrentHeader != null) {
- //switchToHeaderLocal(mCurrentHeader);
- showBreadCrumbs(mCurrentHeader.title, null);
- }
-
- if (mParentHeader != null) {
- setParentTitle(mParentHeader.title, null, new OnClickListener() {
- @Override
- public void onClick(View v) {
- switchToParent(mParentHeader.fragment);
- }
- });
- }
-
- // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
- if (onIsMultiPane()) {
- getActionBar().setDisplayHomeAsUpEnabled(false);
- getActionBar().setHomeButtonEnabled(false);
- }
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- // Save the current fragment, if it is the same as originally launched
- if (mCurrentHeader != null) {
- outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
- }
- if (mParentHeader != null) {
- outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- invalidateHeaders();
- }
- };
- mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
- mDevelopmentPreferencesListener);
-
- ListAdapter listAdapter = getListAdapter();
- if (listAdapter instanceof HeaderAdapter) {
- ((HeaderAdapter) listAdapter).resume();
- }
- invalidateHeaders();
-
- registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- unregisterReceiver(mBatteryInfoReceiver);
-
- ListAdapter listAdapter = getListAdapter();
- if (listAdapter instanceof HeaderAdapter) {
- ((HeaderAdapter) listAdapter).pause();
- }
-
- mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
- mDevelopmentPreferencesListener);
- mDevelopmentPreferencesListener = null;
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mListeningToAccountUpdates) {
- AccountManager.get(this).removeOnAccountsUpdatedListener(this);
- }
- }
-
- @Override
- public boolean onIsMultiPane() {
- return false;
- }
-
- private static final String[] ENTRY_FRAGMENTS = {
- WirelessSettings.class.getName(),
- WifiSettings.class.getName(),
- AdvancedWifiSettings.class.getName(),
- BluetoothSettings.class.getName(),
- TetherSettings.class.getName(),
- WifiP2pSettings.class.getName(),
- VpnSettings.class.getName(),
- DateTimeSettings.class.getName(),
- LocalePicker.class.getName(),
- InputMethodAndLanguageSettings.class.getName(),
- SpellCheckersSettings.class.getName(),
- UserDictionaryList.class.getName(),
- UserDictionarySettings.class.getName(),
- SoundSettings.class.getName(),
- DisplaySettings.class.getName(),
- DeviceInfoSettings.class.getName(),
- ManageApplications.class.getName(),
- ProcessStatsUi.class.getName(),
- NotificationStation.class.getName(),
- LocationSettings.class.getName(),
- SecuritySettings.class.getName(),
- PrivacySettings.class.getName(),
- DeviceAdminSettings.class.getName(),
- AccessibilitySettings.class.getName(),
- CaptionPropertiesFragment.class.getName(),
- TextToSpeechSettings.class.getName(),
- Memory.class.getName(),
- DevelopmentSettings.class.getName(),
- UsbSettings.class.getName(),
- AndroidBeam.class.getName(),
- WifiDisplaySettings.class.getName(),
- PowerUsageSummary.class.getName(),
- AccountSyncSettings.class.getName(),
- CryptKeeperSettings.class.getName(),
- DataUsageSummary.class.getName(),
- DreamSettings.class.getName(),
- UserSettings.class.getName(),
- NotificationAccessSettings.class.getName(),
- ManageAccountsSettings.class.getName(),
- PrintSettingsFragment.class.getName(),
- PrintJobSettingsFragment.class.getName(),
- TrustedCredentialsSettings.class.getName(),
- PaymentSettings.class.getName(),
- KeyboardLayoutPickerFragment.class.getName()
- };
-
- @Override
- protected boolean isValidFragment(String fragmentName) {
- // Almost all fragments are wrapped in this,
- // except for a few that have their own activities.
- for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
- if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
- }
- return false;
- }
-
- private void switchToHeaderLocal(Header header) {
- mInLocalHeaderSwitch = true;
- switchToHeader(header);
- mInLocalHeaderSwitch = false;
- }
-
- @Override
- public void switchToHeader(Header header) {
- if (!mInLocalHeaderSwitch) {
- mCurrentHeader = null;
- mParentHeader = null;
- }
- super.switchToHeader(header);
- }
-
- /**
- * Switch to parent fragment and store the grand parent's info
- * @param className name of the activity wrapper for the parent fragment.
- */
- private void switchToParent(String className) {
- final ComponentName cn = new ComponentName(this, className);
- try {
- final PackageManager pm = getPackageManager();
- final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
-
- if (parentInfo != null && parentInfo.metaData != null) {
- String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
- CharSequence fragmentTitle = parentInfo.loadLabel(pm);
- Header parentHeader = new Header();
- parentHeader.fragment = fragmentClass;
- parentHeader.title = fragmentTitle;
- mCurrentHeader = parentHeader;
-
- switchToHeaderLocal(parentHeader);
- highlightHeader(mTopLevelHeaderId);
-
- mParentHeader = new Header();
- mParentHeader.fragment
- = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
- mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
- }
- } catch (NameNotFoundException nnfe) {
- Log.w(LOG_TAG, "Could not find parent activity : " + className);
- }
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
-
- // If it is not launched from history, then reset to top-level
- if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
- if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
- switchToHeaderLocal(mFirstHeader);
- }
- getListView().setSelectionFromTop(0, 0);
- }
- }
-
- private void highlightHeader(int id) {
- if (id != 0) {
- Integer index = mHeaderIndexMap.get(id);
- if (index != null) {
- getListView().setItemChecked(index, true);
- if (isMultiPane()) {
- getListView().smoothScrollToPosition(index);
- }
- }
- }
- }
-
- @Override
- public Intent getIntent() {
- Intent superIntent = super.getIntent();
- String startingFragment = getStartingFragmentClass(superIntent);
- // This is called from super.onCreate, isMultiPane() is not yet reliable
- // Do not use onIsHidingHeaders either, which relies itself on this method
- if (startingFragment != null && !onIsMultiPane()) {
- Intent modIntent = new Intent(superIntent);
- modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
- Bundle args = superIntent.getExtras();
- if (args != null) {
- args = new Bundle(args);
- } else {
- args = new Bundle();
- }
- args.putParcelable("intent", superIntent);
- modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
- return modIntent;
- }
- return superIntent;
- }
-
- /**
- * Checks if the component name in the intent is different from the Settings class and
- * returns the class name to load as a fragment.
- */
- protected String getStartingFragmentClass(Intent intent) {
- if (mFragmentClass != null) return mFragmentClass;
-
- String intentClass = intent.getComponent().getClassName();
- if (intentClass.equals(getClass().getName())) return null;
-
- if ("com.android.settings.ManageApplications".equals(intentClass)
- || "com.android.settings.RunningServices".equals(intentClass)
- || "com.android.settings.applications.StorageUse".equals(intentClass)) {
- // Old names of manage apps.
- intentClass = com.android.settings.applications.ManageApplications.class.getName();
- }
-
- return intentClass;
- }
-
- /**
- * Override initial header when an activity-alias is causing Settings to be launched
- * for a specific fragment encoded in the android:name parameter.
- */
- @Override
- public Header onGetInitialHeader() {
- String fragmentClass = getStartingFragmentClass(super.getIntent());
- if (fragmentClass != null) {
- Header header = new Header();
- header.fragment = fragmentClass;
- header.title = getTitle();
- header.fragmentArguments = getIntent().getExtras();
- mCurrentHeader = header;
- return header;
- }
-
- return mFirstHeader;
- }
-
- @Override
- public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
- int titleRes, int shortTitleRes) {
- Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
- titleRes, shortTitleRes);
-
- // Some fragments want split ActionBar; these should stay in sync with
- // uiOptions for fragments also defined as activities in manifest.
- if (WifiSettings.class.getName().equals(fragmentName) ||
- WifiP2pSettings.class.getName().equals(fragmentName) ||
- BluetoothSettings.class.getName().equals(fragmentName) ||
- DreamSettings.class.getName().equals(fragmentName) ||
- LocationSettings.class.getName().equals(fragmentName) ||
- ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
- PrintSettingsFragment.class.getName().equals(fragmentName) ||
- PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
- intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
- }
-
- intent.setClass(this, SubSettings.class);
- return intent;
- }
-
- /**
- * Populate the activity with the top-level headers.
- */
- @Override
- public void onBuildHeaders(List<Header> headers) {
- if (!onIsHidingHeaders()) {
- loadHeadersFromResource(R.xml.settings_headers, headers);
- updateHeaderList(headers);
- }
- }
-
- private void updateHeaderList(List<Header> target) {
- final boolean showDev = mDevelopmentPreferences.getBoolean(
- DevelopmentSettings.PREF_SHOW,
- android.os.Build.TYPE.equals("eng"));
- int i = 0;
-
- final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
- mHeaderIndexMap.clear();
- while (i < target.size()) {
- Header header = target.get(i);
- // Ids are integers, so downcasting
- int id = (int) header.id;
- if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
- Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
- } else if (id == R.id.wifi_settings) {
- // Remove WiFi Settings if WiFi service is not available.
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- target.remove(i);
- }
- } else if (id == R.id.bluetooth_settings) {
- // Remove Bluetooth Settings if Bluetooth service is not available.
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
- target.remove(i);
- }
- } else if (id == R.id.data_usage_settings) {
- // Remove data usage when kernel module not enabled
- final INetworkManagementService netManager = INetworkManagementService.Stub
- .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
- try {
- if (!netManager.isBandwidthControlEnabled()) {
- target.remove(i);
- }
- } catch (RemoteException e) {
- // ignored
- }
- } else if (id == R.id.battery_settings) {
- // Remove battery settings when battery is not available. (e.g. TV)
-
- if (!mBatteryPresent) {
- target.remove(i);
- }
- } else if (id == R.id.account_settings) {
- int headerIndex = i + 1;
- i = insertAccountsHeaders(target, headerIndex);
- } else if (id == R.id.home_settings) {
- if (!updateHomeSettingHeaders(header)) {
- target.remove(i);
- }
- } else if (id == R.id.user_settings) {
- if (!UserHandle.MU_ENABLED
- || !UserManager.supportsMultipleUsers()
- || Utils.isMonkeyRunning()) {
- target.remove(i);
- }
- } else if (id == R.id.nfc_payment_settings) {
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
- target.remove(i);
- } else {
- // Only show if NFC is on and we have the HCE feature
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
- if (!adapter.isEnabled() || !getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
- target.remove(i);
- }
- }
- } else if (id == R.id.development_settings) {
- if (!showDev) {
- target.remove(i);
- }
- } else if (id == R.id.account_add) {
- if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
- target.remove(i);
- }
- }
-
- if (i < target.size() && target.get(i) == header
- && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
- && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
- target.remove(i);
- }
-
- // Increment if the current one wasn't removed by the Utils code.
- if (i < target.size() && target.get(i) == header) {
- // Hold on to the first header, when we need to reset to the top-level
- if (mFirstHeader == null &&
- HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
- mFirstHeader = header;
- }
- mHeaderIndexMap.put(id, i);
- i++;
- }
- }
- }
-
- private int insertAccountsHeaders(List<Header> target, int headerIndex) {
- String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
- List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
- for (String accountType : accountTypes) {
- CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
- if (label == null) {
- continue;
- }
-
- Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
- boolean skipToAccount = accounts.length == 1
- && !mAuthenticatorHelper.hasAccountPreferences(accountType);
- Header accHeader = new Header();
- accHeader.title = label;
- if (accHeader.extras == null) {
- accHeader.extras = new Bundle();
- }
- if (skipToAccount) {
- accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
- accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
- accHeader.fragment = AccountSyncSettings.class.getName();
- accHeader.fragmentArguments = new Bundle();
- // Need this for the icon
- accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
- accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
- accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
- accounts[0]);
- } else {
- accHeader.breadCrumbTitle = label;
- accHeader.breadCrumbShortTitle = label;
- accHeader.fragment = ManageAccountsSettings.class.getName();
- accHeader.fragmentArguments = new Bundle();
- accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
- accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
- accountType);
- if (!isMultiPane()) {
- accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
- label.toString());
- }
- }
- accountHeaders.add(accHeader);
- mAuthenticatorHelper.preloadDrawableForType(this, accountType);
- }
-
- // Sort by label
- Collections.sort(accountHeaders, new Comparator<Header>() {
- @Override
- public int compare(Header h1, Header h2) {
- return h1.title.toString().compareTo(h2.title.toString());
- }
- });
-
- for (Header header : accountHeaders) {
- target.add(headerIndex++, header);
- }
- if (!mListeningToAccountUpdates) {
- AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
- mListeningToAccountUpdates = true;
- }
- return headerIndex;
- }
-
- private boolean updateHomeSettingHeaders(Header header) {
- // Once we decide to show Home settings, keep showing it forever
- SharedPreferences sp = getSharedPreferences(HomeSettings.HOME_PREFS, Context.MODE_PRIVATE);
- if (sp.getBoolean(HomeSettings.HOME_PREFS_DO_SHOW, false)) {
- return true;
- }
-
- try {
- final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>();
- getPackageManager().getHomeActivities(homeApps);
- if (homeApps.size() < 2) {
- // When there's only one available home app, omit this settings
- // category entirely at the top level UI. If the user just
- // uninstalled the penultimate home app candidiate, we also
- // now tell them about why they aren't seeing 'Home' in the list.
- if (sShowNoHomeNotice) {
- sShowNoHomeNotice = false;
- NoHomeDialogFragment.show(this);
- }
- return false;
- } else {
- // Okay, we're allowing the Home settings category. Tell it, when
- // invoked via this front door, that we'll need to be told about the
- // case when the user uninstalls all but one home app.
- if (header.fragmentArguments == null) {
- header.fragmentArguments = new Bundle();
- }
- header.fragmentArguments.putBoolean(HomeSettings.HOME_SHOW_NOTICE, true);
- }
- } catch (Exception e) {
- // Can't look up the home activity; bail on configuring the icon
- Log.w(LOG_TAG, "Problem looking up home activity!", e);
- }
-
- sp.edit().putBoolean(HomeSettings.HOME_PREFS_DO_SHOW, true).apply();
- return true;
- }
-
- private void getMetaData() {
- try {
- ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
- PackageManager.GET_META_DATA);
- if (ai == null || ai.metaData == null) return;
- mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
- mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
-
- // Check if it has a parent specified and create a Header object
- final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
- String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
- if (parentFragmentClass != null) {
- mParentHeader = new Header();
- mParentHeader.fragment = parentFragmentClass;
- if (parentHeaderTitleRes != 0) {
- mParentHeader.title = getResources().getString(parentHeaderTitleRes);
- }
- }
- } catch (NameNotFoundException nnfe) {
- // No recovery
- }
- }
-
- @Override
- public boolean hasNextButton() {
- return super.hasNextButton();
- }
-
- @Override
- public Button getNextButton() {
- return super.getNextButton();
- }
-
- public static class NoHomeDialogFragment extends DialogFragment {
- public static void show(Activity parent) {
- final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
- dialog.show(parent.getFragmentManager(), null);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity())
- .setMessage(R.string.only_one_home_message)
- .setPositiveButton(android.R.string.ok, null)
- .create();
- }
- }
-
- private static class HeaderAdapter extends ArrayAdapter<Header> {
- static final int HEADER_TYPE_CATEGORY = 0;
- static final int HEADER_TYPE_NORMAL = 1;
- static final int HEADER_TYPE_SWITCH = 2;
- static final int HEADER_TYPE_BUTTON = 3;
- private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
-
- private final WifiEnabler mWifiEnabler;
- private final BluetoothEnabler mBluetoothEnabler;
- private AuthenticatorHelper mAuthHelper;
- private DevicePolicyManager mDevicePolicyManager;
-
- private static class HeaderViewHolder {
- ImageView icon;
- TextView title;
- TextView summary;
- Switch switch_;
- ImageButton button_;
- View divider_;
- }
-
- private LayoutInflater mInflater;
-
- static int getHeaderType(Header header) {
- if (header.fragment == null && header.intent == null) {
- return HEADER_TYPE_CATEGORY;
- } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
- return HEADER_TYPE_SWITCH;
- } else if (header.id == R.id.security_settings) {
- return HEADER_TYPE_BUTTON;
- } else {
- return HEADER_TYPE_NORMAL;
- }
- }
-
- @Override
- public int getItemViewType(int position) {
- Header header = getItem(position);
- return getHeaderType(header);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false; // because of categories
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItemViewType(position) != HEADER_TYPE_CATEGORY;
- }
-
- @Override
- public int getViewTypeCount() {
- return HEADER_TYPE_COUNT;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public HeaderAdapter(Context context, List<Header> objects,
- AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
- super(context, 0, objects);
-
- mAuthHelper = authenticatorHelper;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- // Temp Switches provided as placeholder until the adapter replaces these with actual
- // Switches inflated from their layouts. Must be done before adapter is set in super
- mWifiEnabler = new WifiEnabler(context, new Switch(context));
- mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
- mDevicePolicyManager = dpm;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- HeaderViewHolder holder;
- Header header = getItem(position);
- int headerType = getHeaderType(header);
- View view = null;
-
- if (convertView == null) {
- holder = new HeaderViewHolder();
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- view = new TextView(getContext(), null,
- android.R.attr.listSeparatorTextViewStyle);
- holder.title = (TextView) view;
- break;
-
- case HEADER_TYPE_SWITCH:
- view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
- break;
-
- case HEADER_TYPE_BUTTON:
- view = mInflater.inflate(R.layout.preference_header_button_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.button_ = (ImageButton) view.findViewById(R.id.buttonWidget);
- holder.divider_ = view.findViewById(R.id.divider);
- break;
-
- case HEADER_TYPE_NORMAL:
- view = mInflater.inflate(
- R.layout.preference_header_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- holder.title = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.summary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- break;
- }
- view.setTag(holder);
- } else {
- view = convertView;
- holder = (HeaderViewHolder) view.getTag();
- }
-
- // All view fields must be updated every time, because the view may be recycled
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- holder.title.setText(header.getTitle(getContext().getResources()));
- break;
-
- case HEADER_TYPE_SWITCH:
- // Would need a different treatment if the main menu had more switches
- if (header.id == R.id.wifi_settings) {
- mWifiEnabler.setSwitch(holder.switch_);
- } else {
- mBluetoothEnabler.setSwitch(holder.switch_);
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_BUTTON:
- if (header.id == R.id.security_settings) {
- boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
- if (hasCert) {
- holder.button_.setVisibility(View.VISIBLE);
- holder.divider_.setVisibility(View.VISIBLE);
- boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
- if (isManaged) {
- holder.button_.setImageResource(R.drawable.ic_settings_about);
- } else {
- holder.button_.setImageResource(
- android.R.drawable.stat_notify_error);
- }
- holder.button_.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(
- android.provider.Settings.ACTION_MONITORING_CERT_INFO);
- getContext().startActivity(intent);
- }
- });
- } else {
- holder.button_.setVisibility(View.GONE);
- holder.divider_.setVisibility(View.GONE);
- }
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_NORMAL:
- updateCommonHeaderView(header, holder);
- break;
- }
-
- return view;
- }
-
- private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
- if (header.extras != null
- && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
- String accType = header.extras.getString(
- ManageAccountsSettings.KEY_ACCOUNT_TYPE);
- Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
- setHeaderIcon(holder, icon);
- } else {
- holder.icon.setImageResource(header.iconRes);
- }
- holder.title.setText(header.getTitle(getContext().getResources()));
- CharSequence summary = header.getSummary(getContext().getResources());
- if (!TextUtils.isEmpty(summary)) {
- holder.summary.setVisibility(View.VISIBLE);
- holder.summary.setText(summary);
- } else {
- holder.summary.setVisibility(View.GONE);
- }
- }
-
- private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
- ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
- lp.width = getContext().getResources().getDimensionPixelSize(
- R.dimen.header_icon_width);
- lp.height = lp.width;
- holder.icon.setLayoutParams(lp);
- holder.icon.setImageDrawable(icon);
- }
-
- public void resume() {
- mWifiEnabler.resume();
- mBluetoothEnabler.resume();
- }
-
- public void pause() {
- mWifiEnabler.pause();
- mBluetoothEnabler.pause();
- }
- }
-
- @Override
- public void onHeaderClick(Header header, int position) {
- boolean revert = false;
- if (header.id == R.id.account_add) {
- revert = true;
- }
-
- super.onHeaderClick(header, position);
-
- if (revert && mLastHeader != null) {
- highlightHeader((int) mLastHeader.id);
- } else {
- mLastHeader = header;
- }
- }
-
- @Override
- public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
- // Override the fragment title for Wallpaper settings
- int titleRes = pref.getTitleRes();
- if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
- titleRes = R.string.wallpaper_settings_fragment_title;
- } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
- && UserHandle.myUserId() != UserHandle.USER_OWNER) {
- if (UserManager.get(this).isLinkedUser()) {
- titleRes = R.string.profile_info_settings_title;
- } else {
- titleRes = R.string.user_info_settings_title;
- }
- }
- startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
- null, 0);
- return true;
- }
-
- @Override
- public boolean shouldUpRecreateTask(Intent targetIntent) {
- return super.shouldUpRecreateTask(new Intent(this, Settings.class));
- }
-
- @Override
- public void setListAdapter(ListAdapter adapter) {
- if (adapter == null) {
- super.setListAdapter(null);
- } else {
- DevicePolicyManager dpm =
- (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
- super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper, dpm));
- }
- }
-
- @Override
- public void onAccountsUpdated(Account[] accounts) {
- // TODO: watch for package upgrades to invalidate cache; see 7206643
- mAuthenticatorHelper.updateAuthDescriptions(this);
- mAuthenticatorHelper.onAccountsUpdated(this, accounts);
- invalidateHeaders();
- }
-
- public static void requestHomeNotice() {
- sShowNoHomeNotice = true;
- }
+public class Settings extends SettingsActivity {
/*
- * Settings subclasses for launching independently.
- */
- public static class BluetoothSettingsActivity extends Settings { /* empty */ }
- public static class WirelessSettingsActivity extends Settings { /* empty */ }
- public static class TetherSettingsActivity extends Settings { /* empty */ }
- public static class VpnSettingsActivity extends Settings { /* empty */ }
- public static class DateTimeSettingsActivity extends Settings { /* empty */ }
- public static class StorageSettingsActivity extends Settings { /* empty */ }
- public static class WifiSettingsActivity extends Settings { /* empty */ }
- public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
- public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
- public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
- public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
- public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
- public static class LocalePickerActivity extends Settings { /* empty */ }
- public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
- public static class SoundSettingsActivity extends Settings { /* empty */ }
- public static class DisplaySettingsActivity extends Settings { /* empty */ }
- public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
- public static class ApplicationSettingsActivity extends Settings { /* empty */ }
- public static class ManageApplicationsActivity extends Settings { /* empty */ }
- public static class AppOpsSummaryActivity extends Settings {
+ * Settings subclasses for launching independently.
+ */
+ public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WirelessSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class TetherSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class VpnSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class StorageSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class InputMethodAndLanguageSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }
+ public static class InputMethodAndSubtypeEnablerActivity extends SettingsActivity { /* empty */ }
+ public static class SpellCheckersSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class LocalePickerActivity extends SettingsActivity { /* empty */ }
+ public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class SoundSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
+ public static class AppOpsSummaryActivity extends SettingsActivity {
@Override
public boolean isValidFragment(String className) {
if (AppOpsSummary.class.getName().equals(className)) {
return true;
}
return super.isValidFragment(className);
- }
+ }
}
- public static class StorageUseActivity extends Settings { /* empty */ }
- public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
- public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
- public static class CaptioningSettingsActivity extends Settings { /* empty */ }
- public static class SecuritySettingsActivity extends Settings { /* empty */ }
- public static class LocationSettingsActivity extends Settings { /* empty */ }
- public static class PrivacySettingsActivity extends Settings { /* empty */ }
- public static class RunningServicesActivity extends Settings { /* empty */ }
- public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
- public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
- public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
- public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
- public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
- public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
- public static class DataUsageSummaryActivity extends Settings { /* empty */ }
- public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
- public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
- public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
- public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
- public static class DreamSettingsActivity extends Settings { /* empty */ }
- public static class NotificationStationActivity extends Settings { /* empty */ }
- public static class UserSettingsActivity extends Settings { /* empty */ }
- public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
- public static class UsbSettingsActivity extends Settings { /* empty */ }
- public static class TrustedCredentialsSettingsActivity extends Settings { /* empty */ }
- public static class PaymentSettingsActivity extends Settings { /* empty */ }
- public static class PrintSettingsActivity extends Settings { /* empty */ }
- public static class PrintJobSettingsActivity extends Settings { /* empty */ }
+ public static class StorageUseActivity extends SettingsActivity { /* empty */ }
+ public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AccessibilityInversionSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AccessibilityContrastSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AccessibilityDaltonizerSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class SecuritySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class LocationSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class PrivacySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class RunningServicesActivity extends SettingsActivity { /* empty */ }
+ public static class ManageAccountsSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class PowerUsageSummaryActivity extends SettingsActivity { /* empty */ }
+ public static class AccountSyncSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AccountSyncSettingsInAddAccountActivity extends SettingsActivity { /* empty */ }
+ public static class CryptKeeperSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DeviceAdminSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DataUsageSummaryActivity extends SettingsActivity { /* empty */ }
+ public static class AdvancedWifiSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class TextToSpeechSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AndroidBeamSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WifiDisplaySettingsActivity extends SettingsActivity { /* empty */ }
+ public static class DreamSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class NotificationStationActivity extends SettingsActivity { /* empty */ }
+ public static class UserSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class NotificationAccessSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class UsbSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class TrustedCredentialsSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class PaymentSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class PrintSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class PrintJobSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ }
+
+ public static class TopLevelSettings extends SettingsActivity { /* empty */ }
}
+
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
new file mode 100644
index 000000000..e49d8277e
--- /dev/null
+++ b/src/com/android/settings/SettingsActivity.java
@@ -0,0 +1,1872 @@
+/*
+ * 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.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.OnAccountsUpdateListener;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.INetworkManagementService;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.widget.DrawerLayout;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.XmlUtils;
+import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.CaptionPropertiesFragment;
+import com.android.settings.accounts.AccountSyncSettings;
+import com.android.settings.accounts.AuthenticatorHelper;
+import com.android.settings.accounts.ManageAccountsSettings;
+import com.android.settings.applications.ManageApplications;
+import com.android.settings.applications.ProcessStatsUi;
+import com.android.settings.bluetooth.BluetoothEnabler;
+import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.dashboard.DashboardSummary;
+import com.android.settings.deviceinfo.Memory;
+import com.android.settings.deviceinfo.UsbSettings;
+import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.indexer.Index;
+import com.android.settings.indexer.IndexableRef;
+import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
+import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
+import com.android.settings.inputmethod.SpellCheckersSettings;
+import com.android.settings.inputmethod.UserDictionaryList;
+import com.android.settings.location.LocationSettings;
+import com.android.settings.net.DataUsageMeteredSettings;
+import com.android.settings.nfc.AndroidBeam;
+import com.android.settings.nfc.PaymentSettings;
+import com.android.settings.print.PrintJobSettingsFragment;
+import com.android.settings.print.PrintSettingsFragment;
+import com.android.settings.tts.TextToSpeechSettings;
+import com.android.settings.users.UserSettings;
+import com.android.settings.vpn2.VpnSettings;
+import com.android.settings.wfd.WifiDisplaySettings;
+import com.android.settings.wifi.AdvancedWifiSettings;
+import com.android.settings.wifi.WifiEnabler;
+import com.android.settings.wifi.WifiSettings;
+import com.android.settings.wifi.p2p.WifiP2pSettings;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+public class SettingsActivity extends Activity
+ implements PreferenceManager.OnPreferenceTreeClickListener,
+ PreferenceFragment.OnPreferenceStartFragmentCallback,
+ ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener {
+
+ private static final String LOG_TAG = "Settings";
+
+ // Constants for state save/restore
+ private static final String SAVE_KEY_HEADERS_TAG = ":settings:headers";
+ private static final String SAVE_KEY_CURRENT_HEADER_TAG = ":settings:cur_header";
+
+ /**
+ * When starting this activity, the invoking Intent can contain this extra
+ * string to specify which fragment should be initially displayed.
+ * <p/>Starting from Key Lime Pie, when this argument is passed in, the activity
+ * will call isValidFragment() to confirm that the fragment class name is valid for this
+ * activity.
+ */
+ public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
+
+ /**
+ * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
+ * this extra can also be specified to supply a Bundle of arguments to pass
+ * to that fragment when it is instantiated during the initial creation
+ * of the activity.
+ */
+ public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
+
+ /**
+ * When starting this activity, the invoking Intent can contain this extra
+ * boolean that the header list should not be displayed. This is most often
+ * used in conjunction with {@link #EXTRA_SHOW_FRAGMENT} to launch
+ * the activity to display a specific fragment that the user has navigated
+ * to.
+ */
+ public static final String EXTRA_NO_HEADERS = ":settings:no_headers";
+
+ public static final String BACK_STACK_PREFS = ":settings:prefs";
+
+ // extras that allow any preference activity to be launched as part of a wizard
+
+ // show Back and Next buttons? takes boolean parameter
+ // Back will then return RESULT_CANCELED and Next RESULT_OK
+ protected static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
+
+ // add a Skip button?
+ private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
+
+ // specify custom text for the Back or Next buttons, or cause a button to not appear
+ // at all by setting it to null
+ protected static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
+ protected static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
+
+ /**
+ * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
+ * this extra can also be specify to supply the title to be shown for
+ * that fragment.
+ */
+ protected static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
+
+ private static final String META_DATA_KEY_HEADER_ID =
+ "com.android.settings.TOP_LEVEL_HEADER_ID";
+
+ private static final String META_DATA_KEY_FRAGMENT_CLASS =
+ "com.android.settings.FRAGMENT_CLASS";
+
+ private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
+
+ private static boolean sShowNoHomeNotice = false;
+
+ private String mFragmentClass;
+ private int mTopLevelHeaderId;
+ private Header mFirstHeader;
+ private Header mSelectedHeader;
+ private Header mCurrentHeader;
+
+ private CharSequence mInitialTitle;
+ private Header mInitialHeader;
+
+ // Show only these settings for restricted users
+ private int[] SETTINGS_FOR_RESTRICTED = {
+ R.id.wireless_section,
+ R.id.wifi_settings,
+ R.id.bluetooth_settings,
+ R.id.data_usage_settings,
+ R.id.wireless_settings,
+ R.id.device_section,
+ R.id.sound_settings,
+ R.id.display_settings,
+ R.id.storage_settings,
+ R.id.application_settings,
+ R.id.battery_settings,
+ R.id.personal_section,
+ R.id.location_settings,
+ R.id.security_settings,
+ R.id.language_settings,
+ R.id.user_settings,
+ R.id.account_settings,
+ R.id.account_add,
+ R.id.system_section,
+ R.id.date_time_settings,
+ R.id.about_settings,
+ R.id.accessibility_settings,
+ R.id.print_settings,
+ R.id.nfc_payment_settings,
+ R.id.home_settings,
+ R.id.dashboard
+ };
+
+ private static final String[] ENTRY_FRAGMENTS = {
+ WirelessSettings.class.getName(),
+ WifiSettings.class.getName(),
+ AdvancedWifiSettings.class.getName(),
+ BluetoothSettings.class.getName(),
+ TetherSettings.class.getName(),
+ WifiP2pSettings.class.getName(),
+ VpnSettings.class.getName(),
+ DateTimeSettings.class.getName(),
+ LocalePicker.class.getName(),
+ InputMethodAndLanguageSettings.class.getName(),
+ SpellCheckersSettings.class.getName(),
+ UserDictionaryList.class.getName(),
+ UserDictionarySettings.class.getName(),
+ SoundSettings.class.getName(),
+ DisplaySettings.class.getName(),
+ DeviceInfoSettings.class.getName(),
+ ManageApplications.class.getName(),
+ ProcessStatsUi.class.getName(),
+ NotificationStation.class.getName(),
+ LocationSettings.class.getName(),
+ SecuritySettings.class.getName(),
+ PrivacySettings.class.getName(),
+ DeviceAdminSettings.class.getName(),
+ AccessibilitySettings.class.getName(),
+ CaptionPropertiesFragment.class.getName(),
+ com.android.settings.accessibility.ToggleInversionPreferenceFragment.class.getName(),
+ com.android.settings.accessibility.ToggleContrastPreferenceFragment.class.getName(),
+ com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(),
+ TextToSpeechSettings.class.getName(),
+ Memory.class.getName(),
+ DevelopmentSettings.class.getName(),
+ UsbSettings.class.getName(),
+ AndroidBeam.class.getName(),
+ WifiDisplaySettings.class.getName(),
+ PowerUsageSummary.class.getName(),
+ AccountSyncSettings.class.getName(),
+ CryptKeeperSettings.class.getName(),
+ DataUsageSummary.class.getName(),
+ DreamSettings.class.getName(),
+ UserSettings.class.getName(),
+ NotificationAccessSettings.class.getName(),
+ ManageAccountsSettings.class.getName(),
+ PrintSettingsFragment.class.getName(),
+ PrintJobSettingsFragment.class.getName(),
+ TrustedCredentialsSettings.class.getName(),
+ PaymentSettings.class.getName(),
+ KeyboardLayoutPickerFragment.class.getName(),
+ DashboardSummary.class.getName(),
+ ZenModeSettings.class.getName()
+ };
+
+ private SharedPreferences mDevelopmentPreferences;
+ private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
+
+ // TODO: Update Call Settings based on airplane mode state.
+
+ protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
+
+ private AuthenticatorHelper mAuthenticatorHelper;
+ private boolean mListeningToAccountUpdates;
+
+ private Button mNextButton;
+
+ private boolean mBatteryPresent = true;
+ private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+ boolean batteryPresent = Utils.isBatteryPresent(intent);
+
+ if (mBatteryPresent != batteryPresent) {
+ mBatteryPresent = batteryPresent;
+ invalidateHeaders();
+ }
+ }
+ }
+ };
+
+ private final ArrayList<Header> mHeaders = new ArrayList<Header>();
+ private HeaderAdapter mHeaderAdapter;
+
+ private DrawerLayout mDrawerLayout;
+ private ListView mDrawer;
+ private ActionBarDrawerToggle mDrawerToggle;
+ private ActionBar mActionBar;
+
+ private static final int MSG_BUILD_HEADERS = 1;
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_BUILD_HEADERS: {
+ mHeaders.clear();
+ onBuildHeaders(mHeaders);
+ mHeaderAdapter.notifyDataSetChanged();
+ if (mCurrentHeader != null) {
+ Header mappedHeader = findBestMatchingHeader(mCurrentHeader, mHeaders);
+ if (mappedHeader != null) {
+ setSelectedHeader(mappedHeader);
+ }
+ }
+ } break;
+ }
+ }
+ };
+
+ private static int NO_DATA_RES_ID = 0;
+
+ /**
+ * Indexable data description.
+ *
+ * Known restriction: we are only searching (for now) the first level of Settings.
+ */
+ private static IndexableRef[] INDEXABLE_REFS = new IndexableRef[] {
+ new IndexableRef(1, NO_DATA_RES_ID,
+ WifiSettings.class.getName(),
+ R.drawable.ic_settings_wireless),
+ new IndexableRef(2, R.xml.bluetooth_settings,
+ BluetoothSettings.class.getName(),
+ R.drawable.ic_settings_bluetooth2),
+ new IndexableRef(3, R.xml.data_usage_metered_prefs,
+ DataUsageMeteredSettings.class.getName(),
+ R.drawable.ic_settings_data_usage),
+ new IndexableRef(4, R.xml.wireless_settings,
+ WirelessSettings.class.getName(),
+ R.drawable.empty_icon),
+ new IndexableRef(5, R.xml.home_selection,
+ HomeSettings.class.getName(),
+ R.drawable.ic_settings_home),
+ new IndexableRef(6, R.xml.sound_settings,
+ SoundSettings.class.getName(),
+ R.drawable.ic_settings_sound),
+ new IndexableRef(7, R.xml.display_settings,
+ DisplaySettings.class.getName(),
+ R.drawable.ic_settings_display),
+ new IndexableRef(7, NO_DATA_RES_ID,
+ WallpaperTypeSettings.class.getName(),
+ R.drawable.ic_settings_display),
+ new IndexableRef(8, R.xml.device_info_memory,
+ Memory.class.getName(),
+ R.drawable.ic_settings_storage),
+ new IndexableRef(9, R.xml.power_usage_summary,
+ PowerUsageSummary.class.getName(),
+ R.drawable.ic_settings_battery),
+ new IndexableRef(10, R.xml.user_settings,
+ UserSettings.class.getName(),
+ R.drawable.ic_settings_multiuser),
+ new IndexableRef(11, R.xml.location_settings,
+ LocationSettings.class.getName(),
+ R.drawable.ic_settings_location),
+ new IndexableRef(12, R.xml.security_settings,
+ SecuritySettings.class.getName(),
+ R.drawable.ic_settings_security),
+ new IndexableRef(13, R.xml.language_settings,
+ InputMethodAndLanguageSettings.class.getName(),
+ R.drawable.ic_settings_language),
+ new IndexableRef(14, R.xml.privacy_settings,
+ PrivacySettings.class.getName(),
+ R.drawable.ic_settings_backup),
+ new IndexableRef(15, R.xml.date_time_prefs,
+ DateTimeSettings.class.getName(),
+ R.drawable.ic_settings_date_time),
+ new IndexableRef(16, R.xml.accessibility_settings,
+ AccessibilitySettings.class.getName(),
+ R.drawable.ic_settings_accessibility),
+ new IndexableRef(17, R.xml.print_settings,
+ PrintSettingsFragment.class.getName(),
+ com.android.internal.R.drawable.ic_print),
+ new IndexableRef(18, R.xml.development_prefs,
+ DevelopmentSettings.class.getName(),
+ R.drawable.ic_settings_development),
+ new IndexableRef(19, R.xml.device_info_settings,
+ DeviceInfoSettings.class.getName(),
+ R.drawable.ic_settings_about),
+ };
+
+ @Override
+ public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
+ // Override the fragment title for Wallpaper settings
+ int titleRes = pref.getTitleRes();
+ if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
+ titleRes = R.string.wallpaper_settings_fragment_title;
+ } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
+ && UserHandle.myUserId() != UserHandle.USER_OWNER) {
+ if (UserManager.get(this).isLinkedUser()) {
+ titleRes = R.string.profile_info_settings_title;
+ } else {
+ titleRes = R.string.user_info_settings_title;
+ }
+ }
+ startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
+ null, 0);
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ return false;
+ }
+
+ private class DrawerListener implements DrawerLayout.DrawerListener {
+ @Override
+ public void onDrawerOpened(View drawerView) {
+ mDrawerToggle.onDrawerOpened(drawerView);
+ }
+
+ @Override
+ public void onDrawerClosed(View drawerView) {
+ mDrawerToggle.onDrawerClosed(drawerView);
+ // Cannot process clicks when the App is finishing
+ if (isFinishing() || mSelectedHeader == null) {
+ return;
+ }
+ switchToHeader(mSelectedHeader, false, false);
+ mSelectedHeader = null;
+ }
+
+ @Override
+ public void onDrawerSlide(View drawerView, float slideOffset) {
+ mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
+ }
+
+ @Override
+ public void onDrawerStateChanged(int newState) {
+ mDrawerToggle.onDrawerStateChanged(newState);
+ }
+ }
+
+ private class DrawerItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ mDrawerLayout.closeDrawer(mDrawer);
+ onListItemClick((ListView)parent, view, position, id);
+ }
+ }
+
+ private Header findBestMatchingHeader(Header current, ArrayList<Header> from) {
+ ArrayList<Header> matches = new ArrayList<Header>();
+ for (int j=0; j<from.size(); j++) {
+ Header oh = from.get(j);
+ if (current == oh || (current.id != HEADER_ID_UNDEFINED && current.id == oh.id)) {
+ // Must be this one.
+ matches.clear();
+ matches.add(oh);
+ break;
+ }
+ if (current.fragment != null) {
+ if (current.fragment.equals(oh.fragment)) {
+ matches.add(oh);
+ }
+ } else if (current.intent != null) {
+ if (current.intent.equals(oh.intent)) {
+ matches.add(oh);
+ }
+ } else if (current.title != null) {
+ if (current.title.equals(oh.title)) {
+ matches.add(oh);
+ }
+ }
+ }
+ final int NM = matches.size();
+ if (NM == 1) {
+ return matches.get(0);
+ } else if (NM > 1) {
+ for (int j=0; j<NM; j++) {
+ Header oh = matches.get(j);
+ if (current.fragmentArguments != null &&
+ current.fragmentArguments.equals(oh.fragmentArguments)) {
+ return oh;
+ }
+ if (current.extras != null && current.extras.equals(oh.extras)) {
+ return oh;
+ }
+ if (current.title != null && current.title.equals(oh.title)) {
+ return oh;
+ }
+ }
+ }
+ return null;
+ }
+
+ private void invalidateHeaders() {
+ if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) {
+ mHandler.sendEmptyMessage(MSG_BUILD_HEADERS);
+ }
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ mDrawerToggle.syncState();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ Index.getInstance(this).update();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mDrawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
+ getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
+ }
+
+ Index.getInstance(this).addIndexableData(INDEXABLE_REFS);
+ Index.getInstance(this).update();
+
+ mAuthenticatorHelper = new AuthenticatorHelper();
+ mAuthenticatorHelper.updateAuthDescriptions(this);
+ mAuthenticatorHelper.onAccountsUpdated(this, null);
+
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+ mHeaderAdapter= new HeaderAdapter(this, mHeaders, mAuthenticatorHelper, dpm);
+
+ mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
+ Context.MODE_PRIVATE);
+
+ getMetaData();
+
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.settings_main);
+
+ getFragmentManager().addOnBackStackChangedListener(this);
+
+ mActionBar = getActionBar();
+ mActionBar.setDisplayHomeAsUpEnabled(true);
+ mActionBar.setHomeButtonEnabled(true);
+
+ mDrawer = (ListView) findViewById(R.id.headers_drawer);
+ mDrawer.setAdapter(mHeaderAdapter);
+ mDrawer.setOnItemClickListener(new DrawerItemClickListener());
+ mDrawer.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+
+ mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
+ R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
+
+ if (savedInstanceState != null) {
+ // We are restarting from a previous saved state; used that to
+ // initialize, instead of starting fresh.
+ mInitialTitle = getTitle();
+
+ ArrayList<Header> headers =
+ savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG);
+ if (headers != null) {
+ mHeaders.addAll(headers);
+ int curHeader = savedInstanceState.getInt(SAVE_KEY_CURRENT_HEADER_TAG,
+ (int) HEADER_ID_UNDEFINED);
+ if (curHeader >= 0 && curHeader < mHeaders.size()) {
+ setSelectedHeader(mHeaders.get(curHeader));
+ mInitialHeader = mCurrentHeader;
+ }
+ setTitleFromBackStack();
+ }
+ } else {
+ String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
+ Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+
+ // We need to build the Headers in all cases
+ onBuildHeaders(mHeaders);
+
+ if (initialFragment != null) {
+ // If we are just showing a fragment, we want to run in
+ // new fragment mode, but don't need to compute and show
+ // the headers.
+ final int initialTitleResId = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
+ mInitialTitle = (initialTitleResId > 0) ? getText(initialTitleResId) : getTitle();
+ setTitle(mInitialTitle);
+ switchToHeaderInner(initialFragment, initialArguments, true, false, mInitialTitle);
+ setSelectedHeaderById(mTopLevelHeaderId);
+ mInitialHeader = mCurrentHeader;
+ } else {
+ // If there are headers, then at this point we need to show
+ // them and, depending on the screen, we may also show in-line
+ // the currently selected preference fragment.
+ if (mHeaders.size() > 0) {
+ mInitialHeader = onGetInitialHeader();
+ mInitialTitle = getHeaderTitle(mInitialHeader);
+ switchToHeader(mInitialHeader, false, true);
+ }
+ }
+ }
+
+ // see if we should show Back/Next buttons
+ Intent intent = getIntent();
+ if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
+
+ View buttonBar = findViewById(com.android.internal.R.id.button_bar);
+ if (buttonBar != null) {
+ buttonBar.setVisibility(View.VISIBLE);
+
+ Button backButton = (Button)findViewById(com.android.internal.R.id.back_button);
+ backButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+ Button skipButton = (Button)findViewById(com.android.internal.R.id.skip_button);
+ skipButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_OK);
+ finish();
+ }
+ });
+ mNextButton = (Button)findViewById(com.android.internal.R.id.next_button);
+ mNextButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ setResult(RESULT_OK);
+ finish();
+ }
+ });
+
+ // set our various button parameters
+ if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
+ String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
+ if (TextUtils.isEmpty(buttonText)) {
+ mNextButton.setVisibility(View.GONE);
+ }
+ else {
+ mNextButton.setText(buttonText);
+ }
+ }
+ if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
+ String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
+ if (TextUtils.isEmpty(buttonText)) {
+ backButton.setVisibility(View.GONE);
+ }
+ else {
+ backButton.setText(buttonText);
+ }
+ }
+ if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
+ skipButton.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+
+ if (!onIsHidingHeaders()) {
+ highlightHeader(mTopLevelHeaderId);
+ }
+ }
+
+ public Header onGetInitialHeader() {
+ String fragmentClass = getStartingFragmentClass(super.getIntent());
+ if (fragmentClass != null) {
+ Header header = new Header();
+ header.fragment = fragmentClass;
+ header.title = getTitle();
+ header.fragmentArguments = getIntent().getExtras();
+ return header;
+ }
+
+ return mFirstHeader;
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (mDrawerLayout.isDrawerOpen(mDrawer)) {
+ mDrawerLayout.closeDrawer(mDrawer);
+ return;
+ }
+ super.onBackPressed();
+ }
+
+ @Override
+ public void onBackStackChanged() {
+ if (setTitleFromBackStack() == 0) {
+ setSelectedHeaderById(mInitialHeader.id);
+ }
+ }
+
+ private int setTitleFromBackStack() {
+ final int count = getFragmentManager().getBackStackEntryCount();
+
+ if (count == 0) {
+ setTitle(mInitialTitle);
+ return 0;
+ }
+
+ FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
+ setTitleFromBackStackEntry(bse);
+
+ return count;
+ }
+
+ private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
+ final CharSequence title;
+ final int titleRes = bse.getBreadCrumbTitleRes();
+ if (titleRes > 0) {
+ title = getText(titleRes);
+ } else {
+ title = bse.getBreadCrumbTitle();
+ }
+ if (title != null) {
+ setTitle(title);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ if (mHeaders.size() > 0) {
+ outState.putParcelableArrayList(SAVE_KEY_HEADERS_TAG, mHeaders);
+ if (mCurrentHeader != null) {
+ int index = mHeaders.indexOf(mCurrentHeader);
+ if (index >= 0) {
+ outState.putInt(SAVE_KEY_CURRENT_HEADER_TAG, index);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ invalidateHeaders();
+ }
+ };
+ mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
+ mDevelopmentPreferencesListener);
+
+ mHeaderAdapter.resume(this);
+ invalidateHeaders();
+
+ registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+ mDrawerLayout.setDrawerListener(new DrawerListener());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ mDrawerLayout.setDrawerListener(null);
+
+ unregisterReceiver(mBatteryInfoReceiver);
+
+ mHeaderAdapter.pause();
+
+ mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
+ mDevelopmentPreferencesListener);
+
+ mDevelopmentPreferencesListener = null;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mListeningToAccountUpdates) {
+ AccountManager.get(this).removeOnAccountsUpdatedListener(this);
+ }
+ }
+
+ protected boolean isValidFragment(String fragmentName) {
+ // Almost all fragments are wrapped in this,
+ // except for a few that have their own activities.
+ for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
+ if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
+ }
+ return false;
+ }
+
+ private CharSequence getHeaderTitle(Header header) {
+ if (header == null || header.fragment == null) return getTitle();
+ final CharSequence title;
+ if (header.fragment.equals(DashboardSummary.class.getName())) {
+ title = getResources().getString(R.string.settings_label);
+ } else {
+ title = header.getTitle(getResources());
+ }
+ return title;
+ }
+
+ private void setSelectedHeaderById(long headerId) {
+ final int count = mHeaders.size();
+ for (int n = 0; n < count; n++) {
+ Header h = mHeaders.get(n);
+ if (h.id == headerId) {
+ setSelectedHeader(h);
+ return;
+ }
+ }
+ }
+
+ /**
+ * As the Headers can be rebuilt, their references can change, so use this method with caution!
+ */
+ private void setSelectedHeader(Header header) {
+ if (header == null) {
+ mCurrentHeader = null;
+ return;
+ }
+ // Update selected Header into Drawer only if it is not "Add Account"
+ if (header.id == R.id.account_add) {
+ mDrawer.clearChoices();
+ return;
+ }
+ mCurrentHeader = header;
+ int index = mHeaders.indexOf(header);
+ if (index >= 0) {
+ mDrawer.setItemChecked(index, true);
+ } else {
+ mDrawer.clearChoices();
+ }
+ }
+
+ private void highlightHeader(int id) {
+ if (id != 0) {
+ Integer index = mHeaderIndexMap.get(id);
+ if (index != null) {
+ mDrawer.setItemChecked(index, true);
+ if (mDrawer.getVisibility() == View.VISIBLE) {
+ mDrawer.smoothScrollToPosition(index);
+ }
+ }
+ }
+ }
+
+ /**
+ * When in two-pane mode, switch to the fragment pane to show the given
+ * preference fragment.
+ *
+ * @param header The new header to display.
+ * @param validate true means that the fragment's Header needs to be validated.
+ * @param initial true means that it is the initial Header.
+ */
+ private void switchToHeader(Header header, boolean validate, boolean initial) {
+ if (header == null) {
+ return;
+ }
+ // For switching to another Header it should be a different one
+ if (mCurrentHeader == null || header.id != mCurrentHeader.id) {
+ if (header.fragment != null) {
+ boolean addToBackStack;
+ if (initial) {
+ addToBackStack = false;
+ } else {
+ if (header.id != mInitialHeader.id) {
+ addToBackStack = true;
+ } else {
+ addToBackStack = (mTopLevelHeaderId > 0);
+ }
+ }
+ switchToHeaderInner(header.fragment, header.fragmentArguments, validate,
+ addToBackStack, getHeaderTitle(header));
+ setSelectedHeader(header);
+ } else if (header.intent != null) {
+ setSelectedHeader(header);
+ startActivity(header.intent);
+ } else {
+ throw new IllegalStateException(
+ "Can't switch to header that has no Fragment nor Intent");
+ }
+ }
+ }
+
+ /**
+ * Switch the fragment pane to show the given preference fragment.
+ *
+ * (used for initial fragment)
+ *
+ * @param fragmentName The name of the fragment to display.
+ * @param args Optional arguments to supply to the fragment.
+ * @param validate true means that the fragment's Header needs to be validated.
+ * @param title The title of the fragment to display.
+ */
+ private void switchToHeader(String fragmentName, Bundle args, boolean validate,
+ CharSequence title) {
+ setSelectedHeader(null);
+ switchToHeaderInner(fragmentName, args, validate, false, title);
+ }
+
+ /**
+ * Switch to a specific Header with taking care of validation, Title and BackStack
+ */
+ private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate,
+ boolean addToBackStack, CharSequence title) {
+ getFragmentManager().popBackStack(BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ if (validate && !isValidFragment(fragmentName)) {
+ throw new IllegalArgumentException("Invalid fragment for this activity: "
+ + fragmentName);
+ }
+ Fragment f = Fragment.instantiate(this, fragmentName, args);
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, f);
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ if (addToBackStack) {
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ }
+ if (title != null) {
+ transaction.setBreadCrumbTitle(title);
+ }
+ transaction.commitAllowingStateLoss();
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ // If it is not launched from history, then reset to top-level
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
+ if (mDrawer != null) {
+ mDrawer.setSelectionFromTop(0, 0);
+ }
+ }
+ }
+
+ /**
+ * Called to determine whether the header list should be hidden.
+ * The default implementation returns the
+ * value given in {@link #EXTRA_NO_HEADERS} or false if it is not supplied.
+ * This is set to false, for example, when the activity is being re-launched
+ * to show a particular preference activity.
+ */
+ public boolean onIsHidingHeaders() {
+ return getIntent().getBooleanExtra(EXTRA_NO_HEADERS, false);
+ }
+
+ @Override
+ public Intent getIntent() {
+ Intent superIntent = super.getIntent();
+ String startingFragment = getStartingFragmentClass(superIntent);
+ // This is called from super.onCreate, isMultiPane() is not yet reliable
+ // Do not use onIsHidingHeaders either, which relies itself on this method
+ if (startingFragment != null) {
+ Intent modIntent = new Intent(superIntent);
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
+ Bundle args = superIntent.getExtras();
+ if (args != null) {
+ args = new Bundle(args);
+ } else {
+ args = new Bundle();
+ }
+ args.putParcelable("intent", superIntent);
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
+ return modIntent;
+ }
+ return superIntent;
+ }
+
+ /**
+ * Checks if the component name in the intent is different from the Settings class and
+ * returns the class name to load as a fragment.
+ */
+ private String getStartingFragmentClass(Intent intent) {
+ if (mFragmentClass != null) return mFragmentClass;
+
+ String intentClass = intent.getComponent().getClassName();
+ if (intentClass.equals(getClass().getName())) return null;
+
+ if ("com.android.settings.ManageApplications".equals(intentClass)
+ || "com.android.settings.RunningServices".equals(intentClass)
+ || "com.android.settings.applications.StorageUse".equals(intentClass)) {
+ // Old names of manage apps.
+ intentClass = com.android.settings.applications.ManageApplications.class.getName();
+ }
+
+ return intentClass;
+ }
+
+ /**
+ * Start a new fragment containing a preference panel. If the preferences
+ * are being displayed in multi-pane mode, the given fragment class will
+ * be instantiated and placed in the appropriate pane. If running in
+ * single-pane mode, a new activity will be launched in which to show the
+ * fragment.
+ *
+ * @param fragmentClass Full name of the class implementing the fragment.
+ * @param args Any desired arguments to supply to the fragment.
+ * @param titleRes Optional resource identifier of the title of this
+ * fragment.
+ * @param titleText Optional text of the title of this fragment.
+ * @param resultTo Optional fragment that result data should be sent to.
+ * If non-null, resultTo.onActivityResult() will be called when this
+ * preference panel is done. The launched panel must use
+ * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
+ * @param resultRequestCode If resultTo is non-null, this is the caller's
+ * request code to be received with the resut.
+ */
+ public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+ CharSequence titleText, Fragment resultTo,
+ int resultRequestCode) {
+ startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
+ }
+
+ /**
+ * Called by a preference panel fragment to finish itself.
+ *
+ * @param caller The fragment that is asking to be finished.
+ * @param resultCode Optional result code to send back to the original
+ * launching fragment.
+ * @param resultData Optional result data to send back to the original
+ * launching fragment.
+ */
+ public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
+ setResult(resultCode, resultData);
+ }
+
+ /**
+ * Start a new fragment.
+ *
+ * @param fragment The fragment to start
+ * @param push If true, the current fragment will be pushed onto the back stack. If false,
+ * the current fragment will be replaced.
+ */
+ public void startPreferenceFragment(Fragment fragment, boolean push) {
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, fragment);
+ if (push) {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ } else {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ }
+ transaction.commitAllowingStateLoss();
+ }
+
+ /**
+ * Start a new fragment.
+ *
+ * @param fragmentName The name of the fragment to display.
+ * @param args Optional arguments to supply to the fragment.
+ * @param resultTo Option fragment that should receive the result of
+ * the activity launch.
+ * @param resultRequestCode If resultTo is non-null, this is the request code in which to
+ * report the result.
+ * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a
+ * valid one then it will be used to get the title. Otherwise the titleText
+ * argument will be used as the title.
+ * @param titleText string to display for the title of.
+ */
+ private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
+ int resultRequestCode, int titleRes, CharSequence titleText) {
+ final CharSequence cs;
+ if (titleRes != 0) {
+ cs = getText(titleRes);
+ } else {
+ cs = titleText;
+ }
+
+ Fragment f = Fragment.instantiate(this, fragmentName, args);
+ if (resultTo != null) {
+ f.setTargetFragment(resultTo, resultRequestCode);
+ }
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, f);
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ transaction.setBreadCrumbTitle(cs);
+ transaction.commitAllowingStateLoss();
+ }
+
+ /**
+ * Called when the activity needs its list of headers build.
+ *
+ * @param headers The list in which to place the headers.
+ */
+ private void onBuildHeaders(List<Header> headers) {
+ loadHeadersFromResource(R.xml.settings_headers, headers);
+ updateHeaderList(headers);
+ }
+
+ /**
+ * Parse the given XML file as a header description, adding each
+ * parsed Header into the target list.
+ *
+ * @param resid The XML resource to load and parse.
+ * @param target The list in which the parsed headers should be placed.
+ */
+ private void loadHeadersFromResource(int resid, List<Header> target) {
+ XmlResourceParser parser = null;
+ try {
+ parser = getResources().getXml(resid);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ // Parse next until start tag is found
+ }
+
+ String nodeName = parser.getName();
+ if (!"preference-headers".equals(nodeName)) {
+ throw new RuntimeException(
+ "XML document must start with <preference-headers> tag; found"
+ + nodeName + " at " + parser.getPositionDescription());
+ }
+
+ Bundle curBundle = null;
+
+ final int outerDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ nodeName = parser.getName();
+ if ("header".equals(nodeName)) {
+ Header header = new Header();
+
+ TypedArray sa = obtainStyledAttributes(
+ attrs, com.android.internal.R.styleable.PreferenceHeader);
+ header.id = sa.getResourceId(
+ com.android.internal.R.styleable.PreferenceHeader_id,
+ (int)HEADER_ID_UNDEFINED);
+ TypedValue tv = sa.peekValue(
+ com.android.internal.R.styleable.PreferenceHeader_title);
+ if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+ if (tv.resourceId != 0) {
+ header.titleRes = tv.resourceId;
+ } else {
+ header.title = tv.string;
+ }
+ }
+ tv = sa.peekValue(
+ com.android.internal.R.styleable.PreferenceHeader_summary);
+ if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+ if (tv.resourceId != 0) {
+ header.summaryRes = tv.resourceId;
+ } else {
+ header.summary = tv.string;
+ }
+ }
+ header.iconRes = sa.getResourceId(
+ com.android.internal.R.styleable.PreferenceHeader_icon, 0);
+ header.fragment = sa.getString(
+ com.android.internal.R.styleable.PreferenceHeader_fragment);
+ sa.recycle();
+
+ if (curBundle == null) {
+ curBundle = new Bundle();
+ }
+
+ final int innerDepth = parser.getDepth();
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String innerNodeName = parser.getName();
+ if (innerNodeName.equals("extra")) {
+ getResources().parseBundleExtra("extra", attrs, curBundle);
+ XmlUtils.skipCurrentTag(parser);
+
+ } else if (innerNodeName.equals("intent")) {
+ header.intent = Intent.parseIntent(getResources(), parser, attrs);
+
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ if (curBundle.size() > 0) {
+ header.fragmentArguments = curBundle;
+ curBundle = null;
+ }
+
+ target.add(header);
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException("Error parsing headers", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Error parsing headers", e);
+ } finally {
+ if (parser != null) parser.close();
+ }
+ }
+
+ private void updateHeaderList(List<Header> target) {
+ final boolean showDev = mDevelopmentPreferences.getBoolean(
+ DevelopmentSettings.PREF_SHOW,
+ android.os.Build.TYPE.equals("eng"));
+ int i = 0;
+
+ final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ mHeaderIndexMap.clear();
+ while (i < target.size()) {
+ Header header = target.get(i);
+ // Ids are integers, so downcasting
+ int id = (int) header.id;
+ if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
+ Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
+ } else if (id == R.id.wifi_settings) {
+ // Remove WiFi Settings if WiFi service is not available.
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ target.remove(i);
+ }
+ } else if (id == R.id.bluetooth_settings) {
+ // Remove Bluetooth Settings if Bluetooth service is not available.
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
+ target.remove(i);
+ }
+ } else if (id == R.id.data_usage_settings) {
+ // Remove data usage when kernel module not enabled
+ final INetworkManagementService netManager = INetworkManagementService.Stub
+ .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+ try {
+ if (!netManager.isBandwidthControlEnabled()) {
+ target.remove(i);
+ }
+ } catch (RemoteException e) {
+ // ignored
+ }
+ } else if (id == R.id.battery_settings) {
+ // Remove battery settings when battery is not available. (e.g. TV)
+
+ if (!mBatteryPresent) {
+ target.remove(i);
+ }
+ } else if (id == R.id.account_settings) {
+ int headerIndex = i + 1;
+ i = insertAccountsHeaders(target, headerIndex);
+ } else if (id == R.id.home_settings) {
+ if (!updateHomeSettingHeaders(header)) {
+ target.remove(i);
+ }
+ } else if (id == R.id.user_settings) {
+ if (!UserHandle.MU_ENABLED
+ || !UserManager.supportsMultipleUsers()
+ || Utils.isMonkeyRunning()) {
+ target.remove(i);
+ }
+ } else if (id == R.id.nfc_payment_settings) {
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
+ target.remove(i);
+ } else {
+ // Only show if NFC is on and we have the HCE feature
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
+ if (!adapter.isEnabled() || !getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
+ target.remove(i);
+ }
+ }
+ } else if (id == R.id.development_settings) {
+ if (!showDev) {
+ target.remove(i);
+ }
+ } else if (id == R.id.account_add) {
+ if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
+ target.remove(i);
+ }
+ }
+
+ if (i < target.size() && target.get(i) == header
+ && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
+ && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
+ target.remove(i);
+ }
+
+ // Increment if the current one wasn't removed by the Utils code.
+ if (i < target.size() && target.get(i) == header) {
+ // Hold on to the first header, when we need to reset to the top-level
+ if (mFirstHeader == null &&
+ HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
+ mFirstHeader = header;
+ }
+ mHeaderIndexMap.put(id, i);
+ i++;
+ }
+ }
+ }
+
+ private int insertAccountsHeaders(List<Header> target, int headerIndex) {
+ String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
+ List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
+ for (String accountType : accountTypes) {
+ CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
+ if (label == null) {
+ continue;
+ }
+
+ Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
+ boolean skipToAccount = accounts.length == 1
+ && !mAuthenticatorHelper.hasAccountPreferences(accountType);
+ Header accHeader = new Header();
+ accHeader.title = label;
+ if (accHeader.extras == null) {
+ accHeader.extras = new Bundle();
+ }
+ if (skipToAccount) {
+ accHeader.fragment = AccountSyncSettings.class.getName();
+ accHeader.fragmentArguments = new Bundle();
+ // Need this for the icon
+ accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
+ accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
+ accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
+ accounts[0]);
+ } else {
+ accHeader.fragment = ManageAccountsSettings.class.getName();
+ accHeader.fragmentArguments = new Bundle();
+ accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
+ accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
+ accountType);
+ accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
+ label.toString());
+ }
+ accountHeaders.add(accHeader);
+ mAuthenticatorHelper.preloadDrawableForType(this, accountType);
+ }
+
+ // Sort by label
+ Collections.sort(accountHeaders, new Comparator<Header>() {
+ @Override
+ public int compare(Header h1, Header h2) {
+ return h1.title.toString().compareTo(h2.title.toString());
+ }
+ });
+
+ for (Header header : accountHeaders) {
+ target.add(headerIndex++, header);
+ }
+ if (!mListeningToAccountUpdates) {
+ AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
+ mListeningToAccountUpdates = true;
+ }
+ return headerIndex;
+ }
+
+ private boolean updateHomeSettingHeaders(Header header) {
+ // Once we decide to show Home settings, keep showing it forever
+ SharedPreferences sp = getSharedPreferences(HomeSettings.HOME_PREFS, Context.MODE_PRIVATE);
+ if (sp.getBoolean(HomeSettings.HOME_PREFS_DO_SHOW, false)) {
+ return true;
+ }
+
+ try {
+ final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>();
+ getPackageManager().getHomeActivities(homeApps);
+ if (homeApps.size() < 2) {
+ // When there's only one available home app, omit this settings
+ // category entirely at the top level UI. If the user just
+ // uninstalled the penultimate home app candidiate, we also
+ // now tell them about why they aren't seeing 'Home' in the list.
+ if (sShowNoHomeNotice) {
+ sShowNoHomeNotice = false;
+ NoHomeDialogFragment.show(this);
+ }
+ return false;
+ } else {
+ // Okay, we're allowing the Home settings category. Tell it, when
+ // invoked via this front door, that we'll need to be told about the
+ // case when the user uninstalls all but one home app.
+ if (header.fragmentArguments == null) {
+ header.fragmentArguments = new Bundle();
+ }
+ header.fragmentArguments.putBoolean(HomeSettings.HOME_SHOW_NOTICE, true);
+ }
+ } catch (Exception e) {
+ // Can't look up the home activity; bail on configuring the icon
+ Log.w(LOG_TAG, "Problem looking up home activity!", e);
+ }
+
+ sp.edit().putBoolean(HomeSettings.HOME_PREFS_DO_SHOW, true).apply();
+ return true;
+ }
+
+ private void getMetaData() {
+ try {
+ ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
+ PackageManager.GET_META_DATA);
+ if (ai == null || ai.metaData == null) return;
+ mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
+ mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
+ } catch (NameNotFoundException nnfe) {
+ // No recovery
+ Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
+ }
+ }
+
+ // give subclasses access to the Next button
+ public boolean hasNextButton() {
+ return mNextButton != null;
+ }
+
+ public Button getNextButton() {
+ return mNextButton;
+ }
+
+ public static class NoHomeDialogFragment extends DialogFragment {
+ public static void show(Activity parent) {
+ final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
+ dialog.show(parent.getFragmentManager(), null);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.only_one_home_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+ }
+
+ private static class HeaderAdapter extends ArrayAdapter<Header> {
+ static final int HEADER_TYPE_CATEGORY = 0;
+ static final int HEADER_TYPE_NORMAL = 1;
+ static final int HEADER_TYPE_SWITCH = 2;
+ static final int HEADER_TYPE_BUTTON = 3;
+ private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
+
+ private final WifiEnabler mWifiEnabler;
+ private final BluetoothEnabler mBluetoothEnabler;
+ private AuthenticatorHelper mAuthHelper;
+ private DevicePolicyManager mDevicePolicyManager;
+
+ private static class HeaderViewHolder {
+ ImageView mIcon;
+ TextView mTitle;
+ TextView mSummary;
+ Switch mSwitch;
+ ImageButton mButton;
+ View mDivider;
+ }
+
+ private LayoutInflater mInflater;
+
+ static int getHeaderType(Header header) {
+ if (header.fragment == null && header.intent == null) {
+ return HEADER_TYPE_CATEGORY;
+ } else if (header.id == R.id.security_settings) {
+ return HEADER_TYPE_BUTTON;
+ } else {
+ return HEADER_TYPE_NORMAL;
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ Header header = getItem(position);
+ return getHeaderType(header);
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false; // because of categories
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItemViewType(position) != HEADER_TYPE_CATEGORY;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return HEADER_TYPE_COUNT;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public HeaderAdapter(Context context, List<Header> objects,
+ AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
+ super(context, 0, objects);
+
+ mAuthHelper = authenticatorHelper;
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ // Temp Switches provided as placeholder until the adapter replaces these with actual
+ // Switches inflated from their layouts. Must be done before adapter is set in super
+ mWifiEnabler = new WifiEnabler(context, new Switch(context));
+ mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
+ mDevicePolicyManager = dpm;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ HeaderViewHolder holder;
+ Header header = getItem(position);
+ int headerType = getHeaderType(header);
+ View view = null;
+
+ if (convertView == null) {
+ holder = new HeaderViewHolder();
+ switch (headerType) {
+ case HEADER_TYPE_CATEGORY:
+ view = new TextView(getContext(), null,
+ android.R.attr.listSeparatorTextViewStyle);
+ holder.mTitle = (TextView) view;
+ break;
+
+ case HEADER_TYPE_SWITCH:
+ view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ holder.mSwitch = (Switch) view.findViewById(R.id.switchWidget);
+ break;
+
+ case HEADER_TYPE_BUTTON:
+ view = mInflater.inflate(R.layout.preference_header_button_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ holder.mButton = (ImageButton) view.findViewById(R.id.buttonWidget);
+ holder.mDivider = view.findViewById(R.id.divider);
+ break;
+
+ case HEADER_TYPE_NORMAL:
+ view = mInflater.inflate(
+ R.layout.preference_header_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ break;
+ }
+ view.setTag(holder);
+ } else {
+ view = convertView;
+ holder = (HeaderViewHolder) view.getTag();
+ }
+
+ // All view fields must be updated every time, because the view may be recycled
+ switch (headerType) {
+ case HEADER_TYPE_CATEGORY:
+ holder.mTitle.setText(header.getTitle(getContext().getResources()));
+ break;
+
+ case HEADER_TYPE_SWITCH:
+ // Would need a different treatment if the main menu had more switches
+ if (header.id == R.id.wifi_settings) {
+ mWifiEnabler.setSwitch(holder.mSwitch);
+ } else {
+ mBluetoothEnabler.setSwitch(holder.mSwitch);
+ }
+ updateCommonHeaderView(header, holder);
+ break;
+
+ case HEADER_TYPE_BUTTON:
+ if (header.id == R.id.security_settings) {
+ boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
+ if (hasCert) {
+ holder.mButton.setVisibility(View.VISIBLE);
+ holder.mDivider.setVisibility(View.VISIBLE);
+ boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
+ if (isManaged) {
+ holder.mButton.setImageResource(R.drawable.ic_settings_about);
+ } else {
+ holder.mButton.setImageResource(
+ android.R.drawable.stat_notify_error);
+ }
+ holder.mButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(
+ android.provider.Settings.ACTION_MONITORING_CERT_INFO);
+ getContext().startActivity(intent);
+ }
+ });
+ } else {
+ holder.mButton.setVisibility(View.GONE);
+ holder.mDivider.setVisibility(View.GONE);
+ }
+ }
+ updateCommonHeaderView(header, holder);
+ break;
+
+ case HEADER_TYPE_NORMAL:
+ updateCommonHeaderView(header, holder);
+ break;
+ }
+
+ return view;
+ }
+
+ private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
+ if (header.extras != null
+ && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
+ String accType = header.extras.getString(
+ ManageAccountsSettings.KEY_ACCOUNT_TYPE);
+ Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
+ setHeaderIcon(holder, icon);
+ } else {
+ if (header.iconRes > 0) {
+ holder.mIcon.setImageResource(header.iconRes);
+ } else {
+ holder.mIcon.setImageDrawable(null);
+ }
+ }
+ if (holder.mIcon != null) {
+ if (header.iconRes > 0) {
+ holder.mIcon.setBackgroundResource(R.color.background_drawer_icon);
+ } else {
+ holder.mIcon.setBackground(null);
+ }
+ }
+ holder.mTitle.setText(header.getTitle(getContext().getResources()));
+ CharSequence summary = header.getSummary(getContext().getResources());
+ if (!TextUtils.isEmpty(summary)) {
+ holder.mSummary.setVisibility(View.VISIBLE);
+ holder.mSummary.setText(summary);
+ } else {
+ holder.mSummary.setVisibility(View.GONE);
+ }
+ }
+
+ private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
+ ViewGroup.LayoutParams lp = holder.mIcon.getLayoutParams();
+ lp.width = getContext().getResources().getDimensionPixelSize(
+ R.dimen.header_icon_width);
+ lp.height = lp.width;
+ holder.mIcon.setLayoutParams(lp);
+ holder.mIcon.setImageDrawable(icon);
+ }
+
+ public void resume(Context context) {
+ mWifiEnabler.resume();
+ mBluetoothEnabler.resume(context);
+ }
+
+ public void pause() {
+ mWifiEnabler.pause();
+ mBluetoothEnabler.pause();
+ }
+ }
+
+ private void onListItemClick(ListView l, View v, int position, long id) {
+ if (!isResumed()) {
+ return;
+ }
+ Object item = mHeaderAdapter.getItem(position);
+ if (item instanceof Header) {
+ mSelectedHeader = (Header) item;
+ }
+ }
+
+ @Override
+ public boolean shouldUpRecreateTask(Intent targetIntent) {
+ return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
+ }
+
+ @Override
+ public void onAccountsUpdated(Account[] accounts) {
+ // TODO: watch for package upgrades to invalidate cache; see 7206643
+ mAuthenticatorHelper.updateAuthDescriptions(this);
+ mAuthenticatorHelper.onAccountsUpdated(this, accounts);
+ invalidateHeaders();
+ }
+
+ public static void requestHomeNotice() {
+ sShowNoHomeNotice = true;
+ }
+
+ /**
+ * Default value for {@link Header#id Header.id} indicating that no
+ * identifier value is set. All other values (including those below -1)
+ * are valid.
+ */
+ private static final long HEADER_ID_UNDEFINED = -1;
+
+ /**
+ * Description of a single Header item that the user can select.
+ */
+ static final class Header implements Parcelable {
+ /**
+ * Identifier for this header, to correlate with a new list when
+ * it is updated. The default value is
+ * {@link SettingsActivity#HEADER_ID_UNDEFINED}, meaning no id.
+ * @attr ref android.R.styleable#PreferenceHeader_id
+ */
+ public long id = HEADER_ID_UNDEFINED;
+
+ /**
+ * Resource ID of title of the header that is shown to the user.
+ * @attr ref android.R.styleable#PreferenceHeader_title
+ */
+ public int titleRes;
+
+ /**
+ * Title of the header that is shown to the user.
+ * @attr ref android.R.styleable#PreferenceHeader_title
+ */
+ public CharSequence title;
+
+ /**
+ * Resource ID of optional summary describing what this header controls.
+ * @attr ref android.R.styleable#PreferenceHeader_summary
+ */
+ public int summaryRes;
+
+ /**
+ * Optional summary describing what this header controls.
+ * @attr ref android.R.styleable#PreferenceHeader_summary
+ */
+ public CharSequence summary;
+
+ /**
+ * Optional icon resource to show for this header.
+ * @attr ref android.R.styleable#PreferenceHeader_icon
+ */
+ public int iconRes;
+
+ /**
+ * Full class name of the fragment to display when this header is
+ * selected.
+ * @attr ref android.R.styleable#PreferenceHeader_fragment
+ */
+ public String fragment;
+
+ /**
+ * Optional arguments to supply to the fragment when it is
+ * instantiated.
+ */
+ public Bundle fragmentArguments;
+
+ /**
+ * Intent to launch when the preference is selected.
+ */
+ public Intent intent;
+
+ /**
+ * Optional additional data for use by subclasses of the activity
+ */
+ public Bundle extras;
+
+ public Header() {
+ // Empty
+ }
+
+ /**
+ * Return the currently set title. If {@link #titleRes} is set,
+ * this resource is loaded from <var>res</var> and returned. Otherwise
+ * {@link #title} is returned.
+ */
+ public CharSequence getTitle(Resources res) {
+ if (titleRes != 0) {
+ return res.getText(titleRes);
+ }
+ return title;
+ }
+
+ /**
+ * Return the currently set summary. If {@link #summaryRes} is set,
+ * this resource is loaded from <var>res</var> and returned. Otherwise
+ * {@link #summary} is returned.
+ */
+ public CharSequence getSummary(Resources res) {
+ if (summaryRes != 0) {
+ return res.getText(summaryRes);
+ }
+ return summary;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(id);
+ dest.writeInt(titleRes);
+ TextUtils.writeToParcel(title, dest, flags);
+ dest.writeInt(summaryRes);
+ TextUtils.writeToParcel(summary, dest, flags);
+ dest.writeInt(iconRes);
+ dest.writeString(fragment);
+ dest.writeBundle(fragmentArguments);
+ if (intent != null) {
+ dest.writeInt(1);
+ intent.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeBundle(extras);
+ }
+
+ public void readFromParcel(Parcel in) {
+ id = in.readLong();
+ titleRes = in.readInt();
+ title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ summaryRes = in.readInt();
+ summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ iconRes = in.readInt();
+ fragment = in.readString();
+ fragmentArguments = in.readBundle();
+ if (in.readInt() != 0) {
+ intent = Intent.CREATOR.createFromParcel(in);
+ }
+ extras = in.readBundle();
+ }
+
+ Header(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public static final Creator<Header> CREATOR = new Creator<Header>() {
+ public Header createFromParcel(Parcel source) {
+ return new Header(source);
+ }
+ public Header[] newArray(int size) {
+ return new Header[size];
+ }
+ };
+ }
+}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 0a382b578..35893ffaf 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -22,12 +22,9 @@ import android.app.Fragment;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
import android.content.pm.PackageManager;
-import android.net.Uri;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.text.TextUtils;
import android.util.Log;
@@ -147,7 +144,7 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
Log.e(TAG, "Old dialog fragment not null!");
}
mDialogFragment = new SettingsDialogFragment(this, dialogId);
- mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
+ mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId));
}
public Dialog onCreateDialog(int dialogId) {
@@ -236,17 +233,15 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0);
+ mParentFragment = getParentFragment();
int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1);
- if (mParentFragmentId > -1) {
- mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId);
- if (!(mParentFragment instanceof DialogCreatable)) {
- throw new IllegalArgumentException(
- (mParentFragment != null
- ? mParentFragment.getClass().getName()
- : mParentFragmentId)
- + " must implement "
- + DialogCreatable.class.getName());
- }
+ if (!(mParentFragment instanceof DialogCreatable)) {
+ throw new IllegalArgumentException(
+ (mParentFragment != null
+ ? mParentFragment.getClass().getName()
+ : mParentFragmentId)
+ + " must implement "
+ + DialogCreatable.class.getName());
}
// This dialog fragment could be created from non-SettingsPreferenceFragment
if (mParentFragment instanceof SettingsPreferenceFragment) {
@@ -305,13 +300,13 @@ public class SettingsPreferenceFragment extends PreferenceFragment implements Di
public boolean startFragment(
Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
- if (getActivity() instanceof PreferenceActivity) {
- PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
- preferenceActivity.startPreferencePanel(fragmentClass, extras,
+ if (getActivity() instanceof SettingsActivity) {
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(fragmentClass, extras,
R.string.lock_settings_picker_title, null, caller, requestCode);
return true;
} else {
- Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
+ Log.w(TAG, "Parent isn't Settings activity, thus there's no way to launch the "
+ "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
+ ")");
return false;
diff --git a/src/com/android/settings/SoundSettings.java b/src/com/android/settings/SoundSettings.java
index 28d93f16a..45fd0dbee 100644
--- a/src/com/android/settings/SoundSettings.java
+++ b/src/com/android/settings/SoundSettings.java
@@ -248,8 +248,13 @@ public class SoundSettings extends SettingsPreferenceFragment implements
private void updateRingtoneName(int type, Preference preference, int msg) {
if (preference == null) return;
- Context context = getActivity();
- if (context == null) return;
+ final CharSequence summary = updateRingtoneName(getActivity(), type);
+ if (summary == null) return;
+ mHandler.sendMessage(mHandler.obtainMessage(msg, summary));
+ }
+
+ public static CharSequence updateRingtoneName(Context context, int type) {
+ if (context == null) return null;
Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type);
CharSequence summary = context.getString(com.android.internal.R.string.ringtone_unknown);
// Is it a silent ringtone?
@@ -270,7 +275,7 @@ public class SoundSettings extends SettingsPreferenceFragment implements
// Unknown title for the ringtone
}
}
- mHandler.sendMessage(mHandler.obtainMessage(msg, summary));
+ return summary;
}
private void lookupRingtoneNames() {
diff --git a/src/com/android/settings/SubSettings.java b/src/com/android/settings/SubSettings.java
index 34e9ba3a7..04955b2b0 100644
--- a/src/com/android/settings/SubSettings.java
+++ b/src/com/android/settings/SubSettings.java
@@ -16,16 +16,13 @@
package com.android.settings;
-import android.app.Fragment;
import android.util.Log;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
-
/**
* Stub class for showing sub-settings; we can't use the main Settings class
* since for our app it is a special singleTask class.
*/
-public class SubSettings extends Settings {
+public class SubSettings extends SettingsActivity {
@Override
public boolean onNavigateUp() {
diff --git a/src/com/android/settings/TrustedCredentialsSettings.java b/src/com/android/settings/TrustedCredentialsSettings.java
index cdb96cbbc..65d09348c 100644
--- a/src/com/android/settings/TrustedCredentialsSettings.java
+++ b/src/com/android/settings/TrustedCredentialsSettings.java
@@ -35,15 +35,20 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
+import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TextView;
import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
@@ -360,10 +365,42 @@ public class TrustedCredentialsSettings extends Fragment {
}
private void showCertDialog(final CertHolder certHolder) {
- View view = certHolder.mSslCert.inflateCertificateView(getActivity());
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(com.android.internal.R.string.ssl_certificate);
- builder.setView(view);
+
+ final ArrayList<View> views = new ArrayList<View>();
+ final ArrayList<String> titles = new ArrayList<String>();
+ addCertChain(certHolder, views, titles);
+
+ ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
+ android.R.layout.simple_spinner_item,
+ titles);
+ arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ Spinner spinner = new Spinner(getActivity());
+ spinner.setAdapter(arrayAdapter);
+ spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position,
+ long id) {
+ for(int i = 0; i < views.size(); i++) {
+ views.get(i).setVisibility(i == position ? View.VISIBLE : View.GONE);
+ }
+ }
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) { }
+ });
+
+ LinearLayout container = new LinearLayout(getActivity());
+ container.setOrientation(LinearLayout.VERTICAL);
+ container.addView(spinner);
+ for (int i = 0; i < views.size(); ++i) {
+ View certificateView = views.get(i);
+ if (i != 0) {
+ certificateView.setVisibility(View.GONE);
+ }
+ container.addView(certificateView);
+ }
+ builder.setView(container);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
@@ -371,6 +408,7 @@ public class TrustedCredentialsSettings extends Fragment {
});
final Dialog certDialog = builder.create();
+ View view = views.get(0);
ViewGroup body = (ViewGroup) view.findViewById(com.android.internal.R.id.body);
LayoutInflater inflater = LayoutInflater.from(getActivity());
Button removeButton = (Button) inflater.inflate(R.layout.trusted_credential_details,
@@ -409,6 +447,27 @@ public class TrustedCredentialsSettings extends Fragment {
certDialog.show();
}
+ private void addCertChain(final CertHolder certHolder, final ArrayList<View> views,
+ final ArrayList<String> titles) {
+
+ List<X509Certificate> certificates = null;
+ try {
+ certificates = mStore.getCertificateChain(certHolder.mX509Cert);
+ } catch (CertificateException ex) {
+ return;
+ }
+ for (X509Certificate certificate : certificates) {
+ addCertDetails(certificate, views, titles);
+ }
+ }
+
+ private void addCertDetails(X509Certificate certificate, final ArrayList<View> views,
+ final ArrayList<String> titles) {
+ SslCertificate sslCert = new SslCertificate(certificate);
+ views.add(sslCert.inflateCertificateView(getActivity()));
+ titles.add(sslCert.getIssuedTo().getCName());
+ }
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_PIN_CHALLENGE) {
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index da120048d..1e9fd0aee 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -192,9 +192,8 @@ public class UserDictionarySettings extends ListFragment {
args.putString(UserDictionaryAddWordContents.EXTRA_WORD, editingWord);
args.putString(UserDictionaryAddWordContents.EXTRA_SHORTCUT, editingShortcut);
args.putString(UserDictionaryAddWordContents.EXTRA_LOCALE, mLocale);
- android.preference.PreferenceActivity pa =
- (android.preference.PreferenceActivity)getActivity();
- pa.startPreferencePanel(
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(
com.android.settings.inputmethod.UserDictionaryAddWordFragment.class.getName(),
args, R.string.user_dict_settings_add_dialog_title, null, null, 0);
}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index b9e729c78..bf44835b1 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -40,31 +39,23 @@ import android.net.LinkProperties;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
-import android.preference.PreferenceActivity.Header;
import android.preference.PreferenceFrameLayout;
import android.preference.PreferenceGroup;
import android.provider.ContactsContract.CommonDataKinds;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.RawContacts;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TabWidget;
-import com.android.settings.users.ProfileUpdateReceiver;
-
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
@@ -246,7 +237,7 @@ public class Utils {
}
public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
- List<Header> target, Header header) {
+ List<SettingsActivity.Header> target, SettingsActivity.Header header) {
Intent intent = header.intent;
if (intent != null) {
diff --git a/src/com/android/settings/WallpaperTypeSettings.java b/src/com/android/settings/WallpaperTypeSettings.java
index fa5f0ac73..f46315a1d 100644
--- a/src/com/android/settings/WallpaperTypeSettings.java
+++ b/src/com/android/settings/WallpaperTypeSettings.java
@@ -16,18 +16,23 @@
package com.android.settings;
-import android.app.Activity;
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.preference.Preference;
import android.preference.PreferenceScreen;
+import com.android.settings.indexer.Indexable;
+import com.android.settings.indexer.IndexableData;
+import com.android.settings.indexer.IndexableRef;
+import java.util.ArrayList;
import java.util.List;
-public class WallpaperTypeSettings extends SettingsPreferenceFragment {
+public class WallpaperTypeSettings extends SettingsPreferenceFragment implements Indexable {
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -38,9 +43,9 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment {
private void populateWallpaperTypes() {
// Search for activities that satisfy the ACTION_SET_WALLPAPER action
- Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
+ final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
final PackageManager pm = getPackageManager();
- List<ResolveInfo> rList = pm.queryIntentActivities(intent,
+ final List<ResolveInfo> rList = pm.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
final PreferenceScreen parent = getPreferenceScreen();
@@ -58,4 +63,42 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment {
parent.addPreference(pref);
}
}
+
+ public static final IndexDataProvider INDEX_DATA_PROVIDER =
+ new IndexDataProvider() {
+ @Override
+ public List<IndexableRef> getRefsToIndex(Context context) {
+ return null;
+ }
+
+ @Override
+ public List<IndexableData> getRawDataToIndex(Context context) {
+ final List<IndexableData> result = new ArrayList<IndexableData>();
+
+ final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
+ final PackageManager pm = context.getPackageManager();
+ final List<ResolveInfo> rList = pm.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+
+ // Add indexable data for each of the matching activities
+ for (ResolveInfo info : rList) {
+ Intent prefIntent = new Intent(intent);
+ prefIntent.setComponent(new ComponentName(
+ info.activityInfo.packageName, info.activityInfo.name));
+ CharSequence label = info.loadLabel(pm);
+ if (label == null) label = info.activityInfo.packageName;
+
+ IndexableData data = new IndexableData();
+ data.title = label.toString();
+ data.fragmentTitle = context.getResources().getString(
+ R.string.wallpaper_settings_fragment_title);
+ data.intentAction = intent.getAction();
+ data.intentTargetPackage = info.activityInfo.packageName;
+ data.intentTargetClass = info.activityInfo.name;
+ result.add(data);
+ }
+
+ return result;
+ }
+ };
}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 65127b577..59074e583 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -80,6 +80,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
private ConnectivityManager mCm;
private TelephonyManager mTm;
+ private PackageManager mPm;
private static final int MANAGE_MOBILE_PLAN_DIALOG_ID = 1;
private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage";
@@ -91,7 +92,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
}
/**
* Invoked on each preference click in this hierarchy, overrides
- * PreferenceActivity's implementation. Used to make sure we track the
+ * PreferenceFragment's implementation. Used to make sure we track the
* preference click events.
*/
@Override
@@ -124,6 +125,15 @@ public class WirelessSettings extends RestrictedSettingsFragment
NetworkInfo ni = mCm.getProvisioningOrActiveNetworkInfo();
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) {
+ startActivity(provisioningIntent);
+ return;
+ }
+
// Get provisioning URL
String url = mCm.getMobileProvisioningUrl();
if (!TextUtils.isEmpty(url)) {
@@ -192,15 +202,14 @@ public class WirelessSettings extends RestrictedSettingsFragment
CharSequence[] entryValues = new CharSequence[count];
Drawable[] entryImages = new Drawable[count];
- PackageManager packageManager = getPackageManager();
int i = 0;
for (SmsApplicationData smsApplicationData : smsApplications) {
entries[i] = smsApplicationData.mApplicationName;
entryValues[i] = smsApplicationData.mPackageName;
try {
- entryImages[i] = packageManager.getApplicationIcon(smsApplicationData.mPackageName);
+ entryImages[i] = mPm.getApplicationIcon(smsApplicationData.mPackageName);
} catch (NameNotFoundException e) {
- entryImages[i] = packageManager.getDefaultActivityIcon();
+ entryImages[i] = mPm.getDefaultActivityIcon();
}
i++;
}
@@ -260,6 +269,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ mPm = getPackageManager();
addPreferencesFromResource(R.xml.wireless_settings);
@@ -352,7 +362,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
}
// Remove Airplane Mode settings if it's a stationary device such as a TV.
- if (getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
+ if (mPm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
removePreference(KEY_TOGGLE_AIRPLANE);
}
@@ -380,8 +390,7 @@ public class WirelessSettings extends RestrictedSettingsFragment
com.android.internal.R.bool.config_cellBroadcastAppLinks);
try {
if (isCellBroadcastAppLinkEnabled) {
- PackageManager pm = getPackageManager();
- if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+ if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
isCellBroadcastAppLinkEnabled = false; // CMAS app disabled
}
diff --git a/src/com/android/settings/ZenModeListPreference.java b/src/com/android/settings/ZenModeListPreference.java
new file mode 100644
index 000000000..e405e0fe5
--- /dev/null
+++ b/src/com/android/settings/ZenModeListPreference.java
@@ -0,0 +1,130 @@
+/*
+ * 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.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+public class ZenModeListPreference extends ListPreference {
+ private static final String TAG = "ZenModeListPreference";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final Handler mHandler = new Handler();
+ private final ContentResolver mResolver;
+
+ private ImageView mConfigure;
+ private int mMode;
+
+ public ZenModeListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (DEBUG) Log.d(TAG, "new ZenModeListPreference()");
+ mContext = context;
+ mResolver = context.getContentResolver();
+ setWidgetLayoutResource(R.layout.preference_zen_mode);
+ }
+
+ public void init() {
+ if (DEBUG) Log.d(TAG, "init");
+ loadZenModeSetting("init");
+ setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (DEBUG) Log.d(TAG, "onPreferenceChange " + newValue);
+ final boolean updateWithNewValue = saveZenModeSetting((String)newValue);
+ return updateWithNewValue;
+ }
+ });
+ mResolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+ false, new SettingsObserver());
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ if (DEBUG) Log.d(TAG, "onBindView");
+ super.onBindView(view);
+ mConfigure = (ImageView)view.findViewById(R.id.configure_zen_mode);
+ updateConfigureVisibility();
+ mConfigure.setOnClickListener(new OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ if (mMode != Settings.Global.ZEN_MODE_LIMITED) return;
+ if (mContext instanceof SettingsActivity) {
+ SettingsActivity sa = (SettingsActivity)mContext;
+ sa.startPreferencePanel(ZenModeSettings.class.getName(),
+ null, R.string.zen_mode_settings_title, null, null, 0);
+ }
+ }
+ });
+ }
+
+ private void updateConfigureVisibility() {
+ if (mConfigure != null) {
+ final boolean limited = mMode == Settings.Global.ZEN_MODE_LIMITED;
+ mConfigure.setVisibility(limited ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void loadZenModeSetting(String reason) {
+ if (DEBUG) Log.d(TAG, "loadZenModeSetting " + reason);
+ mMode = Settings.Global.getInt(mResolver,
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+ setValue(Integer.toString(mMode));
+ updateConfigureVisibility();
+ }
+
+ private boolean saveZenModeSetting(String value) {
+ if (DEBUG) Log.d(TAG, "saveZenModeSetting " + value);
+ try {
+ final int v = Integer.valueOf(value);
+ checkZenMode(v);
+ return Settings.Global.putInt(mResolver, Settings.Global.ZEN_MODE, v);
+ } catch (Throwable t) {
+ Log.w(TAG, "Failed to update zen mode with value: " + value, t);
+ return false;
+ }
+ }
+
+ private static void checkZenMode(int mode) {
+ if (mode < Settings.Global.ZEN_MODE_OFF || mode > Settings.Global.ZEN_MODE_FULL) {
+ throw new IllegalArgumentException("Invalid zen mode: " + mode);
+ }
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver() {
+ super(mHandler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ loadZenModeSetting("change");
+ }
+ }
+}
diff --git a/src/com/android/settings/ZenModeSettings.java b/src/com/android/settings/ZenModeSettings.java
new file mode 100644
index 000000000..15c3a5ce2
--- /dev/null
+++ b/src/com/android/settings/ZenModeSettings.java
@@ -0,0 +1,294 @@
+/*
+ * 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.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class ZenModeSettings extends SettingsPreferenceFragment {
+ private static final String TAG = "ZenModeSettings";
+ private static final boolean DEBUG = false;
+
+ private ZenModeConfigView mConfig;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final Context context = getActivity();
+ final ScrollView sv = new ScrollView(context);
+ sv.setVerticalScrollBarEnabled(false);
+ sv.setHorizontalScrollBarEnabled(false);
+ mConfig = new ZenModeConfigView(context);
+ sv.addView(mConfig);
+ return sv;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ mConfig.resetBackground();
+ }
+
+ public static final class ZenModeConfigView extends LinearLayout {
+ private static final Typeface LIGHT =
+ Typeface.create("sans-serif-light", Typeface.NORMAL);
+ private static final int BG_COLOR = 0xffe7e8e9;
+ private final Context mContext;
+
+ private Drawable mOldBackground;
+ private Toast mToast;
+
+ public ZenModeConfigView(Context context) {
+ super(context);
+ mContext = context;
+ setOrientation(VERTICAL);
+
+ int p = getResources().getDimensionPixelSize(R.dimen.content_margin_left);
+ TextView tv = addHeader("When on");
+ tv.setPadding(0, p / 2, 0, p / 4);
+ addBuckets();
+ tv = addHeader("Automatically turn on");
+ tv.setPadding(0, p / 2, 0, p / 4);
+ addTriggers();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mOldBackground = getParentView().getBackground();
+ if (DEBUG) Log.d(TAG, "onAttachedToWindow mOldBackground=" + mOldBackground);
+ getParentView().setBackgroundColor(BG_COLOR);
+ }
+
+ public void resetBackground() {
+ if (DEBUG) Log.d(TAG, "resetBackground");
+ getParentView().setBackground(mOldBackground);
+ }
+
+ private View getParentView() {
+ return (View)getParent().getParent();
+ }
+
+ private TextView addHeader(String text) {
+ TextView tv = new TextView(mContext);
+ tv.setTypeface(LIGHT);
+ tv.setTextColor(0x7f000000);
+ tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.5f);
+ tv.setText(text);
+ addView(tv);
+ return tv;
+ }
+
+ private void addTriggers() {
+ addView(new TriggerView("While driving"));
+ addView(new TriggerView("While in meetings"));
+ addView(new TriggerView("During a set time period"));
+ }
+
+ private void addBuckets() {
+ LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ BucketView callView = new BucketView(android.R.drawable.ic_menu_call, "Calls", 0,
+ "Block all", "Starred contacts only", "Allow all");
+ addView(callView, lp);
+ lp.topMargin = 4;
+ BucketView msgView = new BucketView(android.R.drawable.ic_menu_myplaces,
+ "Text & SMS Messages", 0,
+ "Block all", "Starred contacts only", "Allow all");
+ addView(msgView, lp);
+ BucketView alarmView = new BucketView(android.R.drawable.ic_menu_agenda,
+ "Alarms & Timers", 1,
+ "Block all", "Allow all");
+ addView(alarmView, lp);
+ BucketView otherView = new BucketView(android.R.drawable.ic_menu_info_details,
+ "Other Interruptions", 0,
+ "Block all", "Block all except...");
+ addView(otherView, lp);
+ }
+
+ private void notImplemented() {
+ if (mToast != null) mToast.cancel();
+ mToast = Toast.makeText(mContext, "Not implemented", Toast.LENGTH_SHORT);
+ mToast.show();
+ }
+
+ private class BucketView extends RelativeLayout {
+ private final BucketSpinner mSpinner;
+
+ public BucketView(int icon, String category, int defaultValue, String... values) {
+ super(ZenModeConfigView.this.mContext);
+
+ setBackgroundColor(0xffffffff);
+ final int p = getResources().getDimensionPixelSize(R.dimen.content_margin_left);
+
+ final ImageView iv = new ImageView(mContext);
+ iv.setId(android.R.id.icon);
+ iv.setImageResource(icon);
+ iv.setAlpha(.5f);
+
+ final int size = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.app_icon_size);
+ LayoutParams lp = new LayoutParams(size, size);
+ lp.addRule(CENTER_VERTICAL);
+ lp.leftMargin = 16;
+ lp.rightMargin = 16;
+ addView(iv, lp);
+
+ TextView tv = new TextView(mContext);
+ tv.setPadding(4, 0, 0, 0);
+ tv.setId(android.R.id.title);
+ tv.setTextColor(0xff000000);
+ tv.setText(category);
+ tv.setAllCaps(true);
+ lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(RIGHT_OF, iv.getId());
+ lp.topMargin = p / 2;
+ addView(tv, lp);
+
+ mSpinner = new BucketSpinner(defaultValue, values);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(RIGHT_OF, iv.getId());
+ lp.addRule(BELOW, tv.getId());
+ addView(mSpinner, lp);
+ }
+ }
+
+ private class BucketSpinner extends Spinner {
+ private final Bitmap mArrow;
+
+ public BucketSpinner(int defaultValue, String... values) {
+ super(ZenModeConfigView.this.mContext);
+ setGravity(Gravity.LEFT);
+ mArrow = BitmapFactory.decodeResource(getResources(),
+ R.drawable.spinner_default_holo_dark_am_no_underline);
+ setPadding(0, 0, getPaddingRight(), getPaddingBottom());
+ setBackgroundColor(0x00000000);
+ final ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, 0) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ return getDropDownView(position, convertView, parent);
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ final TextView tv = convertView != null ? (TextView) convertView
+ : new TextView(ZenModeConfigView.this.mContext);
+ tv.setText(getItem(position));
+ if (convertView == null) {
+ tv.setTypeface(LIGHT);
+ tv.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ tv.setTextColor(0xff000000);
+ tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.5f);
+ final int p = (int) tv.getTextSize() / 2;
+ if (parent instanceof ListView) {
+ final ListView lv = (ListView)parent;
+ lv.setDividerHeight(0);
+ tv.setBackgroundColor(BG_COLOR);
+ tv.setPadding(p, p, p, p);
+ } else {
+ tv.setPadding(0, 0, p, 0);
+ }
+ }
+ return tv;
+ }
+ };
+ adapter.addAll(values);
+ setAdapter(adapter);
+ setSelection(defaultValue, true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ final TextView tv = (TextView)getSelectedView();
+ final int w = (int)tv.getLayout().getLineWidth(0);
+ final int left = w - mArrow.getWidth() / 4;
+ final int top = getHeight() - mArrow.getHeight();
+ canvas.drawBitmap(mArrow, left, top, null);
+ super.onDraw(canvas);
+ }
+
+ @Override
+ public void setSelection(int position) {
+ if (position != getSelectedItemPosition()) {
+ notImplemented();
+ }
+ }
+ }
+
+ private class TriggerView extends RelativeLayout {
+ public TriggerView(String text) {
+ super(ZenModeConfigView.this.mContext);
+
+ setBackgroundColor(0xffffffff);
+ final int p = getResources().getDimensionPixelSize(R.dimen.content_margin_left);
+ final int p2 = p / 4;
+ setPadding(p2, p2, p2, p2);
+
+ final CheckBox cb = new CheckBox(mContext);
+ cb.setId(android.R.id.checkbox);
+ cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ cb.setChecked(false);
+ notImplemented();
+ }
+ }
+ });
+ LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT);
+ lp.addRule(ALIGN_PARENT_RIGHT);
+ addView(cb, lp);
+
+ final TextView tv = new TextView(mContext);
+ tv.setText(text);
+ tv.setTypeface(LIGHT);
+ tv.setTextColor(0xff000000);
+ tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.5f);
+ final int p3 = p / 2;
+ tv.setPadding(p3, 0, p3, 0);
+ lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(LEFT_OF, cb.getId());
+ lp.addRule(CENTER_VERTICAL);
+ addView(tv, lp);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 4d24d0968..9c1e30040 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -18,14 +18,8 @@ package com.android.settings.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
@@ -33,7 +27,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
@@ -42,7 +35,6 @@ import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
-import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
@@ -68,20 +60,11 @@ import java.util.Set;
*/
public class AccessibilitySettings extends SettingsPreferenceFragment implements DialogCreatable,
Preference.OnPreferenceChangeListener {
- private static final String LOG_TAG = "AccessibilitySettings";
-
- private static final String DEFAULT_SCREENREADER_MARKET_LINK =
- "market://search?q=pname:com.google.android.marvin.talkback";
private static final float LARGE_FONT_SCALE = 1.3f;
- private static final String SYSTEM_PROPERTY_MARKET_URL = "ro.screenreader.market";
-
static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':';
- private static final String KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE =
- "key_install_accessibility_service_offered_once";
-
// Preference categories
private static final String SERVICES_CATEGORY = "services_category";
private static final String SYSTEM_CATEGORY = "system_category";
@@ -103,6 +86,12 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
"captioning_preference_screen";
private static final String DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN =
"screen_magnification_preference_screen";
+ private static final String DISPLAY_CONTRAST_PREFERENCE_SCREEN =
+ "contrast_preference_screen";
+ private static final String DISPLAY_INVERSION_PREFERENCE_SCREEN =
+ "inversion_preference_screen";
+ private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN =
+ "daltonizer_preference_screen";
// Extras passed to sub-fragments.
static final String EXTRA_PREFERENCE_KEY = "preference_key";
@@ -119,9 +108,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
// presentation.
private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;
- // Dialog IDs.
- private static final int DIALOG_ID_NO_ACCESSIBILITY_SERVICES = 1;
-
// Auxiliary members.
final static SimpleStringSplitter sStringColonSplitter =
new SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
@@ -198,6 +184,9 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
private PreferenceScreen mCaptioningPreferenceScreen;
private PreferenceScreen mDisplayMagnificationPreferenceScreen;
private PreferenceScreen mGlobalGesturePreferenceScreen;
+ private PreferenceScreen mDisplayInversionPreferenceScreen;
+ private PreferenceScreen mDisplayContrastPreferenceScreen;
+ private PreferenceScreen mDisplayDaltonizerPreferenceScreen;
private int mLongPressTimeoutDefault;
@@ -214,8 +203,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
loadInstalledServices();
updateAllPreferences();
- offerInstallAccessibilitySerivceOnce();
-
mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
mSettingsContentObserver.register(getContentResolver());
if (RotationPolicy.isRotationSupported(getActivity())) {
@@ -375,6 +362,14 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
mDisplayMagnificationPreferenceScreen = (PreferenceScreen) findPreference(
DISPLAY_MAGNIFICATION_PREFERENCE_SCREEN);
+ // Display color adjustments.
+ mDisplayContrastPreferenceScreen = (PreferenceScreen) findPreference(
+ DISPLAY_CONTRAST_PREFERENCE_SCREEN);
+ mDisplayInversionPreferenceScreen = (PreferenceScreen) findPreference(
+ DISPLAY_INVERSION_PREFERENCE_SCREEN);
+ mDisplayDaltonizerPreferenceScreen = (PreferenceScreen) findPreference(
+ DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
+
// Global gesture.
mGlobalGesturePreferenceScreen =
(PreferenceScreen) findPreference(ENABLE_ACCESSIBILITY_GESTURE_PREFERENCE_SCREEN);
@@ -518,25 +513,16 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
mSelectLongPressTimeoutPreference.setValue(value);
mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValuetoTitleMap.get(value));
- // Captioning.
- final boolean captioningEnabled = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, 0) == 1;
- if (captioningEnabled) {
- mCaptioningPreferenceScreen.setSummary(R.string.accessibility_feature_state_on);
- } else {
- mCaptioningPreferenceScreen.setSummary(R.string.accessibility_feature_state_off);
- }
-
- // Screen magnification.
- final boolean magnificationEnabled = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
- if (magnificationEnabled) {
- mDisplayMagnificationPreferenceScreen.setSummary(
- R.string.accessibility_feature_state_on);
- } else {
- mDisplayMagnificationPreferenceScreen.setSummary(
- R.string.accessibility_feature_state_off);
- }
+ updateFeatureSummary(Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
+ mCaptioningPreferenceScreen);
+ updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+ mDisplayMagnificationPreferenceScreen);
+ updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+ mDisplayInversionPreferenceScreen);
+ updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
+ mDisplayContrastPreferenceScreen);
+ updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+ mDisplayDaltonizerPreferenceScreen);
// Global gesture
final boolean globalGestureEnabled = Settings.Global.getInt(getContentResolver(),
@@ -550,6 +536,12 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
}
}
+ private void updateFeatureSummary(String prefKey, Preference pref) {
+ final boolean enabled = Settings.Secure.getInt(getContentResolver(), prefKey, 0) == 1;
+ pref.setSummary(enabled ? R.string.accessibility_feature_state_on
+ : R.string.accessibility_feature_state_off);
+ }
+
private void updateLockScreenRotationCheckbox() {
Context context = getActivity();
if (context != null) {
@@ -558,72 +550,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
}
}
- private void offerInstallAccessibilitySerivceOnce() {
- // There is always one preference - if no services it is just a message.
- if (mServicesCategory.getPreference(0) != mNoServicesMessagePreference) {
- return;
- }
- SharedPreferences preferences = getActivity().getPreferences(Context.MODE_PRIVATE);
- final boolean offerInstallService = !preferences.getBoolean(
- KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE, false);
- if (offerInstallService) {
- String screenreaderMarketLink = SystemProperties.get(
- SYSTEM_PROPERTY_MARKET_URL,
- DEFAULT_SCREENREADER_MARKET_LINK);
- Uri marketUri = Uri.parse(screenreaderMarketLink);
- Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
-
- if (getPackageManager().resolveActivity(marketIntent, 0) == null) {
- // Don't show the dialog if no market app is found/installed.
- return;
- }
-
- preferences.edit().putBoolean(KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE,
- true).commit();
- // Notify user that they do not have any accessibility
- // services installed and direct them to Market to get TalkBack.
- showDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
- }
- }
-
- @Override
- public Dialog onCreateDialog(int dialogId) {
- switch (dialogId) {
- case DIALOG_ID_NO_ACCESSIBILITY_SERVICES:
- return new AlertDialog.Builder(getActivity())
- .setTitle(R.string.accessibility_service_no_apps_title)
- .setMessage(R.string.accessibility_service_no_apps_message)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // dismiss the dialog before launching
- // the activity otherwise the dialog
- // removal occurs after
- // onSaveInstanceState which triggers an
- // exception
- removeDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
- String screenreaderMarketLink = SystemProperties.get(
- SYSTEM_PROPERTY_MARKET_URL,
- DEFAULT_SCREENREADER_MARKET_LINK);
- Uri marketUri = Uri.parse(screenreaderMarketLink);
- Intent marketIntent = new Intent(Intent.ACTION_VIEW,
- marketUri);
- try {
- startActivity(marketIntent);
- } catch (ActivityNotFoundException anfe) {
- Log.w(LOG_TAG, "Couldn't start play store activity",
- anfe);
- }
- }
- })
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- default:
- return null;
- }
- }
-
private void loadInstalledServices() {
Set<ComponentName> installedServices = sInstalledServices;
installedServices.clear();
diff --git a/src/com/android/settings/accessibility/CaptionPropertiesFragment.java b/src/com/android/settings/accessibility/CaptionPropertiesFragment.java
index 8a08d90ed..49e31cfe5 100644
--- a/src/com/android/settings/accessibility/CaptionPropertiesFragment.java
+++ b/src/com/android/settings/accessibility/CaptionPropertiesFragment.java
@@ -54,6 +54,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private static final String PREF_BACKGROUND_OPACITY = "captioning_background_opacity";
private static final String PREF_FOREGROUND_COLOR = "captioning_foreground_color";
private static final String PREF_FOREGROUND_OPACITY = "captioning_foreground_opacity";
+ private static final String PREF_WINDOW_COLOR = "captioning_window_color";
+ private static final String PREF_WINDOW_OPACITY = "captioning_window_opacity";
private static final String PREF_EDGE_COLOR = "captioning_edge_color";
private static final String PREF_EDGE_TYPE = "captioning_edge_type";
private static final String PREF_FONT_SIZE = "captioning_font_size";
@@ -66,6 +68,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private CaptioningManager mCaptioningManager;
private SubtitleView mPreviewText;
+ private View mPreviewWindow;
+ private ToggleSwitch mToggleSwitch;
// Standard options.
private LocalePreference mLocale;
@@ -80,6 +84,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
private ColorPreference mEdgeColor;
private ColorPreference mBackgroundColor;
private ColorPreference mBackgroundOpacity;
+ private ColorPreference mWindowColor;
+ private ColorPreference mWindowOpacity;
private PreferenceCategory mCustom;
private boolean mShowingCustom;
@@ -119,12 +125,38 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ final boolean enabled = mCaptioningManager.isEnabled();
mPreviewText = (SubtitleView) view.findViewById(R.id.preview_text);
+ mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
+
+ final Context context = view.getContext();
+ final int padding = context.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ mToggleSwitch = new ToggleSwitch(context);
+ mToggleSwitch.setPaddingRelative(0, 0, padding, 0);
+ mToggleSwitch.setCheckedInternal(enabled);
+
+ mPreviewWindow = view.findViewById(R.id.preview_window);
+
+ getPreferenceScreen().setEnabled(enabled);
- installActionBarToggleSwitch();
refreshPreviewText();
}
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ installActionBarToggleSwitch();
+ }
+
+ @Override
+ public void onPause() {
+ removeActionBarToggleSwitch();
+
+ super.onPause();
+ }
+
private void refreshPreviewText() {
final Context context = getActivity();
if (context == null) {
@@ -145,6 +177,9 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
} else {
preview.setText(R.string.captioning_preview_text);
}
+
+ final CaptionStyle style = mCaptioningManager.getUserStyle();
+ mPreviewWindow.setBackgroundColor(style.windowColor);
}
}
@@ -167,39 +202,41 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
}
}
- private void installActionBarToggleSwitch() {
- final Activity activity = getActivity();
- final ToggleSwitch toggleSwitch = new ToggleSwitch(activity);
-
- final int padding = getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- toggleSwitch.setPaddingRelative(0, 0, padding, 0);
-
- final ActionBar actionBar = activity.getActionBar();
- actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
-
- final ActionBar.LayoutParams params = new ActionBar.LayoutParams(
- ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END);
- actionBar.setCustomView(toggleSwitch, params);
-
- final boolean enabled = mCaptioningManager.isEnabled();
- getPreferenceScreen().setEnabled(enabled);
- mPreviewText.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- toggleSwitch.setCheckedInternal(enabled);
- toggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
+ protected void onInstallActionBarToggleSwitch() {
+ mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
@Override
public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
toggleSwitch.setCheckedInternal(checked);
Settings.Secure.putInt(getActivity().getContentResolver(),
Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, checked ? 1 : 0);
getPreferenceScreen().setEnabled(checked);
- mPreviewText.setVisibility(checked ? View.VISIBLE : View.INVISIBLE);
+ if (mPreviewText != null) {
+ mPreviewText.setVisibility(checked ? View.VISIBLE : View.INVISIBLE);
+ }
return false;
}
});
}
+ private void installActionBarToggleSwitch() {
+ final ActionBar ab = getActivity().getActionBar();
+ final ActionBar.LayoutParams params = new ActionBar.LayoutParams(
+ ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END);
+ ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
+ ab.setCustomView(mToggleSwitch, params);
+
+ onInstallActionBarToggleSwitch();
+ }
+
+ private void removeActionBarToggleSwitch() {
+ mToggleSwitch.setOnBeforeCheckedChangeListener(null);
+
+ final ActionBar ab = getActivity().getActionBar();
+ ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
+ ab.setCustomView(null);
+ }
+
private void initializeAllPreferences() {
mLocale = (LocalePreference) findPreference(PREF_LOCALE);
mFontSize = (ListPreference) findPreference(PREF_FONT_SIZE);
@@ -246,6 +283,14 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mBackgroundOpacity.setTitles(opacityTitles);
mBackgroundOpacity.setValues(opacityValues);
+ mWindowColor = (ColorPreference) mCustom.findPreference(PREF_WINDOW_COLOR);
+ mWindowColor.setTitles(bgColorTitles);
+ mWindowColor.setValues(bgColorValues);
+
+ mWindowOpacity = (ColorPreference) mCustom.findPreference(PREF_WINDOW_OPACITY);
+ mWindowOpacity.setTitles(opacityTitles);
+ mWindowOpacity.setValues(opacityValues);
+
mEdgeType = (EdgeTypePreference) mCustom.findPreference(PREF_EDGE_TYPE);
mTypeface = (ListPreference) mCustom.findPreference(PREF_TYPEFACE);
}
@@ -257,6 +302,8 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
mEdgeColor.setOnValueChangedListener(this);
mBackgroundColor.setOnValueChangedListener(this);
mBackgroundOpacity.setOnValueChangedListener(this);
+ mWindowColor.setOnValueChangedListener(this);
+ mWindowOpacity.setOnValueChangedListener(this);
mEdgeType.setOnValueChangedListener(this);
mTypeface.setOnPreferenceChangeListener(this);
@@ -278,6 +325,7 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
parseColorOpacity(mForegroundColor, mForegroundOpacity, attrs.foregroundColor);
parseColorOpacity(mBackgroundColor, mBackgroundOpacity, attrs.backgroundColor);
+ parseColorOpacity(mWindowColor, mWindowOpacity, attrs.windowColor);
final String rawTypeface = attrs.mRawTypeface;
mTypeface.setValue(rawTypeface == null ? "" : rawTypeface);
@@ -334,6 +382,10 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment
final int merged = mergeColorOpacity(mBackgroundColor, mBackgroundOpacity);
Settings.Secure.putInt(
cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, merged);
+ } else if (mWindowColor == preference || mWindowOpacity == preference) {
+ final int merged = mergeColorOpacity(mWindowColor, mWindowOpacity);
+ Settings.Secure.putInt(
+ cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, merged);
} else if (mEdgeColor == preference) {
Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, value);
} else if (mPreset == preference) {
diff --git a/src/com/android/settings/accessibility/EdgeTypePreference.java b/src/com/android/settings/accessibility/EdgeTypePreference.java
index ad71a765c..3bff704f3 100644
--- a/src/com/android/settings/accessibility/EdgeTypePreference.java
+++ b/src/com/android/settings/accessibility/EdgeTypePreference.java
@@ -34,7 +34,7 @@ public class EdgeTypePreference extends ListDialogPreference {
private static final int DEFAULT_FOREGROUND_COLOR = Color.WHITE;
private static final int DEFAULT_BACKGROUND_COLOR = Color.TRANSPARENT;
private static final int DEFAULT_EDGE_COLOR = Color.BLACK;
- private static final float DEFAULT_FONT_SIZE = 96f;
+ private static final float DEFAULT_FONT_SIZE = 32f;
public EdgeTypePreference(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -57,7 +57,9 @@ public class EdgeTypePreference extends ListDialogPreference {
preview.setForegroundColor(DEFAULT_FOREGROUND_COLOR);
preview.setBackgroundColor(DEFAULT_BACKGROUND_COLOR);
- preview.setTextSize(DEFAULT_FONT_SIZE);
+
+ final float density = getContext().getResources().getDisplayMetrics().density;
+ preview.setTextSize(DEFAULT_FONT_SIZE * density);
final int value = getValueAt(index);
preview.setEdgeType(value);
diff --git a/src/com/android/settings/accessibility/PresetPreference.java b/src/com/android/settings/accessibility/PresetPreference.java
index 84aba6c7e..9f1aee37c 100644
--- a/src/com/android/settings/accessibility/PresetPreference.java
+++ b/src/com/android/settings/accessibility/PresetPreference.java
@@ -27,7 +27,7 @@ import com.android.internal.widget.SubtitleView;
import com.android.settings.R;
public class PresetPreference extends ListDialogPreference {
- private static final float DEFAULT_FONT_SIZE = 96f;
+ private static final float DEFAULT_FONT_SIZE = 32f;
private final CaptioningManager mCaptioningManager;
@@ -54,7 +54,8 @@ public class PresetPreference extends ListDialogPreference {
CaptionPropertiesFragment.applyCaptionProperties(
mCaptioningManager, previewText, value);
- previewText.setTextSize(DEFAULT_FONT_SIZE);
+ final float density = getContext().getResources().getDisplayMetrics().density;
+ previewText.setTextSize(DEFAULT_FONT_SIZE * density);
final CharSequence title = getTitleAt(index);
if (title != null) {
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 0c568f063..db473f8a8 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -154,41 +154,44 @@ public class ToggleAccessibilityServicePreferenceFragment
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DIALOG_ID_ENABLE_WARNING: {
- mShownDialogId = DIALOG_ID_ENABLE_WARNING;
- AccessibilityServiceInfo info = getAccessibilityServiceInfo();
- if (info == null) {
- return null;
+ mShownDialogId = DIALOG_ID_ENABLE_WARNING;
+ AccessibilityServiceInfo info = getAccessibilityServiceInfo();
+ if (info == null) {
+ return null;
+ }
+ AlertDialog ad = new AlertDialog.Builder(getActivity())
+ .setTitle(getString(R.string.enable_service_title,
+ info.getResolveInfo().loadLabel(getPackageManager())))
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setView(createEnableDialogContentView(info))
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .create();
+ ad.create();
+ ad.getButton(AlertDialog.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
+ return ad;
}
- return new AlertDialog.Builder(getActivity())
- .setTitle(getString(R.string.enable_service_title,
- info.getResolveInfo().loadLabel(getPackageManager())))
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setView(createEnableDialogContentView(info))
- .setCancelable(true)
- .setPositiveButton(android.R.string.ok, this)
- .setNegativeButton(android.R.string.cancel, this)
- .create();
- }
case DIALOG_ID_DISABLE_WARNING: {
- mShownDialogId = DIALOG_ID_DISABLE_WARNING;
- AccessibilityServiceInfo info = getAccessibilityServiceInfo();
- if (info == null) {
- return null;
+ mShownDialogId = DIALOG_ID_DISABLE_WARNING;
+ AccessibilityServiceInfo info = getAccessibilityServiceInfo();
+ if (info == null) {
+ return null;
+ }
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(getString(R.string.disable_service_title,
+ info.getResolveInfo().loadLabel(getPackageManager())))
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setMessage(getString(R.string.disable_service_message,
+ info.getResolveInfo().loadLabel(getPackageManager())))
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .create();
}
- return new AlertDialog.Builder(getActivity())
- .setTitle(getString(R.string.disable_service_title,
- info.getResolveInfo().loadLabel(getPackageManager())))
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setMessage(getString(R.string.disable_service_message,
- info.getResolveInfo().loadLabel(getPackageManager())))
- .setCancelable(true)
- .setPositiveButton(android.R.string.ok, this)
- .setNegativeButton(android.R.string.cancel, this)
- .create();
- }
default: {
- throw new IllegalArgumentException();
- }
+ throw new IllegalArgumentException();
+ }
}
}
diff --git a/src/com/android/settings/accessibility/ToggleContrastPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleContrastPreferenceFragment.java
new file mode 100644
index 000000000..d1e30f8d7
--- /dev/null
+++ b/src/com/android/settings/accessibility/ToggleContrastPreferenceFragment.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 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.accessibility;
+
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.preference.SeekBarPreference;
+import android.provider.Settings;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+import com.android.settings.R;
+import com.android.settings.accessibility.ToggleSwitch.OnBeforeCheckedChangeListener;
+
+public class ToggleContrastPreferenceFragment extends ToggleFeaturePreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+ private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED;
+ private static final String QUICK_SETTING_ENABLED =
+ Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_QUICK_SETTING_ENABLED;
+
+ private CheckBoxPreference mEnableQuickSetting;
+ private SeekBarPreference mBrightness;
+ private SeekBarPreference mContrast;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.accessibility_contrast_settings);
+
+ mEnableQuickSetting = (CheckBoxPreference) findPreference("enable_quick_setting");
+ mBrightness = (SeekBarPreference) findPreference("brightness");
+ mBrightness.setMax(1000);
+ mContrast = (SeekBarPreference) findPreference("contrast");
+ mContrast.setMax(1000);
+
+ initPreferences();
+ }
+
+ @Override
+ protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? 1 : 0);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mEnableQuickSetting) {
+ Settings.Secure.putInt(
+ getContentResolver(), QUICK_SETTING_ENABLED, ((Boolean) newValue) ? 1 : 0);
+ } else if (preference == mBrightness) {
+ final int progress = (Integer) newValue;
+ final float value = progress / 1000f - 0.5f;
+ Settings.Secure.putFloat(
+ getContentResolver(), Settings.Secure.ACCESSIBILITY_DISPLAY_BRIGHTNESS, value);
+ } else if (preference == mContrast) {
+ final int progress = (Integer) newValue;
+ final float value = progress / 1000f * 10f + 1f;
+ Settings.Secure.putFloat(
+ getContentResolver(), Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST, value);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ setTitle(getString(R.string.accessibility_display_contrast_preference_title));
+ }
+
+ @Override
+ protected void onInstallActionBarToggleSwitch() {
+ super.onInstallActionBarToggleSwitch();
+
+ mToggleSwitch.setCheckedInternal(
+ Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
+ mToggleSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean checked) {
+ onPreferenceToggled(mPreferenceKey, checked);
+ }
+ });
+ }
+
+ private void initPreferences() {
+ mEnableQuickSetting.setChecked(
+ Settings.Secure.getInt(getContentResolver(), QUICK_SETTING_ENABLED, 0) == 1);
+ mEnableQuickSetting.setOnPreferenceChangeListener(this);
+
+ final float brightness = Settings.Secure.getFloat(
+ getContentResolver(), Settings.Secure.ACCESSIBILITY_DISPLAY_BRIGHTNESS, 0);
+ final float contrast = Settings.Secure.getFloat(
+ getContentResolver(), Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST, 2);
+
+ // Available brightness range is -0.5 to 0.5.
+ mBrightness.setProgress((int) (1000 * (brightness + 0.5f)));
+ mBrightness.setOnPreferenceChangeListener(this);
+
+ // Available contrast range is 1 to 10.
+ mContrast.setProgress((int) (1000 * (contrast - 1f) / 10f));
+ mContrast.setOnPreferenceChangeListener(this);
+ }
+}
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
new file mode 100644
index 000000000..384aafc66
--- /dev/null
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 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.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceScreen;
+import android.preference.SeekBarPreference;
+import android.provider.Settings;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+import com.android.settings.R;
+import com.android.settings.accessibility.ToggleSwitch.OnBeforeCheckedChangeListener;
+
+public class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+ private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED;
+ private static final String TYPE = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER;
+ private static final String QUICK_SETTING_ENABLED =
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_QUICK_SETTING_ENABLED;
+ private static final int DEFAULT_TYPE = AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
+
+ private CheckBoxPreference mEnableQuickSetting;
+ private ListPreference mType;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.accessibility_daltonizer_settings);
+
+ mEnableQuickSetting = (CheckBoxPreference) findPreference("enable_quick_setting");
+ mType = (ListPreference) findPreference("type");
+
+ initPreferences();
+ }
+
+ @Override
+ protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? 1 : 0);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mEnableQuickSetting) {
+ Settings.Secure.putInt(
+ getContentResolver(), QUICK_SETTING_ENABLED, ((Boolean) newValue) ? 1 : 0);
+ } else if (preference == mType) {
+ Settings.Secure.putInt(getContentResolver(), TYPE, Integer.parseInt((String) newValue));
+ preference.setSummary("%s");
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ setTitle(getString(R.string.accessibility_display_daltonizer_preference_title));
+ }
+
+ @Override
+ protected void onInstallActionBarToggleSwitch() {
+ super.onInstallActionBarToggleSwitch();
+
+ mToggleSwitch.setCheckedInternal(
+ Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
+ mToggleSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean checked) {
+ onPreferenceToggled(mPreferenceKey, checked);
+ }
+ });
+ }
+
+ private void initPreferences() {
+ mEnableQuickSetting.setChecked(
+ Settings.Secure.getInt(getContentResolver(), QUICK_SETTING_ENABLED, 0) == 1);
+ mEnableQuickSetting.setOnPreferenceChangeListener(this);
+
+ final String value = Integer.toString(
+ Settings.Secure.getInt(getContentResolver(), TYPE, DEFAULT_TYPE));
+ mType.setValue(value);
+ mType.setOnPreferenceChangeListener(this);
+ final int index = mType.findIndexOfValue(value);
+ if (index < 0) {
+ // We're using a mode controlled by developer preferences.
+ mType.setSummary(getString(R.string.daltonizer_type_overridden,
+ getString(R.string.simulate_color_space)));
+ }
+ }
+}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 2fbbabdb0..03f907263 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -18,12 +18,12 @@ package com.android.settings.accessibility;
import android.app.ActionBar;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.view.Gravity;
import android.view.Menu;
@@ -35,6 +35,7 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
public abstract class ToggleFeaturePreferenceFragment
@@ -86,18 +87,28 @@ public abstract class ToggleFeaturePreferenceFragment
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- onInstallActionBarToggleSwitch();
+
+ final Context context = view.getContext();
+ final int padding = context.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ mToggleSwitch = new ToggleSwitch(context);
+ mToggleSwitch.setPaddingRelative(0, 0, padding, 0);
+
onProcessArguments(getArguments());
- // Set a transparent drawable to prevent use of the default one.
- getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
- getListView().setDivider(null);
}
@Override
- public void onDestroyView() {
- getActivity().getActionBar().setCustomView(null);
- mToggleSwitch.setOnBeforeCheckedChangeListener(null);
- super.onDestroyView();
+ public void onResume() {
+ super.onResume();
+
+ installActionBarToggleSwitch();
+ }
+
+ @Override
+ public void onPause() {
+ removeActionBarToggleSwitch();
+
+ super.onPause();
}
protected abstract void onPreferenceToggled(String preferenceKey, boolean enabled);
@@ -111,37 +122,66 @@ public abstract class ToggleFeaturePreferenceFragment
}
protected void onInstallActionBarToggleSwitch() {
- mToggleSwitch = createAndAddActionBarToggleSwitch(getActivity());
+ // Implement this to set a checked listener.
}
- private ToggleSwitch createAndAddActionBarToggleSwitch(Activity activity) {
- ToggleSwitch toggleSwitch = new ToggleSwitch(activity);
- final int padding = activity.getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- toggleSwitch.setPaddingRelative(0, 0, padding, 0);
- activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
- ActionBar.DISPLAY_SHOW_CUSTOM);
- activity.getActionBar().setCustomView(toggleSwitch,
- new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
- ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END));
- return toggleSwitch;
+ private void installActionBarToggleSwitch() {
+ final ActionBar ab = getActivity().getActionBar();
+ final ActionBar.LayoutParams params = new ActionBar.LayoutParams(
+ ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END);
+ ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
+ ab.setCustomView(mToggleSwitch, params);
+
+ onInstallActionBarToggleSwitch();
+ }
+
+ private void removeActionBarToggleSwitch() {
+ mToggleSwitch.setOnBeforeCheckedChangeListener(null);
+
+ final ActionBar ab = getActivity().getActionBar();
+ ab.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
+ ab.setCustomView(null);
+ }
+
+ public void setTitle(String title) {
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ if (!activity.onIsHidingHeaders()) {
+ getActivity().setTitle(title);
+ }
}
protected void onProcessArguments(Bundle arguments) {
+ if (arguments == null) {
+ getPreferenceScreen().removePreference(mSummaryPreference);
+ return;
+ }
+
// Key.
mPreferenceKey = arguments.getString(AccessibilitySettings.EXTRA_PREFERENCE_KEY);
+
// Enabled.
- final boolean enabled = arguments.getBoolean(AccessibilitySettings.EXTRA_CHECKED);
- mToggleSwitch.setCheckedInternal(enabled);
+ if (arguments.containsKey(AccessibilitySettings.EXTRA_CHECKED)) {
+ final boolean enabled = arguments.getBoolean(AccessibilitySettings.EXTRA_CHECKED);
+ mToggleSwitch.setCheckedInternal(enabled);
+ }
+
// Title.
- PreferenceActivity activity = (PreferenceActivity) getActivity();
- if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
- String title = arguments.getString(AccessibilitySettings.EXTRA_TITLE);
- getActivity().setTitle(title);
+ if (arguments.containsKey(AccessibilitySettings.EXTRA_TITLE)) {
+ setTitle(arguments.getString(AccessibilitySettings.EXTRA_TITLE));
}
+
// Summary.
- CharSequence summary = arguments.getCharSequence(AccessibilitySettings.EXTRA_SUMMARY);
- mSummaryPreference.setSummary(summary);
+ if (arguments.containsKey(AccessibilitySettings.EXTRA_SUMMARY)) {
+ final CharSequence summary = arguments.getCharSequence(
+ AccessibilitySettings.EXTRA_SUMMARY);
+ mSummaryPreference.setSummary(summary);
+
+ // Set a transparent drawable to prevent use of the default one.
+ getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
+ getListView().setDivider(null);
+ } else {
+ getPreferenceScreen().removePreference(mSummaryPreference);
+ }
}
}
diff --git a/src/com/android/settings/accessibility/ToggleInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleInversionPreferenceFragment.java
new file mode 100644
index 000000000..bfb250059
--- /dev/null
+++ b/src/com/android/settings/accessibility/ToggleInversionPreferenceFragment.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.preference.SeekBarPreference;
+import android.provider.Settings;
+import android.view.View;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+
+import com.android.settings.R;
+import com.android.settings.accessibility.ToggleSwitch.OnBeforeCheckedChangeListener;
+
+public class ToggleInversionPreferenceFragment extends ToggleFeaturePreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+ private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED;
+ private static final String TYPE = Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION;
+ private static final String QUICK_SETTING_ENABLED =
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_QUICK_SETTING_ENABLED;
+ private static final int DEFAULT_TYPE = AccessibilityManager.INVERSION_STANDARD;
+
+ private CheckBoxPreference mEnableQuickSetting;
+ private ListPreference mType;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.accessibility_inversion_settings);
+
+ mEnableQuickSetting = (CheckBoxPreference) findPreference("enable_quick_setting");
+ mType = (ListPreference) findPreference("type");
+
+ initPreferences();
+ }
+
+ @Override
+ protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
+ Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? 1 : 0);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mEnableQuickSetting) {
+ Settings.Secure.putInt(
+ getContentResolver(), QUICK_SETTING_ENABLED, ((Boolean) newValue) ? 1 : 0);
+ } else if (preference == mType) {
+ Settings.Secure.putInt(getContentResolver(), TYPE, Integer.parseInt((String) newValue));
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ setTitle(getString(R.string.accessibility_display_inversion_preference_title));
+ }
+
+ @Override
+ protected void onInstallActionBarToggleSwitch() {
+ super.onInstallActionBarToggleSwitch();
+
+ mToggleSwitch.setCheckedInternal(
+ Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
+ mToggleSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean checked) {
+ onPreferenceToggled(mPreferenceKey, checked);
+ }
+ });
+ }
+
+ private void initPreferences() {
+ mEnableQuickSetting.setChecked(
+ Settings.Secure.getInt(getContentResolver(), QUICK_SETTING_ENABLED, 0) == 1);
+ mEnableQuickSetting.setOnPreferenceChangeListener(this);
+
+ mType.setValue(
+ Integer.toString(Settings.Secure.getInt(getContentResolver(), TYPE, DEFAULT_TYPE)));
+ mType.setOnPreferenceChangeListener(this);
+ }
+}
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index 2759a8f16..f5332633a 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -38,7 +38,6 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.text.format.DateFormat;
import android.util.Log;
diff --git a/src/com/android/settings/accounts/AddAccountSettings.java b/src/com/android/settings/accounts/AddAccountSettings.java
index 39906eb30..34b6c8d64 100644
--- a/src/com/android/settings/accounts/AddAccountSettings.java
+++ b/src/com/android/settings/accounts/AddAccountSettings.java
@@ -31,6 +31,7 @@ import android.util.Log;
import android.widget.Toast;
import com.android.settings.R;
+import com.android.settings.Settings;
import com.android.settings.Utils;
import java.io.IOException;
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index 184f68092..b5a6579e3 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -31,7 +31,6 @@ import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.LayoutInflater;
@@ -45,6 +44,7 @@ import android.widget.TextView;
import com.android.settings.AccountPreference;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.location.LocationSettings;
@@ -146,7 +146,7 @@ public class ManageAccountsSettings extends AccountPreferenceBase
private void startAccountSettings(AccountPreference acctPref) {
Bundle args = new Bundle();
args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, acctPref.getAccount());
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
AccountSyncSettings.class.getCanonicalName(), args,
R.string.account_sync_settings_title, acctPref.getAccount().name,
this, REQUEST_SHOW_SYNC_SETTINGS);
@@ -368,7 +368,7 @@ public class ManageAccountsSettings extends AccountPreferenceBase
@Override
public boolean onPreferenceClick(Preference preference) {
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
mClass, null, mTitleRes, null, null, 0);
// Hack: announce that the Google account preferences page is launching the location
// settings
diff --git a/src/com/android/settings/accounts/SyncSettingsActivity.java b/src/com/android/settings/accounts/SyncSettingsActivity.java
index 96f16d684..9b1bc32e7 100644
--- a/src/com/android/settings/accounts/SyncSettingsActivity.java
+++ b/src/com/android/settings/accounts/SyncSettingsActivity.java
@@ -16,22 +16,20 @@
package com.android.settings.accounts;
-import android.app.Fragment;
import android.content.Intent;
-import android.preference.PreferenceActivity;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.SettingsActivity;
/**
* Launcher activity for the SyncSettings fragment.
*
*/
-public class SyncSettingsActivity extends PreferenceActivity {
+public class SyncSettingsActivity extends SettingsActivity {
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
- modIntent.putExtra(EXTRA_SHOW_FRAGMENT, SyncSettings.class.getName());
- modIntent.putExtra(EXTRA_NO_HEADERS, true);
+ modIntent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, SyncSettings.class.getName());
+ modIntent.putExtra(SettingsActivity.EXTRA_NO_HEADERS, true);
return modIntent;
}
diff --git a/src/com/android/settings/applications/AppOpsCategory.java b/src/com/android/settings/applications/AppOpsCategory.java
index 125a43b9d..03ebb9e5e 100644
--- a/src/com/android/settings/applications/AppOpsCategory.java
+++ b/src/com/android/settings/applications/AppOpsCategory.java
@@ -28,7 +28,6 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +39,7 @@ import android.widget.TextView;
import java.util.List;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.applications.AppOpsState.AppOpEntry;
public class AppOpsCategory extends ListFragment implements
@@ -333,8 +333,8 @@ public class AppOpsCategory extends ListFragment implements
Bundle args = new Bundle();
args.putString(AppOpsDetails.ARG_PACKAGE_NAME, mCurrentPkgName);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.startPreferencePanel(AppOpsDetails.class.getName(), args,
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(AppOpsDetails.class.getName(), args,
R.string.app_ops_settings, null, this, RESULT_APP_DETAILS);
}
diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java
index 1e2ac7d63..d9dec1958 100644
--- a/src/com/android/settings/applications/AppOpsDetails.java
+++ b/src/com/android/settings/applications/AppOpsDetails.java
@@ -28,7 +28,6 @@ import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -40,6 +39,7 @@ import android.widget.Switch;
import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import java.util.List;
@@ -161,8 +161,8 @@ public class AppOpsDetails extends Fragment {
private void setIntentAndFinish(boolean finish, boolean appChanged) {
Intent intent = new Intent();
intent.putExtra(ManageApplications.APP_CHG, appChanged);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
+ SettingsActivity sa = (SettingsActivity)getActivity();
+ sa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
}
/** Called when the activity is first created. */
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 6729ea947..b1145a11c 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -19,6 +19,7 @@ package com.android.settings.applications;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.SmsUsageMonitor;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
@@ -57,7 +58,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
-import android.preference.PreferenceActivity;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.format.Formatter;
@@ -926,8 +926,8 @@ public class InstalledAppDetails extends Fragment
if(localLOGV) Log.i(TAG, "appChanged="+appChanged);
Intent intent = new Intent();
intent.putExtra(ManageApplications.APP_CHG, appChanged);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
+ SettingsActivity sa = (SettingsActivity)getActivity();
+ sa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
}
private void refreshSizeInfo() {
diff --git a/src/com/android/settings/applications/InstalledAppDetailsTop.java b/src/com/android/settings/applications/InstalledAppDetailsTop.java
index 44a88fb5e..e731c1c12 100644
--- a/src/com/android/settings/applications/InstalledAppDetailsTop.java
+++ b/src/com/android/settings/applications/InstalledAppDetailsTop.java
@@ -1,12 +1,25 @@
+/*
+ * Copyright (C) 2010 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.applications;
-import android.app.Fragment;
import android.content.Intent;
-import android.preference.PreferenceActivity;
-
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.SettingsActivity;
-public class InstalledAppDetailsTop extends PreferenceActivity {
+public class InstalledAppDetailsTop extends SettingsActivity {
@Override
public Intent getIntent() {
@@ -21,5 +34,4 @@ public class InstalledAppDetailsTop extends PreferenceActivity {
if (InstalledAppDetails.class.getName().equals(fragmentName)) return true;
return false;
}
-
}
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 8b4be0141..d68b6a998 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -29,7 +29,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -44,9 +43,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceFrameLayout;
-import android.provider.Settings;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
@@ -72,6 +69,7 @@ import android.widget.TextView;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.content.PackageHelper;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.Settings.RunningServicesActivity;
import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.applications.ApplicationsState.AppEntry;
@@ -854,7 +852,7 @@ public class ManageApplications extends Fragment implements
|| className.endsWith(".StorageUse")) {
mSortOrder = SORT_ORDER_SIZE;
defaultListType = LIST_TYPE_ALL;
- } else if (Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS.equals(action)) {
+ } else if (android.provider.Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS.equals(action)) {
// Select the all-apps list, with the default sorting
defaultListType = LIST_TYPE_ALL;
}
@@ -1037,8 +1035,8 @@ public class ManageApplications extends Fragment implements
Bundle args = new Bundle();
args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
R.string.application_info_label, null, this, INSTALLED_APP_DETAILS);
}
diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java
index 0821ced23..87024783f 100644
--- a/src/com/android/settings/applications/ProcStatsEntry.java
+++ b/src/com/android/settings/applications/ProcStatsEntry.java
@@ -23,6 +23,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.app.ProcessStats;
import java.util.ArrayList;
@@ -109,22 +110,26 @@ public final class ProcStatsEntry implements Parcelable {
// See if there is one significant package that was running here.
ArrayList<ProcStatsEntry> subProcs = new ArrayList<ProcStatsEntry>();
for (int ipkg=0; ipkg<mPackages.size(); ipkg++) {
- ProcessStats.PackageState pkgState = stats.mPackages.get(mPackages.get(ipkg), mUid);
- if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
- + mPackages.get(ipkg) + ":");
- if (pkgState == null) {
- Log.w(TAG, "No package state found for " + mPackages.get(ipkg) + "/"
- + mUid + " in process " + mName);
- continue;
- }
- ProcessStats.ProcessState pkgProc = pkgState.mProcesses.get(mName);
- if (pkgProc == null) {
- Log.w(TAG, "No process " + mName + " found in package state "
- + mPackages.get(ipkg) + "/" + mUid);
- continue;
+ SparseArray<ProcessStats.PackageState> vpkgs
+ = stats.mPackages.get(mPackages.get(ipkg), mUid);
+ for (int ivers=0; ivers<vpkgs.size(); ivers++) {
+ ProcessStats.PackageState pkgState = vpkgs.valueAt(ivers);
+ if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ", pkg "
+ + pkgState + ":");
+ if (pkgState == null) {
+ Log.w(TAG, "No package state found for " + mPackages.get(ipkg) + "/"
+ + mUid + " in process " + mName);
+ continue;
+ }
+ ProcessStats.ProcessState pkgProc = pkgState.mProcesses.get(mName);
+ if (pkgProc == null) {
+ Log.w(TAG, "No process " + mName + " found in package state "
+ + mPackages.get(ipkg) + "/" + mUid);
+ continue;
+ }
+ subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, totals, useUss,
+ weightWithTime));
}
- subProcs.add(new ProcStatsEntry(pkgProc, pkgState.mPackageName, totals, useUss,
- weightWithTime));
}
if (subProcs.size() > 1) {
Collections.sort(subProcs, compare);
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index 326ca7bb3..5d0660a90 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -30,7 +30,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
-import android.preference.PreferenceActivity;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
@@ -161,7 +160,6 @@ public class ProcessStatsDetail extends Fragment implements Button.OnClickListen
}
private void doAction(int action) {
- PreferenceActivity pa = (PreferenceActivity)getActivity();
switch (action) {
case ACTION_FORCE_STOP:
killProcesses();
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index 8322ea352..9deb22ddd 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -25,7 +25,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserManager;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
@@ -40,6 +39,7 @@ import com.android.internal.app.IProcessStats;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.Utils;
import java.io.IOException;
@@ -192,7 +192,7 @@ public class ProcessStatsUi extends PreferenceFragment
args.putBoolean(ProcessStatsDetail.EXTRA_USE_USS, mUseUss);
args.putLong(ProcessStatsDetail.EXTRA_MAX_WEIGHT, mMaxWeight);
args.putLong(ProcessStatsDetail.EXTRA_TOTAL_TIME, mTotalTime);
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
ProcessStatsDetail.class.getName(), args, R.string.details_title, null, null, 0);
return super.onPreferenceTreeClick(preferenceScreen, preference);
@@ -466,33 +466,36 @@ public class ProcessStatsUi extends PreferenceFragment
final ProcessMap<ProcStatsEntry> entriesMap = new ProcessMap<ProcStatsEntry>();
for (int ipkg=0, N=mStats.mPackages.getMap().size(); ipkg<N; ipkg++) {
- final SparseArray<ProcessStats.PackageState> pkgUids
+ final SparseArray<SparseArray<ProcessStats.PackageState>> pkgUids
= mStats.mPackages.getMap().valueAt(ipkg);
for (int iu=0; iu<pkgUids.size(); iu++) {
- final ProcessStats.PackageState st = pkgUids.valueAt(iu);
- for (int iproc=0; iproc<st.mProcesses.size(); iproc++) {
- final ProcessStats.ProcessState pkgProc = st.mProcesses.valueAt(iproc);
- final ProcessStats.ProcessState proc = mStats.mProcesses.get(pkgProc.mName,
- pkgProc.mUid);
- if (proc == null) {
- Log.w(TAG, "No process found for pkg " + st.mPackageName
- + "/" + st.mUid + " proc name " + pkgProc.mName);
- continue;
- }
- ProcStatsEntry ent = entriesMap.get(proc.mName, proc.mUid);
- if (ent == null) {
- ent = new ProcStatsEntry(proc, st.mPackageName, totals, mUseUss,
- mStatsType == MENU_TYPE_BACKGROUND);
- if (ent.mDuration > 0) {
- if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
- + proc.mUid + ": time=" + makeDuration(ent.mDuration) + " ("
- + ((((double)ent.mDuration) / memTotalTime) * 100) + "%)"
- + " pss=" + ent.mAvgPss);
- entriesMap.put(proc.mName, proc.mUid, ent);
- entries.add(ent);
+ final SparseArray<ProcessStats.PackageState> vpkgs = pkgUids.valueAt(iu);
+ for (int iv=0; iv<vpkgs.size(); iv++) {
+ final ProcessStats.PackageState st = vpkgs.valueAt(iv);
+ for (int iproc=0; iproc<st.mProcesses.size(); iproc++) {
+ final ProcessStats.ProcessState pkgProc = st.mProcesses.valueAt(iproc);
+ final ProcessStats.ProcessState proc = mStats.mProcesses.get(pkgProc.mName,
+ pkgProc.mUid);
+ if (proc == null) {
+ Log.w(TAG, "No process found for pkg " + st.mPackageName
+ + "/" + st.mUid + " proc name " + pkgProc.mName);
+ continue;
+ }
+ ProcStatsEntry ent = entriesMap.get(proc.mName, proc.mUid);
+ if (ent == null) {
+ ent = new ProcStatsEntry(proc, st.mPackageName, totals, mUseUss,
+ mStatsType == MENU_TYPE_BACKGROUND);
+ if (ent.mDuration > 0) {
+ if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
+ + proc.mUid + ": time=" + makeDuration(ent.mDuration) + " ("
+ + ((((double)ent.mDuration) / memTotalTime) * 100) + "%)"
+ + " pss=" + ent.mAvgPss);
+ entriesMap.put(proc.mName, proc.mUid, ent);
+ entries.add(ent);
+ }
+ } else {
+ ent.addPackage(st.mPackageName);
}
- } else {
- ent.addPackage(st.mPackageName);
}
}
}
@@ -503,21 +506,25 @@ public class ProcessStatsUi extends PreferenceFragment
// Add in service info.
if (mStatsType == MENU_TYPE_BACKGROUND) {
for (int ip=0, N=mStats.mPackages.getMap().size(); ip<N; ip++) {
- SparseArray<ProcessStats.PackageState> uids = mStats.mPackages.getMap().valueAt(ip);
+ SparseArray<SparseArray<ProcessStats.PackageState>> uids
+ = mStats.mPackages.getMap().valueAt(ip);
for (int iu=0; iu<uids.size(); iu++) {
- ProcessStats.PackageState ps = uids.valueAt(iu);
- for (int is=0, NS=ps.mServices.size(); is<NS; is++) {
- ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
- if (ss.mProcessName != null) {
- ProcStatsEntry ent = entriesMap.get(ss.mProcessName, uids.keyAt(iu));
- if (ent != null) {
- if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
- + "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
- + ss.mProcessName);
- ent.addService(ss);
- } else {
- Log.w(TAG, "No process " + ss.mProcessName + "/" + uids.keyAt(iu)
- + " for service " + ss.mName);
+ SparseArray<ProcessStats.PackageState> vpkgs = uids.valueAt(iu);
+ for (int iv=0; iv<vpkgs.size(); iv++) {
+ ProcessStats.PackageState ps = vpkgs.valueAt(iv);
+ for (int is=0, NS=ps.mServices.size(); is<NS; is++) {
+ ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
+ if (ss.mProcessName != null) {
+ ProcStatsEntry ent = entriesMap.get(ss.mProcessName, uids.keyAt(iu));
+ if (ent != null) {
+ if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
+ + "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
+ + ss.mProcessName);
+ ent.addService(ss);
+ } else {
+ Log.w(TAG, "No process " + ss.mProcessName + "/" + uids.keyAt(iu)
+ + " for service " + ss.mName);
+ }
}
}
}
diff --git a/src/com/android/settings/applications/RunningProcessesView.java b/src/com/android/settings/applications/RunningProcessesView.java
index 8eb0496cd..caa545076 100644
--- a/src/com/android/settings/applications/RunningProcessesView.java
+++ b/src/com/android/settings/applications/RunningProcessesView.java
@@ -28,7 +28,6 @@ import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.preference.PreferenceActivity;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.util.AttributeSet;
@@ -42,6 +41,7 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AbsListView.RecyclerListener;
+import com.android.settings.SettingsActivity;
import java.util.ArrayList;
import java.util.Collections;
@@ -397,9 +397,9 @@ public class RunningProcessesView extends FrameLayout
}
args.putInt(RunningServiceDetails.KEY_USER_ID, mi.mUserId);
args.putBoolean(RunningServiceDetails.KEY_BACKGROUND, mAdapter.mShowBackground);
-
- PreferenceActivity pa = (PreferenceActivity)mOwner.getActivity();
- pa.startPreferencePanel(RunningServiceDetails.class.getName(), args,
+
+ SettingsActivity sa = (SettingsActivity) mOwner.getActivity();
+ sa.startPreferencePanel(RunningServiceDetails.class.getName(), args,
R.string.runningservicedetails_settings_title, null, null, 0);
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothAdvertisingEnabler.java b/src/com/android/settings/bluetooth/BluetoothAdvertisingEnabler.java
deleted file mode 100644
index b9e4ee2e8..000000000
--- a/src/com/android/settings/bluetooth/BluetoothAdvertisingEnabler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 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.content.Context;
-import android.preference.PreferenceScreen;
-
-import com.android.settings.R;
-
-/**
- * BluetoothAdvertisingEnabler helps manager change of bluetooth advertising preferences.
- */
-final class BluetoothAdvertisingEnabler {
-
- private final Context mContext;
- private final PreferenceScreen mBluetoothAdvertisingPreference;
-
- public BluetoothAdvertisingEnabler(Context context, PreferenceScreen bluetoothBroadcast) {
- mContext = context;
- mBluetoothAdvertisingPreference = bluetoothBroadcast;
- }
-
- public void resume() {
- boolean isBroadcastingEnable = LocalBluetoothPreferences.isAdvertisingEnabled(mContext);
- handleAdvertisingStateChange(isBroadcastingEnable);
- }
-
- private void handleAdvertisingStateChange(boolean isBroadcastingEnable) {
- mBluetoothAdvertisingPreference.setSummary(isBroadcastingEnable ?
- R.string.bluetooth_broadcasting_state_on :
- R.string.bluetooth_broadcasting_state_off);
- }
-}
diff --git a/src/com/android/settings/bluetooth/BluetoothAdvertisingFragment.java b/src/com/android/settings/bluetooth/BluetoothAdvertisingFragment.java
deleted file mode 100644
index ea6adb046..000000000
--- a/src/com/android/settings/bluetooth/BluetoothAdvertisingFragment.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 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.app.ActionBar;
-import android.app.Activity;
-import android.app.Fragment;
-import android.bluetooth.BluetoothAdapter;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CompoundButton;
-import android.widget.Switch;
-
-import com.android.settings.R;
-
-/**
- * Fragment to display and let the user change advertising preference.
- */
-public class BluetoothAdvertisingFragment extends Fragment
- implements CompoundButton.OnCheckedChangeListener {
-
- private static final String TAG = "BluetoothAdvertisingFragment";
- private View mView;
- private Switch mActionBarSwitch;
- private Activity mActivity;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mActivity = getActivity();
- mActionBarSwitch = new Switch(mActivity);
- if (mActivity instanceof PreferenceActivity) {
- final int padding = mActivity.getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- mActionBarSwitch.setPaddingRelative(0, 0, padding, 0);
- mActivity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
- ActionBar.DISPLAY_SHOW_CUSTOM);
- mActivity.getActionBar().setCustomView(mActionBarSwitch, new ActionBar.LayoutParams(
- ActionBar.LayoutParams.WRAP_CONTENT,
- ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END));
- mActivity.getActionBar().setTitle(R.string.bluetooth_broadcasting);
- }
- mActionBarSwitch.setChecked(
- LocalBluetoothPreferences.isAdvertisingEnabled(mActivity.getApplicationContext()));
-
- mActionBarSwitch.setOnCheckedChangeListener(this);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- mView = inflater.inflate(R.layout.bluetooth_advertising, container, false);
- initView(mView);
- return mView;
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- getActivity().getActionBar().setCustomView(null);
- }
-
- private void initView(View view) {
- mActionBarSwitch.setOnCheckedChangeListener(this);
- }
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean desiredState) {
- mActionBarSwitch.setChecked(desiredState);
- Context context = getActivity();
- LocalBluetoothPreferences.setAdvertisingEnabled(context, desiredState);
- if (!desiredState) {
- LocalBluetoothAdapter adapter =
- LocalBluetoothManager.getInstance(context).getBluetoothAdapter();
- // Stop advertising if advertising is in process.
- if (adapter.isAdvertising()) {
- Intent intent = new Intent(BluetoothAdapter.ACTION_STOP_ADVERTISING);
- getActivity().startActivity(intent);
- }
- }
- }
-}
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
index a040bf293..17da0a783 100755
--- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
@@ -25,10 +25,13 @@ import android.content.SharedPreferences;
import android.os.Handler;
import android.os.SystemProperties;
import android.preference.Preference;
-import android.util.Log;
+import android.text.format.DateUtils;
import com.android.settings.R;
+import android.text.format.Time;
+import android.util.Log;
+
/**
* BluetoothDiscoverableEnabler is a helper to manage the "Discoverable"
* checkbox. It sets/unsets discoverability and keeps track of how much time
@@ -57,11 +60,9 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick
static final int DEFAULT_DISCOVERABLE_TIMEOUT = DISCOVERABLE_TIMEOUT_TWO_MINUTES;
- private final Context mContext;
+ private Context mContext;
private final Handler mUiHandler;
private final Preference mDiscoveryPreference;
- // Preference for visibility time out. Not final as it needs to be set through setter.
- private Preference mVisibilityTimeoutPreference;
private final LocalBluetoothAdapter mLocalAdapter;
@@ -91,9 +92,8 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick
}
};
- BluetoothDiscoverableEnabler(Context context, LocalBluetoothAdapter adapter,
+ BluetoothDiscoverableEnabler(LocalBluetoothAdapter adapter,
Preference discoveryPreference) {
- mContext = context;
mUiHandler = new Handler();
mLocalAdapter = adapter;
mDiscoveryPreference = discoveryPreference;
@@ -101,20 +101,19 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick
discoveryPreference.setPersistent(false);
}
- public void setVisibilityPreference(Preference visibilityPreference) {
- mVisibilityTimeoutPreference = visibilityPreference;
- }
-
- public void resume() {
+ public void resume(Context context) {
if (mLocalAdapter == null) {
return;
}
+ if (mContext != context) {
+ mContext = context;
+ }
+
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
mContext.registerReceiver(mReceiver, filter);
mDiscoveryPreference.setOnPreferenceClickListener(this);
handleModeChanged(mLocalAdapter.getScanMode());
- updateVisibilityTimeoutDisplay();
}
public void pause() {
@@ -125,9 +124,6 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick
mUiHandler.removeCallbacks(mUpdateCountdownSummaryRunnable);
mContext.unregisterReceiver(mReceiver);
mDiscoveryPreference.setOnPreferenceClickListener(null);
- if (mVisibilityTimeoutPreference != null) {
- mVisibilityTimeoutPreference.setOnPreferenceClickListener(null);
- }
}
public boolean onPreferenceClick(Preference preference) {
@@ -150,28 +146,14 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick
if (timeout > 0) {
BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(mContext, endTimestamp);
+ } else {
+ BluetoothDiscoverableTimeoutReceiver.cancelDiscoverableAlarm(mContext);
}
+
} else {
mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
BluetoothDiscoverableTimeoutReceiver.cancelDiscoverableAlarm(mContext);
}
- updateVisibilityTimeoutDisplay();
- }
-
- // Update visibility timeout preference.
- private void updateVisibilityTimeoutDisplay() {
- if (mVisibilityTimeoutPreference == null) {
- return;
- }
- int index = getDiscoverableTimeoutIndex();
-
- String visibilitySummary = "";
- CharSequence[] timeoutChoices =
- mContext.getResources().getTextArray(R.array.bluetooth_visibility_timeout_entries);
- if (index >= 0 && index < timeoutChoices.length) {
- visibilitySummary = timeoutChoices[index].toString();
- }
- mVisibilityTimeoutPreference.setSummary(visibilitySummary);
}
private void updateTimerDisplay(int timeout) {
diff --git a/src/com/android/settings/bluetooth/BluetoothEnabler.java b/src/com/android/settings/bluetooth/BluetoothEnabler.java
index df13eefbd..1a450d441 100644
--- a/src/com/android/settings/bluetooth/BluetoothEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothEnabler.java
@@ -35,7 +35,7 @@ import com.android.settings.WirelessSettings;
* preference reflects the current state.
*/
public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeListener {
- private final Context mContext;
+ private Context mContext;
private Switch mSwitch;
private boolean mValidListener;
private final LocalBluetoothAdapter mLocalAdapter;
@@ -67,12 +67,16 @@ public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeLis
mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
}
- public void resume() {
+ public void resume(Context context) {
if (mLocalAdapter == null) {
mSwitch.setEnabled(false);
return;
}
+ if (mContext != context) {
+ mContext = context;
+ }
+
// Bluetooth state is not sticky, so set it manually
handleStateChanged(mLocalAdapter.getBluetoothState());
diff --git a/src/com/android/settings/bluetooth/BluetoothLocalDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothLocalDevicePreference.java
deleted file mode 100644
index 403c3b4b9..000000000
--- a/src/com/android/settings/bluetooth/BluetoothLocalDevicePreference.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 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.content.Context;
-import android.preference.Preference;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-
-import com.android.settings.R;
-
-/**
- * A preference screen to show information for local device.
- */
-public class BluetoothLocalDevicePreference extends Preference {
- private static OnClickListener mSettingsListener;
-
- public BluetoothLocalDevicePreference(Context context, OnClickListener settingsListener) {
- super(context);
- mSettingsListener = settingsListener;
- setWidgetLayoutResource(R.layout.preference_bluetooth);
- }
-
- @Override
- protected void onBindView(View view) {
- ImageView deviceDetails = (ImageView) view.findViewById(
- R.id.deviceDetails);
- deviceDetails.setOnClickListener(mSettingsListener);
- super.onBindView(view);
- }
-}
diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
index 0af9c4ed7..bf0356c31 100644
--- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java
@@ -26,7 +26,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
@@ -179,9 +178,8 @@ public final class BluetoothNameDialogFragment extends DialogFragment implements
mDeviceNameUpdated = true;
mDeviceNameEdited = false;
mDeviceNameView.setText(mLocalAdapter.getName());
+ getActivity().setTitle(mLocalAdapter.getName());
}
- PreferenceActivity activity = (PreferenceActivity)getActivity();
- activity.showBreadCrumbs(mLocalAdapter.getName(), "");
}
public void afterTextChanged(Editable s) {
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index 4cb36c884..acd9dada7 100755
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -28,7 +28,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
@@ -42,6 +41,7 @@ import android.widget.Switch;
import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
/**
* BluetoothSettings is the Settings screen for Bluetooth configuration and
@@ -51,23 +51,25 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
private static final String TAG = "BluetoothSettings";
private static final int MENU_ID_SCAN = Menu.FIRST;
- private static final int MENU_ID_SHOW_RECEIVED = Menu.FIRST + 1;
+ private static final int MENU_ID_RENAME_DEVICE = Menu.FIRST + 1;
+ private static final int MENU_ID_VISIBILITY_TIMEOUT = Menu.FIRST + 2;
+ private static final int MENU_ID_SHOW_RECEIVED = 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 BluetoothEnabler mBluetoothEnabler;
-
private BluetoothDiscoverableEnabler mDiscoverableEnabler;
private PreferenceGroup mPairedDevicesCategory;
-
private PreferenceGroup mAvailableDevicesCategory;
private boolean mAvailableDevicesCategoryIsPresent;
+
private boolean mActivityStarted;
private TextView mEmptyView;
+ private Switch mSwitch;
private final IntentFilter mIntentFilter;
@@ -103,32 +105,45 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
getListView().setEmptyView(mEmptyView);
+
+ final Activity activity = getActivity();
+ final int padding = activity.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ mSwitch = new Switch(activity);
+ mSwitch.setPaddingRelative(0, 0, padding, 0);
+
+ mBluetoothEnabler = new BluetoothEnabler(activity, mSwitch);
}
@Override
- void addPreferencesForActivity() {
- addPreferencesFromResource(R.xml.bluetooth_settings);
+ public void onStart() {
+ super.onStart();
+
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+
+ if (!activity.onIsHidingHeaders()) {
+ activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+ ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END));
+ }
+ }
- Activity activity = getActivity();
-
- Switch actionBarSwitch = new Switch(activity);
-
- if (activity instanceof PreferenceActivity) {
- PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
- if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
- final int padding = activity.getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- actionBarSwitch.setPaddingRelative(0, 0, padding, 0);
- activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
- ActionBar.DISPLAY_SHOW_CUSTOM);
- activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(
- ActionBar.LayoutParams.WRAP_CONTENT,
- ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END));
- }
+ @Override
+ public void onStop() {
+ super.onStop();
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ if (!activity.onIsHidingHeaders()) {
+ activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(null);
}
+ }
- mBluetoothEnabler = new BluetoothEnabler(activity, actionBarSwitch);
+ @Override
+ void addPreferencesForActivity() {
+ addPreferencesFromResource(R.xml.bluetooth_settings);
setHasOptionsMenu(true);
}
@@ -138,12 +153,12 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
// resume BluetoothEnabler before calling super.onResume() so we don't get
// any onDeviceAdded() callbacks before setting up view in updateContent()
if (mBluetoothEnabler != null) {
- mBluetoothEnabler.resume();
+ mBluetoothEnabler.resume(getActivity());
}
super.onResume();
if (mDiscoverableEnabler != null) {
- mDiscoverableEnabler.resume();
+ mDiscoverableEnabler.resume(getActivity());
}
getActivity().registerReceiver(mReceiver, mIntentFilter);
if (mLocalAdapter != null) {
@@ -176,6 +191,12 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
.setEnabled(bluetoothIsEnabled && !isDiscovering)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
+ .setEnabled(bluetoothIsEnabled)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ menu.add(Menu.NONE, MENU_ID_VISIBILITY_TIMEOUT, 0, R.string.bluetooth_visibility_timeout)
+ .setEnabled(bluetoothIsEnabled)
+ .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);
super.onCreateOptionsMenu(menu, inflater);
@@ -190,6 +211,16 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
}
return true;
+ case MENU_ID_RENAME_DEVICE:
+ new BluetoothNameDialogFragment().show(
+ getFragmentManager(), "rename device");
+ return true;
+
+ case MENU_ID_VISIBILITY_TIMEOUT:
+ new BluetoothVisibilityTimeoutFragment().show(
+ getFragmentManager(), "visibility timeout");
+ return true;
+
case MENU_ID_SHOW_RECEIVED:
Intent intent = new Intent(BTOPP_ACTION_OPEN_RECEIVED_FILES);
getActivity().sendBroadcast(intent);
@@ -234,8 +265,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
// This device
if (mMyDevicePreference == null) {
- mMyDevicePreference = new BluetoothLocalDevicePreference(
- getActivity(), mLocalDeviceProfilesListener);
+ mMyDevicePreference = new Preference(getActivity());
}
mMyDevicePreference.setTitle(mLocalAdapter.getName());
if (getResources().getBoolean(com.android.internal.R.bool.config_voice_capable)) {
@@ -249,9 +279,9 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
if (!isRestrictedAndNotPinProtected()) {
if (mDiscoverableEnabler == null) {
- mDiscoverableEnabler = new BluetoothDiscoverableEnabler(getActivity(),
- mLocalAdapter, mMyDevicePreference);
- mDiscoverableEnabler.resume();
+ mDiscoverableEnabler = new BluetoothDiscoverableEnabler(mLocalAdapter,
+ mMyDevicePreference);
+ mDiscoverableEnabler.resume(getActivity());
LocalBluetoothManager.getInstance(getActivity()).setDiscoverableEnabler(
mDiscoverableEnabler);
}
@@ -343,18 +373,6 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
updateContent(mLocalAdapter.getBluetoothState(), false);
}
- // Listener for local device profile fragment.
- private final View.OnClickListener mLocalDeviceProfilesListener = new View.OnClickListener() {
- public void onClick(View v) {
- if (isRestrictedAndNotPinProtected()) return;
-
- ((PreferenceActivity) getActivity()).startPreferencePanel(
- LocalDeviceProfilesSettings.class.getName(), null,
- 0, mLocalAdapter.getName(), null, 0);
- }
- };
-
-
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
@@ -366,7 +384,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment {
Bundle args = new Bundle(1);
args.putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, device.getDevice());
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
DeviceProfilesSettings.class.getName(), args,
R.string.bluetooth_device_advanced_title, null, null, 0);
} else {
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
index e2faf7fd5..9ced992ca 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
@@ -25,9 +25,7 @@ import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
-import com.android.settings.ProgressCategory;
import com.android.settings.RestrictedSettingsFragment;
-import com.android.settings.SettingsPreferenceFragment;
import java.util.Collection;
import java.util.WeakHashMap;
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothAdapter.java b/src/com/android/settings/bluetooth/LocalBluetoothAdapter.java
index 041ecb7bb..013171c14 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothAdapter.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothAdapter.java
@@ -118,9 +118,6 @@ public final class LocalBluetoothAdapter {
return mAdapter.isDiscovering();
}
- boolean isAdvertising() {
- return mAdapter.isAdvertising();
- }
boolean isEnabled() {
return mAdapter.isEnabled();
}
@@ -129,14 +126,6 @@ public final class LocalBluetoothAdapter {
mAdapter.setDiscoverableTimeout(timeout);
}
- boolean startAdvertising() {
- return mAdapter.startAdvertising();
- }
-
- boolean stopAdvertising() {
- return mAdapter.stopAdvertisting();
- }
-
void setName(String name) {
mAdapter.setName(name);
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
index 265cabb76..ae8dec2ae 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -37,7 +37,6 @@ public final class LocalBluetoothManager {
private Context mForegroundActivity;
private BluetoothDiscoverableEnabler mDiscoverableEnabler;
- private BluetoothAdvertisingEnabler mAdvertisingEnabler;
private final LocalBluetoothAdapter mLocalAdapter;
@@ -71,14 +70,6 @@ public final class LocalBluetoothManager {
return mDiscoverableEnabler;
}
- public void setBluetoothAdvertisingEnabler(BluetoothAdvertisingEnabler advertisingEnabler) {
- this.mAdvertisingEnabler = advertisingEnabler;
- }
-
- public BluetoothAdvertisingEnabler getAdvertisingEnabler() {
- return mAdvertisingEnabler;
- }
-
private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context) {
mContext = context;
mLocalAdapter = adapter;
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
index f862f726d..f00b80178 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
@@ -17,10 +17,8 @@
package com.android.settings.bluetooth;
import android.app.QueuedWork;
-import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.util.Log;
@@ -48,10 +46,6 @@ final class LocalBluetoothPreferences {
private static final String KEY_DISCOVERABLE_END_TIMESTAMP = "discoverable_end_timestamp";
- private static final String KEY_ADVERTISEMENT_PREFERENCE = "bt_advertisement_perference";
-
- private static final boolean DEFAULT_ADVERTISING_ENABLED = false;
-
private LocalBluetoothPreferences() {
}
@@ -64,17 +58,6 @@ final class LocalBluetoothPreferences {
KEY_DISCOVERABLE_END_TIMESTAMP, 0);
}
- static boolean isAdvertisingEnabled(Context context) {
- return getSharedPreferences(context).getBoolean(
- KEY_ADVERTISEMENT_PREFERENCE, DEFAULT_ADVERTISING_ENABLED);
- }
-
- static void setAdvertisingEnabled(Context context, boolean advertisingEnabled) {
- Editor preferenceEditor = getSharedPreferences(context).edit();
- preferenceEditor.putBoolean(KEY_ADVERTISEMENT_PREFERENCE, advertisingEnabled);
- preferenceEditor.apply();
- }
-
static boolean shouldShowDialogInForeground(Context context,
String deviceAddress) {
LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context);
diff --git a/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java b/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java
deleted file mode 100644
index f01bbf5ec..000000000
--- a/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 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.os.Bundle;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-
-/**
- * This preference fragment presents the user with the profiles of the local devices and allow them
- * to be modified.
- */
-public final class LocalDeviceProfilesSettings extends SettingsPreferenceFragment {
- private static final String TAG = "LocalDeviceProfilesSettings";
-
- private static final String KEY_RENAME_DEVICE = "rename_device";
- private static final String KEY_BROADCASTING = "broadcasting";
- private static final String KEY_VISIBILITY_TIMEOUT = "visibility_timeout";
-
- private LocalBluetoothManager mManager;
- private BluetoothDiscoverableEnabler mDiscoverableEnabler;
- private BluetoothAdvertisingEnabler mAdvertisingEnabler;
-
- private Preference mDeviceNamePref;
- private Preference mVisibilityPref;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.bluetooth_local_device_profile);
- getPreferenceScreen().setOrderingAsAdded(true);
- mDeviceNamePref = findPreference(KEY_RENAME_DEVICE);
- mDeviceNamePref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- new BluetoothNameDialogFragment().show(getFragmentManager(), "rename device");
- return true;
- }
- });
-
- mVisibilityPref = findPreference(KEY_VISIBILITY_TIMEOUT);
- mVisibilityPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- new BluetoothVisibilityTimeoutFragment().show(
- getFragmentManager(), "visibility timeout");
- return true;
- }
- });
-
- mManager = LocalBluetoothManager.getInstance(getActivity());
- mDiscoverableEnabler = mManager.getDiscoverableEnabler();
- // Set the visibility timeout preference to the enabler so the visibility timeout
- // preference can be updated when the timeout changes.
- mDiscoverableEnabler.setVisibilityPreference(mVisibilityPref);
-
- PreferenceActivity mActivity = (PreferenceActivity)getActivity();
- mActivity.showBreadCrumbs(mManager.getBluetoothAdapter().getName(), "");
- PreferenceScreen bluetoothBroadcast = (PreferenceScreen)findPreference(KEY_BROADCASTING);
- mAdvertisingEnabler = new BluetoothAdvertisingEnabler(getActivity(), bluetoothBroadcast);
- mManager.setBluetoothAdvertisingEnabler(mAdvertisingEnabler);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mManager.setForegroundActivity(getActivity());
- mAdvertisingEnabler.resume();
- mDiscoverableEnabler.resume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mManager.setForegroundActivity(null);
- if (mDiscoverableEnabler != null) {
- mDiscoverableEnabler.pause();
- }
- }
-
-}
diff --git a/src/com/android/settings/bluetooth/RequestPermissionActivity.java b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
index 1b105deeb..9f266a55c 100644
--- a/src/com/android/settings/bluetooth/RequestPermissionActivity.java
+++ b/src/com/android/settings/bluetooth/RequestPermissionActivity.java
@@ -16,6 +16,8 @@
package com.android.settings.bluetooth;
+import com.android.settings.R;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
@@ -26,22 +28,17 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
-import android.os.UserHandle;
import android.util.Log;
-import com.android.settings.R;
-
/**
- * RequestPermissionActivity asks the user whether to enable bluetooth, discovery or advertisement.
- * This is usually started by an application wanted to start bluetooth, discovery or advertisement.
+ * RequestPermissionActivity asks the user whether to enable discovery. This is
+ * usually started by an application wanted to start bluetooth and or discovery
*/
public class RequestPermissionActivity extends Activity implements
DialogInterface.OnClickListener {
// Command line to test this
// adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
// adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE
- // adb shell am start -a android.bluetooth.adapter.action.START_ADVERTISING
- // adb shell am start -a android.bluetooth.adapter.action.STOP_ADVERTISING
private static final String TAG = "RequestPermissionActivity";
@@ -53,11 +50,6 @@ public class RequestPermissionActivity extends Activity implements
private static final int REQUEST_CODE_START_BT = 1;
- private static final int EXTRA_INTENT_NONE = 0;
- private static final int EXTRA_INTENT_DISCOVERY = 1;
- private static final int EXTRA_INTENT_START_ADVERTISING = 2;
- private static final int EXTRA_INTENT_STOP_ADVERTISING = 3;
-
private LocalBluetoothAdapter mLocalAdapter;
private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
@@ -75,14 +67,10 @@ public class RequestPermissionActivity extends Activity implements
// False if requesting BT to be turned on + discoverable mode
private boolean mEnableOnly;
- private int mExtraIntent = EXTRA_INTENT_NONE;
-
private boolean mUserConfirmed;
private AlertDialog mDialog;
- private Context mContext;
-
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -106,8 +94,6 @@ public class RequestPermissionActivity extends Activity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mContext = getApplicationContext();
-
// Note: initializes mLocalAdapter and returns true on error
if (parseIntent()) {
finish();
@@ -139,27 +125,21 @@ public class RequestPermissionActivity extends Activity implements
intent.setClass(this, RequestPermissionHelperActivity.class);
if (mEnableOnly) {
intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
- } else if (mExtraIntent == EXTRA_INTENT_DISCOVERY) {
+ } else {
intent.setAction(RequestPermissionHelperActivity.
ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
- } else if (mExtraIntent == EXTRA_INTENT_START_ADVERTISING) {
- intent.setAction(RequestPermissionHelperActivity.
- ACTION_INTERNAL_REQUEST_BT_ON_AND_START_ADVERTISE);
- } else if (mExtraIntent == EXTRA_INTENT_STOP_ADVERTISING) {
- // Nothing to do. Advertising cannot be in process with bluetooth disabled.
}
-
startActivityForResult(intent, REQUEST_CODE_START_BT);
mNeededToEnableBluetooth = true;
break;
case BluetoothAdapter.STATE_ON:
- if (needAskUserPermission()) {
- // Ask the user for permissions of bluetooth operations.
- createDialog();
- } else {
- // No need to ask for permission, just proceed.
+ if (mEnableOnly) {
+ // Nothing to do. Already enabled.
proceedAndFinish();
+ } else {
+ // Ask the user about enabling discovery mode
+ createDialog();
}
break;
default:
@@ -167,19 +147,6 @@ public class RequestPermissionActivity extends Activity implements
}
}
- private boolean needAskUserPermission() {
- if (mEnableOnly) {
- return false;
- }
- if (mExtraIntent == EXTRA_INTENT_STOP_ADVERTISING) {
- return false;
- }
- if (mExtraIntent == EXTRA_INTENT_START_ADVERTISING) {
- return !LocalBluetoothPreferences.isAdvertisingEnabled(mContext);
- }
- return true;
- }
-
private void createDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -188,7 +155,7 @@ public class RequestPermissionActivity extends Activity implements
// to turn on BT
builder.setMessage(getString(R.string.bluetooth_turning_on));
builder.setCancelable(false);
- } else if (mExtraIntent == EXTRA_INTENT_DISCOVERY) {
+ } else {
// Ask the user whether to turn on discovery mode or not
// For lasting discoverable mode there is a different message
if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
@@ -200,11 +167,6 @@ public class RequestPermissionActivity extends Activity implements
}
builder.setPositiveButton(getString(R.string.allow), this);
builder.setNegativeButton(getString(R.string.deny), this);
- } else if (mExtraIntent == EXTRA_INTENT_START_ADVERTISING) {
- builder.setMessage(getString(R.string.bluetooth_ask_start_broadcast,
- Utils.getCallingApp(this)));
- builder.setPositiveButton(getString(R.string.allow), this);
- builder.setNegativeButton(getString(R.string.deny), this);
}
mDialog = builder.create();
@@ -261,8 +223,7 @@ public class RequestPermissionActivity extends Activity implements
if (mEnableOnly) {
// BT enabled. Done
returnCode = RESULT_OK;
- } else if (mExtraIntent == EXTRA_INTENT_DISCOVERY
- && mLocalAdapter.setScanMode(
+ } else if (mLocalAdapter.setScanMode(
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) {
// If already in discoverable mode, this will extend the timeout.
long endTime = System.currentTimeMillis() + (long) mTimeout * 1000;
@@ -276,22 +237,6 @@ public class RequestPermissionActivity extends Activity implements
if (returnCode < RESULT_FIRST_USER) {
returnCode = RESULT_FIRST_USER;
}
- } else if (mExtraIntent == EXTRA_INTENT_START_ADVERTISING) {
- // Advertise allowed as user said yes.
- LocalBluetoothPreferences.setAdvertisingEnabled(mContext, true);
- if (mLocalAdapter.startAdvertising()) {
- returnCode = RESULT_OK;
- Intent intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STARTED);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } else {
- returnCode = RESULT_CANCELED;
- }
- } else if (mExtraIntent == EXTRA_INTENT_STOP_ADVERTISING
- && mLocalAdapter.isAdvertising()
- && mLocalAdapter.stopAdvertising()) {
- Intent intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADVERTISING_STOPPED);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- returnCode = RESULT_OK;
} else {
returnCode = RESULT_CANCELED;
}
@@ -314,7 +259,6 @@ public class RequestPermissionActivity extends Activity implements
mEnableOnly = true;
} else if (intent != null
&& intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) {
- mExtraIntent = EXTRA_INTENT_DISCOVERY;
mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);
@@ -323,12 +267,6 @@ public class RequestPermissionActivity extends Activity implements
if (mTimeout < 0 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) {
mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
}
- } else if (intent != null
- && intent.getAction().equals(BluetoothAdapter.ACTION_START_ADVERTISING)) {
- mExtraIntent = EXTRA_INTENT_START_ADVERTISING;
- } else if (intent != null
- && intent.getAction().equals(BluetoothAdapter.ACTION_STOP_ADVERTISING)) {
- mExtraIntent = EXTRA_INTENT_STOP_ADVERTISING;
} else {
Log.e(TAG, "Error: this activity may be started only with intent "
+ BluetoothAdapter.ACTION_REQUEST_ENABLE + " or "
diff --git a/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java b/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java
index 34874b30c..f10851359 100644
--- a/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java
+++ b/src/com/android/settings/bluetooth/RequestPermissionHelperActivity.java
@@ -30,7 +30,7 @@ import android.view.View;
import android.widget.TextView;
/**
- * RequestPermissionHelperActivity asks the user whether to enable discovery or advertisement.
+ * RequestPermissionHelperActivity asks the user whether to enable discovery.
* This is usually started by RequestPermissionActivity.
*/
public class RequestPermissionHelperActivity extends AlertActivity implements
@@ -43,9 +43,6 @@ public class RequestPermissionHelperActivity extends AlertActivity implements
public static final String ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE =
"com.android.settings.bluetooth.ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE";
- public static final String ACTION_INTERNAL_REQUEST_BT_ON_AND_START_ADVERTISE =
- "com.android.settings.bluetooth.ACTION_INTERNAL_REQUEST_BT_ON_AND_ADVERTISE";
-
private LocalBluetoothAdapter mLocalAdapter;
private int mTimeout;
@@ -53,7 +50,6 @@ public class RequestPermissionHelperActivity extends AlertActivity implements
// True if requesting BT to be turned on
// False if requesting BT to be turned on + discoverable mode
private boolean mEnableOnly;
- private boolean mDiscovery;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -79,15 +75,12 @@ public class RequestPermissionHelperActivity extends AlertActivity implements
if (mEnableOnly) {
p.mMessage = getString(R.string.bluetooth_ask_enablement);
- } else if (mDiscovery) {
+ } else {
if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
p.mMessage = getString(R.string.bluetooth_ask_enablement_and_lasting_discovery);
} else {
p.mMessage = getString(R.string.bluetooth_ask_enablement_and_discovery, mTimeout);
}
- } else {
- p.mMessage = getString(R.string.bluetooth_ask_enablement_and_start_broadcast,
- Utils.getCallingApp(this));
}
p.mPositiveButtonText = getString(R.string.allow);
@@ -145,14 +138,9 @@ public class RequestPermissionHelperActivity extends AlertActivity implements
} else if (intent != null
&& intent.getAction().equals(ACTION_INTERNAL_REQUEST_BT_ON_AND_DISCOVERABLE)) {
mEnableOnly = false;
- mDiscovery = true;
// Value used for display purposes. Not range checking.
mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);
- } else if (intent != null
- && intent.getAction().equals(ACTION_INTERNAL_REQUEST_BT_ON_AND_START_ADVERTISE)) {
- mEnableOnly = false;
- mDiscovery = false;
} else {
setResult(RESULT_CANCELED);
return true;
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index 6590b066a..fb44d5a38 100755
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -16,15 +16,11 @@
package com.android.settings.bluetooth;
-import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.widget.Toast;
import com.android.settings.R;
@@ -106,18 +102,4 @@ final class Utils {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}
-
- /**
- * Get application name of the calling activity. Returns empty string on errors.
- */
- static String getCallingApp(Activity activity) {
- final PackageManager pm = activity.getApplicationContext().getPackageManager();
- ApplicationInfo applicationInfo;
- try {
- applicationInfo = pm.getApplicationInfo(activity.getCallingPackage(), 0);
- } catch (final NameNotFoundException e) {
- applicationInfo = null;
- }
- return (applicationInfo == null) ? "" : pm.getApplicationLabel(applicationInfo).toString();
- }
}
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
new file mode 100644
index 000000000..0e034ffe3
--- /dev/null
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -0,0 +1,291 @@
+/*
+ * 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.dashboard;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.indexer.Index;
+
+public class DashboardSummary extends Fragment {
+
+ private EditText mEditText;
+ private ListView mListView;
+
+ private SearchResultsAdapter mAdapter;
+ private Index mIndex;
+ private UpdateSearchResultsTask mUpdateSearchResultsTask;
+
+ /**
+ * A basic AsyncTask for updating the query results cursor
+ */
+ private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
+ @Override
+ protected Cursor doInBackground(String... params) {
+ return mIndex.search(params[0]);
+ }
+
+ @Override
+ protected void onPostExecute(Cursor cursor) {
+ if (!isCancelled()) {
+ setCursor(cursor);
+ } else if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mIndex = Index.getInstance(getActivity());
+ mAdapter = new SearchResultsAdapter(getActivity());
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ clearResults();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ updateSearchResults();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ final View view = inflater.inflate(R.layout.dashboard, container, false);
+
+ mEditText = (EditText)view.findViewById(R.id.edittext_query);
+ mEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ updateSearchResults();
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
+ mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (!hasFocus) {
+ closeSoftKeyboard();
+ }
+ }
+ });
+
+ mListView = (ListView) view.findViewById(R.id.list_results);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ closeSoftKeyboard();
+ final Cursor cursor = mAdapter.mCursor;
+ cursor.moveToPosition(position);
+ final String fragmentName = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_NAME);
+ final String fragmentTitle = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_TITLE);
+
+ ((SettingsActivity) getActivity()).startPreferencePanel(fragmentName, null, 0,
+ fragmentTitle, null, 0);
+ }
+ });
+
+ return view;
+ }
+
+ private void closeSoftKeyboard() {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && imm.isActive(mEditText)) {
+ imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
+ }
+ }
+
+ private void clearResults() {
+ if (mUpdateSearchResultsTask != null) {
+ mUpdateSearchResultsTask.cancel(false);
+ mUpdateSearchResultsTask = null;
+ }
+ setCursor(null);
+ }
+
+ private void setCursor(Cursor cursor) {
+ Cursor oldCursor = mAdapter.swapCursor(cursor);
+ if (oldCursor != null) {
+ oldCursor.close();
+ }
+ }
+
+ private String getFilteredQueryString() {
+ final CharSequence query = mEditText.getText().toString();
+ final StringBuilder filtered = new StringBuilder();
+ for (int n = 0; n < query.length(); n++) {
+ char c = query.charAt(n);
+ if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
+ continue;
+ }
+ filtered.append(c);
+ }
+ return filtered.toString();
+ }
+
+ private void updateSearchResults() {
+ if (mUpdateSearchResultsTask != null) {
+ mUpdateSearchResultsTask.cancel(false);
+ mUpdateSearchResultsTask = null;
+ }
+ final String query = getFilteredQueryString();
+ if (TextUtils.isEmpty(query)) {
+ setCursor(null);
+ } else {
+ mUpdateSearchResultsTask = new UpdateSearchResultsTask();
+ mUpdateSearchResultsTask.execute(query);
+ }
+ }
+
+ private static class SearchResult {
+ public String title;
+ public String summary;
+ public int iconResId;
+
+ public SearchResult(String title, String summary, int iconResId) {
+ this.title = title;
+ this.summary = summary;
+ this.iconResId = iconResId;
+ }
+ }
+
+ private static class SearchResultsAdapter extends BaseAdapter {
+
+ private Cursor mCursor;
+ private LayoutInflater mInflater;
+ private boolean mDataValid;
+
+ public SearchResultsAdapter(Context context) {
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mDataValid = false;
+ }
+
+ public Cursor swapCursor(Cursor newCursor) {
+ if (newCursor == mCursor) {
+ return null;
+ }
+ Cursor oldCursor = mCursor;
+ mCursor = newCursor;
+ if (newCursor != null) {
+ mDataValid = true;
+ notifyDataSetChanged();
+ } else {
+ mDataValid = false;
+ notifyDataSetInvalidated();
+ }
+ return oldCursor;
+ }
+
+ @Override
+ public int getCount() {
+ if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
+ return mCursor.getCount();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (mDataValid && mCursor.moveToPosition(position)) {
+ final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
+ final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
+ final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
+ final int iconResId =
+ TextUtils.isEmpty(iconResStr) ? 0 : Integer.parseInt(iconResStr);
+ return new SearchResult(title, summary, iconResId);
+ }
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (!mDataValid && convertView == null) {
+ throw new IllegalStateException(
+ "this should only be called when the cursor is valid");
+ }
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ View view;
+ TextView textTitle;
+ TextView textSummary;
+ ImageView imageView;
+
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.search_result, parent, false);
+ } else {
+ view = convertView;
+ }
+ textTitle = (TextView) view.findViewById(R.id.title);
+ textSummary = (TextView) view.findViewById(R.id.summary);
+ imageView = (ImageView) view.findViewById(R.id.icon);
+
+ SearchResult result = (SearchResult) getItem(position);
+
+ textTitle.setText(result.title);
+ textSummary.setText(result.summary);
+ if (result.iconResId != R.drawable.empty_icon) {
+ imageView.setImageResource(result.iconResId);
+ imageView.setBackgroundResource(R.color.background_search_result_icon);
+ } else {
+ imageView.setImageDrawable(null);
+ imageView.setBackgroundResource(R.drawable.empty_icon);
+ }
+
+ return view;
+ }
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index 999611d12..4923070b7 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -40,7 +40,6 @@ import android.os.storage.StorageEventListener;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.Menu;
@@ -49,6 +48,7 @@ import android.view.MenuItem;
import android.widget.Toast;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.google.android.collect.Lists;
@@ -186,8 +186,8 @@ public class Memory extends SettingsPreferenceFragment {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.storage_usb:
- if (getActivity() instanceof PreferenceActivity) {
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ if (getActivity() instanceof SettingsActivity) {
+ ((SettingsActivity) getActivity()).startPreferencePanel(
UsbSettings.class.getCanonicalName(),
null,
R.string.storage_title_usb, null,
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index b27b241af..ef1f5c5dc 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -18,6 +18,7 @@ package com.android.settings.deviceinfo;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,13 +36,16 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.preference.PreferenceScreen;
import android.telephony.CellBroadcastMessage;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListAdapter;
+import android.widget.Toast;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
@@ -364,6 +368,27 @@ public class Status extends PreferenceActivity {
} else {
removePreferenceFromScreen(KEY_SERIAL_NUMBER);
}
+
+ // Make every pref on this screen copy its data to the clipboard on longpress.
+ // Super convenient for capturing the IMEI, MAC addr, serial, etc.
+ getListView().setOnItemLongClickListener(
+ new AdapterView.OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view,
+ int position, long id) {
+ ListAdapter listAdapter = (ListAdapter) parent.getAdapter();
+ Preference pref = (Preference) listAdapter.getItem(position);
+
+ ClipboardManager cm = (ClipboardManager)
+ getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setText(pref.getSummary());
+ Toast.makeText(
+ Status.this,
+ com.android.internal.R.string.text_copied,
+ Toast.LENGTH_SHORT).show();
+ return true;
+ }
+ });
}
@Override
diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java b/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
index d1ea09489..a98f8d96d 100644
--- a/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
+++ b/src/com/android/settings/deviceinfo/StorageVolumePreferenceCategory.java
@@ -38,6 +38,7 @@ import android.provider.MediaStore;
import android.text.format.Formatter;
import com.android.settings.R;
+import com.android.settings.Settings;
import com.android.settings.deviceinfo.StorageMeasurement.MeasurementDetails;
import com.android.settings.deviceinfo.StorageMeasurement.MeasurementReceiver;
import com.google.android.collect.Lists;
@@ -428,8 +429,7 @@ public class StorageVolumePreferenceCategory extends PreferenceCategory {
intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, mVolume);
} else if (pref == mItemApps) {
intent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE);
- intent.setClass(getContext(),
- com.android.settings.Settings.ManageApplicationsActivity.class);
+ intent.setClass(getContext(), Settings.ManageApplicationsActivity.class);
} else if (pref == mItemDownloads) {
intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS).putExtra(
DownloadManager.INTENT_EXTRAS_SORT_BY_SIZE, true);
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
new file mode 100644
index 000000000..c2bf127ea
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -0,0 +1,304 @@
+/*
+ * 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.fuelgauge;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+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.UserManager;
+import com.android.internal.os.BatterySipper;
+import com.android.settings.R;
+import com.android.settings.users.UserUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Wraps the power usage data of a BatterySipper with information about package name
+ * and icon image.
+ */
+public class BatteryEntry {
+ public static final int MSG_UPDATE_NAME_ICON = 1;
+ public static final int MSG_REPORT_FULLY_DRAWN = 2;
+
+ static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
+
+ static final ArrayList<BatteryEntry> mRequestQueue = new ArrayList<BatteryEntry>();
+ static Handler sHandler;
+
+ static private class NameAndIconLoader extends Thread {
+ private boolean mAbort = false;
+
+ public NameAndIconLoader() {
+ super("BatteryUsage Icon Loader");
+ }
+
+ public void abort() {
+ mAbort = true;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ BatteryEntry be;
+ synchronized (mRequestQueue) {
+ if (mRequestQueue.isEmpty() || mAbort) {
+ if (sHandler != null) {
+ sHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
+ }
+ mRequestQueue.clear();
+ return;
+ }
+ be = mRequestQueue.remove(0);
+ }
+ be.loadNameAndIcon();
+ }
+ }
+ }
+
+ private static NameAndIconLoader mRequestThread;
+
+ public static void startRequestQueue() {
+ if (sHandler != null) {
+ synchronized (mRequestQueue) {
+ if (!mRequestQueue.isEmpty()) {
+ if (mRequestThread != null) {
+ mRequestThread.abort();
+ }
+ mRequestThread = new NameAndIconLoader();
+ mRequestThread.setPriority(Thread.MIN_PRIORITY);
+ mRequestThread.start();
+ mRequestQueue.notify();
+ }
+ }
+ }
+ }
+
+ public static void stopRequestQueue() {
+ synchronized (mRequestQueue) {
+ if (mRequestThread != null) {
+ mRequestThread.abort();
+ mRequestThread = null;
+ sHandler = null;
+ }
+ }
+ }
+
+ public static void clearUidCache() {
+ sUidCache.clear();
+ }
+
+ public final Context context;
+ public final BatterySipper sipper;
+
+ public String name;
+ public Drawable icon;
+ public int iconId; // For passing to the detail screen.
+ public String defaultPackageName;
+
+ static class UidToDetail {
+ String name;
+ String packageName;
+ Drawable icon;
+ }
+
+ public BatteryEntry(Context context, Handler handler, UserManager um, BatterySipper sipper) {
+ sHandler = handler;
+ this.context = context;
+ this.sipper = sipper;
+ switch (sipper.drainType) {
+ case IDLE:
+ name = context.getResources().getString(R.string.power_idle);
+ iconId = R.drawable.ic_settings_phone_idle;
+ break;
+ case CELL:
+ name = context.getResources().getString(R.string.power_cell);
+ iconId = R.drawable.ic_settings_cell_standby;
+ break;
+ case PHONE:
+ name = context.getResources().getString(R.string.power_phone);
+ iconId = R.drawable.ic_settings_voice_calls;
+ break;
+ case WIFI:
+ name = context.getResources().getString(R.string.power_wifi);
+ iconId = R.drawable.ic_settings_wifi;
+ break;
+ case BLUETOOTH:
+ name = context.getResources().getString(R.string.power_bluetooth);
+ iconId = R.drawable.ic_settings_bluetooth;
+ break;
+ case SCREEN:
+ name = context.getResources().getString(R.string.power_screen);
+ iconId = R.drawable.ic_settings_display;
+ break;
+ case APP:
+ name = sipper.packageWithHighestDrain;
+ break;
+ case USER: {
+ UserInfo info = um.getUserInfo(sipper.userId);
+ if (info != null) {
+ icon = UserUtils.getUserIcon(context, um, info, context.getResources());
+ name = info != null ? info.name : null;
+ if (name == null) {
+ name = Integer.toString(info.id);
+ }
+ name = context.getResources().getString(
+ R.string.running_process_item_user_label, name);
+ } else {
+ icon = null;
+ name = context.getResources().getString(
+ R.string.running_process_item_removed_user_label);
+ }
+ } break;
+ case UNACCOUNTED:
+ name = context.getResources().getString(R.string.power_unaccounted);
+ iconId = R.drawable.ic_power_system;
+ break;
+ case OVERCOUNTED:
+ name = context.getResources().getString(R.string.power_overcounted);
+ iconId = R.drawable.ic_power_system;
+ break;
+ }
+ if (iconId > 0) {
+ icon = context.getResources().getDrawable(iconId);
+ }
+ if ((name == null || iconId == 0) && this.sipper.uidObj != null) {
+ getQuickNameIconForUid(this.sipper.uidObj);
+ }
+ }
+
+ public Drawable getIcon() {
+ return icon;
+ }
+
+ /**
+ * Gets the application name
+ */
+ public String getLabel() {
+ return name;
+ }
+
+ void getQuickNameIconForUid(BatteryStats.Uid uidObj) {
+ final int uid = uidObj.getUid();
+ final String uidString = Integer.toString(uid);
+ if (sUidCache.containsKey(uidString)) {
+ UidToDetail utd = sUidCache.get(uidString);
+ defaultPackageName = utd.packageName;
+ name = utd.name;
+ icon = utd.icon;
+ return;
+ }
+ PackageManager pm = context.getPackageManager();
+ String[] packages = pm.getPackagesForUid(uid);
+ icon = pm.getDefaultActivityIcon();
+ if (packages == null) {
+ //name = Integer.toString(uid);
+ if (uid == 0) {
+ name = context.getResources().getString(R.string.process_kernel_label);
+ } else if ("mediaserver".equals(name)) {
+ name = context.getResources().getString(R.string.process_mediaserver_label);
+ }
+ iconId = R.drawable.ic_power_system;
+ icon = context.getResources().getDrawable(iconId);
+ return;
+ } else {
+ //name = packages[0];
+ }
+ if (sHandler != null) {
+ synchronized (mRequestQueue) {
+ mRequestQueue.add(this);
+ }
+ }
+ }
+
+ /**
+ * Loads the app label and icon image and stores into the cache.
+ */
+ public void loadNameAndIcon() {
+ // Bail out if the current sipper is not an App sipper.
+ if (sipper.uidObj == null) {
+ return;
+ }
+ PackageManager pm = context.getPackageManager();
+ final int uid = sipper.uidObj.getUid();
+ final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
+ sipper.mPackages = pm.getPackagesForUid(uid);
+ if (sipper.mPackages == null) {
+ name = Integer.toString(uid);
+ return;
+ }
+
+ String[] packageLabels = new String[sipper.mPackages.length];
+ System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
+
+ // Convert package names to user-facing labels where possible
+ for (int i = 0; i < packageLabels.length; i++) {
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
+ CharSequence label = ai.loadLabel(pm);
+ if (label != null) {
+ packageLabels[i] = label.toString();
+ }
+ if (ai.icon != 0) {
+ defaultPackageName = sipper.mPackages[i];
+ icon = ai.loadIcon(pm);
+ break;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ if (icon == null) icon = defaultActivityIcon;
+
+ if (packageLabels.length == 1) {
+ name = packageLabels[0];
+ } else {
+ // Look for an official name for this UID.
+ for (String pkgName : sipper.mPackages) {
+ try {
+ final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
+ if (pi.sharedUserLabel != 0) {
+ final CharSequence nm = pm.getText(pkgName,
+ pi.sharedUserLabel, pi.applicationInfo);
+ if (nm != null) {
+ name = nm.toString();
+ if (pi.applicationInfo.icon != 0) {
+ defaultPackageName = pkgName;
+ icon = pi.applicationInfo.loadIcon(pm);
+ }
+ break;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ }
+ final String uidString = Integer.toString(sipper.uidObj.getUid());
+ UidToDetail utd = new UidToDetail();
+ utd.name = name;
+ utd.icon = icon;
+ utd.packageName = defaultPackageName;
+ sUidCache.put(uidString, utd);
+ if (sHandler != null) {
+ sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
+ }
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index 55a045747..25435ef61 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -193,8 +193,8 @@ public class BatteryHistoryChart extends View {
mWifiRunningPaint.setStyle(Paint.Style.STROKE);
mWakeLockPaint.setStyle(Paint.Style.STROKE);
mPhoneSignalChart.setColors(new int[] {
- 0x00000000, 0xffa00000, 0xffa0a000, 0xff808020,
- 0xff808040, 0xff808060, 0xff008000
+ 0x00000000, 0xffa00000, 0xffa07000, 0xffa0a000,
+ 0xff80a000, 0xff409000, 0xff008000
});
mTextPaint.density = getResources().getDisplayMetrics().density;
@@ -361,7 +361,7 @@ public class BatteryHistoryChart extends View {
final HistoryItem rec = new HistoryItem();
while (stats.getNextHistoryLocked(rec)) {
pos++;
- if (rec.cmd == HistoryItem.CMD_UPDATE) {
+ if (rec.isDeltaData()) {
if (first) {
first = false;
mHistStart = rec.time;
@@ -523,7 +523,7 @@ public class BatteryHistoryChart extends View {
if (mStats.startIteratingHistoryLocked()) {
final HistoryItem rec = new HistoryItem();
while (mStats.getNextHistoryLocked(rec) && i < N) {
- if (rec.cmd == BatteryStats.HistoryItem.CMD_UPDATE) {
+ if (rec.isDeltaData()) {
x = (int)(((rec.time-timeStart)*w)/timeChange);
y = mLevelTop + levelh - ((rec.batteryLevel-batLow)*(levelh-1))/batChange;
diff --git a/src/com/android/settings/fuelgauge/BatterySipper.java b/src/com/android/settings/fuelgauge/BatterySipper.java
deleted file mode 100644
index fcc8f6970..000000000
--- a/src/com/android/settings/fuelgauge/BatterySipper.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2009 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.fuelgauge;
-
-import com.android.settings.R;
-import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.BatteryStats.Uid;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * Contains information about package name, icon image, power usage about an
- * application or a system service.
- */
-public class BatterySipper implements Comparable<BatterySipper> {
- final Context mContext;
- /* Cache cleared when PowerUsageSummary is destroyed */
- static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
- final ArrayList<BatterySipper> mRequestQueue;
- final Handler mHandler;
- String name;
- Drawable icon;
- int iconId; // For passing to the detail screen.
- Uid uidObj;
- double value;
- double[] values;
- DrainType drainType;
- long usageTime;
- long cpuTime;
- long gpsTime;
- long wifiRunningTime;
- long cpuFgTime;
- long wakeLockTime;
- long mobileRxBytes;
- long mobileTxBytes;
- long wifiRxBytes;
- long wifiTxBytes;
- double percent;
- double noCoveragePercent;
- String defaultPackageName;
- String[] mPackages;
-
- static class UidToDetail {
- String name;
- String packageName;
- Drawable icon;
- }
-
- BatterySipper(Context context, ArrayList<BatterySipper> requestQueue,
- Handler handler, String label, DrainType drainType,
- int iconId, Uid uid, double[] values) {
- mContext = context;
- mRequestQueue = requestQueue;
- mHandler = handler;
- this.values = values;
- name = label;
- this.drainType = drainType;
- if (iconId > 0) {
- icon = mContext.getResources().getDrawable(iconId);
- }
- if (values != null) value = values[0];
- if ((label == null || iconId == 0) && uid != null) {
- getQuickNameIconForUid(uid);
- }
- uidObj = uid;
- }
-
- double getSortValue() {
- return value;
- }
-
- double[] getValues() {
- return values;
- }
-
- public Drawable getIcon() {
- return icon;
- }
-
- /**
- * Gets the application name
- */
- public String getLabel() {
- return name;
- }
-
- @Override
- public int compareTo(BatterySipper other) {
- // Return the flipped value because we want the items in descending order
- return Double.compare(other.getSortValue(), getSortValue());
- }
-
- /**
- * Gets a list of packages associated with the current user
- */
- public String[] getPackages() {
- return mPackages;
- }
-
- public int getUid() {
- // Bail out if the current sipper is not an App sipper.
- if (uidObj == null) {
- return 0;
- }
- return uidObj.getUid();
- }
-
- void getQuickNameIconForUid(Uid uidObj) {
- final int uid = uidObj.getUid();
- final String uidString = Integer.toString(uid);
- if (sUidCache.containsKey(uidString)) {
- UidToDetail utd = sUidCache.get(uidString);
- defaultPackageName = utd.packageName;
- name = utd.name;
- icon = utd.icon;
- return;
- }
- PackageManager pm = mContext.getPackageManager();
- String[] packages = pm.getPackagesForUid(uid);
- icon = pm.getDefaultActivityIcon();
- if (packages == null) {
- //name = Integer.toString(uid);
- if (uid == 0) {
- name = mContext.getResources().getString(R.string.process_kernel_label);
- } else if ("mediaserver".equals(name)) {
- name = mContext.getResources().getString(R.string.process_mediaserver_label);
- }
- iconId = R.drawable.ic_power_system;
- icon = mContext.getResources().getDrawable(iconId);
- return;
- } else {
- //name = packages[0];
- }
- if (mHandler != null) {
- synchronized (mRequestQueue) {
- mRequestQueue.add(this);
- }
- }
- }
-
- public static void clearUidCache() {
- sUidCache.clear();
- }
-
- /**
- * Loads the app label and icon image and stores into the cache.
- */
- public void loadNameAndIcon() {
- // Bail out if the current sipper is not an App sipper.
- if (uidObj == null) {
- return;
- }
- PackageManager pm = mContext.getPackageManager();
- final int uid = uidObj.getUid();
- final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
- mPackages = pm.getPackagesForUid(uid);
- if (mPackages == null) {
- name = Integer.toString(uid);
- return;
- }
-
- String[] packageLabels = new String[mPackages.length];
- System.arraycopy(mPackages, 0, packageLabels, 0, mPackages.length);
-
- int preferredIndex = -1;
- // Convert package names to user-facing labels where possible
- for (int i = 0; i < packageLabels.length; i++) {
- // Check if package matches preferred package
- if (packageLabels[i].equals(name)) preferredIndex = i;
- try {
- ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
- CharSequence label = ai.loadLabel(pm);
- if (label != null) {
- packageLabels[i] = label.toString();
- }
- if (ai.icon != 0) {
- defaultPackageName = mPackages[i];
- icon = ai.loadIcon(pm);
- break;
- }
- } catch (NameNotFoundException e) {
- }
- }
- if (icon == null) icon = defaultActivityIcon;
-
- if (packageLabels.length == 1) {
- name = packageLabels[0];
- } else {
- // Look for an official name for this UID.
- for (String pkgName : mPackages) {
- try {
- final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
- if (pi.sharedUserLabel != 0) {
- final CharSequence nm = pm.getText(pkgName,
- pi.sharedUserLabel, pi.applicationInfo);
- if (nm != null) {
- name = nm.toString();
- if (pi.applicationInfo.icon != 0) {
- defaultPackageName = pkgName;
- icon = pi.applicationInfo.loadIcon(pm);
- }
- break;
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- }
- final String uidString = Integer.toString(uidObj.getUid());
- UidToDetail utd = new UidToDetail();
- utd.name = name;
- utd.icon = icon;
- utd.packageName = defaultPackageName;
- sUidCache.put(uidString, utd);
- if (mHandler != null) {
- mHandler.sendMessage(
- mHandler.obtainMessage(BatteryStatsHelper.MSG_UPDATE_NAME_ICON, this));
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/BatteryStatsHelper.java b/src/com/android/settings/fuelgauge/BatteryStatsHelper.java
deleted file mode 100644
index 0191692a1..000000000
--- a/src/com/android/settings/fuelgauge/BatteryStatsHelper.java
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (C) 2009 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.fuelgauge;
-
-import static android.os.BatteryStats.NETWORK_MOBILE_RX_BYTES;
-import static android.os.BatteryStats.NETWORK_MOBILE_TX_BYTES;
-import static android.os.BatteryStats.NETWORK_WIFI_RX_BYTES;
-import static android.os.BatteryStats.NETWORK_WIFI_TX_BYTES;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.graphics.drawable.Drawable;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.os.BatteryStats;
-import android.os.BatteryStats.Uid;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.preference.PreferenceActivity;
-import android.telephony.SignalStrength;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.os.BatteryStatsImpl;
-import com.android.internal.os.PowerProfile;
-import com.android.internal.util.FastPrintWriter;
-import com.android.settings.R;
-import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
-import com.android.settings.users.UserUtils;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A helper class for retrieving the power usage information for all applications and services.
- *
- * The caller must initialize this class as soon as activity object is ready to use (for example, in
- * onAttach() for Fragment), call create() in onCreate() and call destroy() in onDestroy().
- */
-public class BatteryStatsHelper {
-
- private static final boolean DEBUG = false;
-
- private static final String TAG = BatteryStatsHelper.class.getSimpleName();
-
- private static BatteryStatsImpl sStatsXfer;
- private IBatteryStats mBatteryInfo;
- private UserManager mUm;
- private BatteryStatsImpl mStats;
- private PowerProfile mPowerProfile;
-
- private final List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
- private final List<BatterySipper> mWifiSippers = new ArrayList<BatterySipper>();
- private final List<BatterySipper> mBluetoothSippers = new ArrayList<BatterySipper>();
- private final SparseArray<List<BatterySipper>> mUserSippers
- = new SparseArray<List<BatterySipper>>();
- private final SparseArray<Double> mUserPower = new SparseArray<Double>();
-
- private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
-
- private long mStatsPeriod = 0;
- private double mMaxPower = 1;
- private double mTotalPower;
- private double mWifiPower;
- private double mBluetoothPower;
-
- // How much the apps together have left WIFI running.
- private long mAppWifiRunning;
-
- /** Queue for fetching name and icon for an application */
- private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>();
-
- private Activity mActivity;
- private Handler mHandler;
-
- private class NameAndIconLoader extends Thread {
- private boolean mAbort = false;
-
- public NameAndIconLoader() {
- super("BatteryUsage Icon Loader");
- }
-
- public void abort() {
- mAbort = true;
- }
-
- @Override
- public void run() {
- while (true) {
- BatterySipper bs;
- synchronized (mRequestQueue) {
- if (mRequestQueue.isEmpty() || mAbort) {
- mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
- return;
- }
- bs = mRequestQueue.remove(0);
- }
- bs.loadNameAndIcon();
- }
- }
- }
-
- private NameAndIconLoader mRequestThread;
-
- public BatteryStatsHelper(Activity activity, Handler handler) {
- mActivity = activity;
- mHandler = handler;
- }
-
- /** Clears the current stats and forces recreating for future use. */
- public void clearStats() {
- mStats = null;
- }
-
- public BatteryStatsImpl getStats() {
- if (mStats == null) {
- load();
- }
- return mStats;
- }
-
- public PowerProfile getPowerProfile() {
- return mPowerProfile;
- }
-
- public void create(Bundle icicle) {
- if (icicle != null) {
- mStats = sStatsXfer;
- }
- mBatteryInfo = IBatteryStats.Stub.asInterface(
- ServiceManager.getService(BatteryStats.SERVICE_NAME));
- mUm = (UserManager) mActivity.getSystemService(Context.USER_SERVICE);
- mPowerProfile = new PowerProfile(mActivity);
- }
-
- public void pause() {
- if (mRequestThread != null) {
- mRequestThread.abort();
- }
- }
-
- public void destroy() {
- if (mActivity.isChangingConfigurations()) {
- sStatsXfer = mStats;
- } else {
- BatterySipper.sUidCache.clear();
- }
- }
-
- public void startBatteryDetailPage(
- PreferenceActivity caller, BatterySipper sipper, boolean showLocationButton) {
- // Initialize mStats if necessary.
- getStats();
-
- Bundle args = new Bundle();
- args.putString(PowerUsageDetail.EXTRA_TITLE, sipper.name);
- args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
- Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
- args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
- Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
- args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, mStatsPeriod);
- args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
- args.putInt(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
- args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
- if (sipper.uidObj != null) {
- args.putInt(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
- }
- args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
- args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
-
- int[] types;
- double[] values;
- switch (sipper.drainType) {
- case APP:
- case USER:
- {
- Uid uid = sipper.uidObj;
- types = new int[] {
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_gps,
- R.string.usage_type_wifi_running,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- R.string.usage_type_audio,
- R.string.usage_type_video,
- };
- values = new double[] {
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.gpsTime,
- sipper.wifiRunningTime,
- sipper.mobileRxBytes,
- sipper.mobileTxBytes,
- sipper.wifiRxBytes,
- sipper.wifiTxBytes,
- 0,
- 0
- };
-
- if (sipper.drainType == DrainType.APP) {
- Writer result = new StringWriter();
- PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
- mStats.dumpLocked(printWriter, "", mStatsType, uid.getUid());
- printWriter.flush();
- args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
-
- result = new StringWriter();
- printWriter = new FastPrintWriter(result, false, 1024);
- mStats.dumpCheckinLocked(printWriter, mStatsType, uid.getUid());
- printWriter.flush();
- args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
- result.toString());
- }
- }
- break;
- case CELL:
- {
- types = new int[] {
- R.string.usage_type_on_time,
- R.string.usage_type_no_coverage
- };
- values = new double[] {
- sipper.usageTime,
- sipper.noCoveragePercent
- };
- }
- break;
- case WIFI:
- {
- types = new int[] {
- R.string.usage_type_wifi_running,
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- };
- values = new double[] {
- sipper.usageTime,
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.mobileRxBytes,
- sipper.mobileTxBytes,
- sipper.wifiRxBytes,
- sipper.wifiTxBytes,
- };
- } break;
- case BLUETOOTH:
- {
- types = new int[] {
- R.string.usage_type_on_time,
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- };
- values = new double[] {
- sipper.usageTime,
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.mobileRxBytes,
- sipper.mobileTxBytes,
- sipper.wifiRxBytes,
- sipper.wifiTxBytes,
- };
- } break;
- default:
- {
- types = new int[] {
- R.string.usage_type_on_time
- };
- values = new double[] {
- sipper.usageTime
- };
- }
- }
- args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
- args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
- caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
- R.string.details_title, null, null, 0);
- }
-
- /**
- * Refreshes the power usage list.
- * @param includeZeroConsumption whether includes those applications which have consumed very
- * little power up till now.
- */
- public void refreshStats(boolean includeZeroConsumption) {
- // Initialize mStats if necessary.
- getStats();
-
- mMaxPower = 0;
- mTotalPower = 0;
- mWifiPower = 0;
- mBluetoothPower = 0;
- mAppWifiRunning = 0;
-
- mUsageList.clear();
- mWifiSippers.clear();
- mBluetoothSippers.clear();
- mUserSippers.clear();
- mUserPower.clear();
-
- processAppUsage(includeZeroConsumption);
- processMiscUsage();
-
- Collections.sort(mUsageList);
-
- if (mHandler != null) {
- synchronized (mRequestQueue) {
- if (!mRequestQueue.isEmpty()) {
- if (mRequestThread != null) {
- mRequestThread.abort();
- }
- mRequestThread = new NameAndIconLoader();
- mRequestThread.setPriority(Thread.MIN_PRIORITY);
- mRequestThread.start();
- mRequestQueue.notify();
- }
- }
- }
- }
-
- private void processAppUsage(boolean includeZeroConsumption) {
- SensorManager sensorManager = (SensorManager) mActivity.getSystemService(
- Context.SENSOR_SERVICE);
- final int which = mStatsType;
- final int speedSteps = mPowerProfile.getNumSpeedSteps();
- final double[] powerCpuNormal = new double[speedSteps];
- final long[] cpuSpeedStepTimes = new long[speedSteps];
- for (int p = 0; p < speedSteps; p++) {
- powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
- }
- final double mobilePowerPerByte = getMobilePowerPerByte();
- final double wifiPowerPerByte = getWifiPowerPerByte();
- long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
- long appWakelockTime = 0;
- BatterySipper osApp = null;
- mStatsPeriod = uSecTime;
- SparseArray<? extends Uid> uidStats = mStats.getUidStats();
- final int NU = uidStats.size();
- for (int iu = 0; iu < NU; iu++) {
- Uid u = uidStats.valueAt(iu);
- double p; // in mAs
- double power = 0; // in mAs
- double highestDrain = 0;
- String packageWithHighestDrain = null;
- //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
- Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
- long cpuTime = 0;
- long cpuFgTime = 0;
- long wakelockTime = 0;
- long gpsTime = 0;
- if (DEBUG) Log.i(TAG, "UID " + u.getUid());
- if (processStats.size() > 0) {
- // Process CPU time
- for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
- : processStats.entrySet()) {
- Uid.Proc ps = ent.getValue();
- final long userTime = ps.getUserTime(which);
- final long systemTime = ps.getSystemTime(which);
- final long foregroundTime = ps.getForegroundTime(which);
- cpuFgTime += foregroundTime * 10; // convert to millis
- final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
- int totalTimeAtSpeeds = 0;
- // Get the total first
- for (int step = 0; step < speedSteps; step++) {
- cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
- totalTimeAtSpeeds += cpuSpeedStepTimes[step];
- }
- if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
- // Then compute the ratio of time spent at each speed
- double processPower = 0;
- for (int step = 0; step < speedSteps; step++) {
- double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
- processPower += ratio * tmpCpuTime * powerCpuNormal[step];
- }
- cpuTime += tmpCpuTime;
- if (DEBUG && processPower != 0) {
- Log.i(TAG, String.format("process %s, cpu power=%.2f",
- ent.getKey(), processPower / 1000));
- }
- power += processPower;
- if (packageWithHighestDrain == null
- || packageWithHighestDrain.startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
- } else if (highestDrain < processPower
- && !ent.getKey().startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
- }
- }
- }
- if (cpuFgTime > cpuTime) {
- if (DEBUG && cpuFgTime > cpuTime + 10000) {
- Log.i(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
- }
- cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
- }
- power /= 1000;
- if (DEBUG && power != 0) Log.i(TAG, String.format("total cpu power=%.2f", power));
-
- // Process wake lock usage
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
- : wakelockStats.entrySet()) {
- Uid.Wakelock wakelock = wakelockEntry.getValue();
- // Only care about partial wake locks since full wake locks
- // are canceled when the user turns the screen off.
- BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
- if (timer != null) {
- wakelockTime += timer.getTotalTimeLocked(uSecTime, which);
- }
- }
- wakelockTime /= 1000; // convert to millis
- appWakelockTime += wakelockTime;
-
- // Add cost of holding a wake lock
- p = (wakelockTime
- * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wakelock power=%.2f", p));
-
- // Add cost of mobile traffic
- final long mobileRx = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
- final long mobileTx = u.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
- p = (mobileRx + mobileTx) * mobilePowerPerByte;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("mobile power=%.2f", p));
-
- // Add cost of wifi traffic
- final long wifiRx = u.getNetworkActivityCount(NETWORK_WIFI_RX_BYTES, mStatsType);
- final long wifiTx = u.getNetworkActivityCount(NETWORK_WIFI_TX_BYTES, mStatsType);
- p = (wifiRx + wifiTx) * wifiPowerPerByte;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi power=%.2f", p));
-
- // Add cost of keeping WIFI running.
- long wifiRunningTimeMs = u.getWifiRunningTime(uSecTime, which) / 1000;
- mAppWifiRunning += wifiRunningTimeMs;
- p = (wifiRunningTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi running power=%.2f", p));
-
- // Add cost of WIFI scans
- long wifiScanTimeMs = u.getWifiScanTime(uSecTime, which) / 1000;
- p = (wifiScanTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi scanning power=%.2f", p));
- for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
- long batchScanTimeMs = u.getWifiBatchedScanTime(bin, uSecTime, which) / 1000;
- p = (batchScanTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin));
- power += p;
- if (DEBUG && p != 0) {
- Log.i(TAG, String.format("wifi batched scanning lvl %d = %.2f", bin, p));
- }
- }
-
- // Process Sensor usage
- Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
- for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
- : sensorStats.entrySet()) {
- Uid.Sensor sensor = sensorEntry.getValue();
- int sensorHandle = sensor.getHandle();
- BatteryStats.Timer timer = sensor.getSensorTime();
- long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
- double multiplier = 0;
- switch (sensorHandle) {
- case Uid.Sensor.GPS:
- multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
- gpsTime = sensorTime;
- break;
- default:
- List<Sensor> sensorList = sensorManager.getSensorList(
- android.hardware.Sensor.TYPE_ALL);
- for (android.hardware.Sensor s : sensorList) {
- if (s.getHandle() == sensorHandle) {
- multiplier = s.getPower();
- break;
- }
- }
- }
- p = (multiplier * sensorTime) / 1000;
- power += p;
- if (DEBUG && p != 0) {
- Log.i(TAG, String.format("sensor %s power=%.2f", sensor.toString(), p));
- }
- }
-
- if (DEBUG) Log.i(TAG, String.format("UID %d total power=%.2f", u.getUid(), power));
-
- // Add the app to the list if it is consuming power
- boolean isOtherUser = false;
- final int userId = UserHandle.getUserId(u.getUid());
- if (power != 0 || includeZeroConsumption || u.getUid() == 0) {
- BatterySipper app = new BatterySipper(mActivity, mRequestQueue, mHandler,
- packageWithHighestDrain, DrainType.APP, 0, u,
- new double[] {power});
- app.cpuTime = cpuTime;
- app.gpsTime = gpsTime;
- app.wifiRunningTime = wifiRunningTimeMs;
- app.cpuFgTime = cpuFgTime;
- app.wakeLockTime = wakelockTime;
- app.mobileRxBytes = mobileRx;
- app.mobileTxBytes = mobileTx;
- app.wifiRxBytes = wifiRx;
- app.wifiTxBytes = wifiTx;
- if (u.getUid() == Process.WIFI_UID) {
- mWifiSippers.add(app);
- } else if (u.getUid() == Process.BLUETOOTH_UID) {
- mBluetoothSippers.add(app);
- } else if (userId != UserHandle.myUserId()
- && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
- isOtherUser = true;
- List<BatterySipper> list = mUserSippers.get(userId);
- if (list == null) {
- list = new ArrayList<BatterySipper>();
- mUserSippers.put(userId, list);
- }
- list.add(app);
- } else {
- mUsageList.add(app);
- }
- if (u.getUid() == 0) {
- osApp = app;
- }
- }
- if (power != 0 || includeZeroConsumption) {
- if (u.getUid() == Process.WIFI_UID) {
- mWifiPower += power;
- } else if (u.getUid() == Process.BLUETOOTH_UID) {
- mBluetoothPower += power;
- } else if (isOtherUser) {
- Double userPower = mUserPower.get(userId);
- if (userPower == null) {
- userPower = power;
- } else {
- userPower += power;
- }
- mUserPower.put(userId, userPower);
- } else {
- if (power > mMaxPower) mMaxPower = power;
- mTotalPower += power;
- }
- }
- }
-
- // The device has probably been awake for longer than the screen on
- // time and application wake lock time would account for. Assign
- // this remainder to the OS, if possible.
- if (osApp != null) {
- long wakeTimeMillis = mStats.computeBatteryUptime(
- SystemClock.uptimeMillis() * 1000, which) / 1000;
- wakeTimeMillis -= appWakelockTime + (mStats.getScreenOnTime(
- SystemClock.elapsedRealtime(), which) / 1000);
- if (wakeTimeMillis > 0) {
- double power = (wakeTimeMillis
- * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
- if (DEBUG) Log.i(TAG, "OS wakeLockTime " + wakeTimeMillis + " power " + power);
- osApp.wakeLockTime += wakeTimeMillis;
- osApp.value += power;
- osApp.values[0] += power;
- if (osApp.value > mMaxPower) mMaxPower = osApp.value;
- mTotalPower += power;
- }
- }
- }
-
- private void addPhoneUsage(long uSecNow) {
- long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
- double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
- * phoneOnTimeMs / 1000;
- addEntry(mActivity.getString(R.string.power_phone), DrainType.PHONE, phoneOnTimeMs,
- R.drawable.ic_settings_voice_calls, phoneOnPower);
- }
-
- private void addScreenUsage(long uSecNow) {
- double power = 0;
- long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
- power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
- final double screenFullPower =
- mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
- for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- double screenBinPower = screenFullPower * (i + 0.5f)
- / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
- long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
- power += screenBinPower * brightnessTime;
- if (DEBUG) {
- Log.i(TAG, "Screen bin power = " + (int) screenBinPower + ", time = "
- + brightnessTime);
- }
- }
- power /= 1000; // To seconds
- addEntry(mActivity.getString(R.string.power_screen), DrainType.SCREEN, screenOnTimeMs,
- R.drawable.ic_settings_display, power);
- }
-
- private void addRadioUsage(long uSecNow) {
- double power = 0;
- final int BINS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
- long signalTimeMs = 0;
- for (int i = 0; i < BINS; i++) {
- long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, uSecNow, mStatsType) / 1000;
- power += strengthTimeMs / 1000
- * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
- signalTimeMs += strengthTimeMs;
- }
- long scanningTimeMs = mStats.getPhoneSignalScanningTime(uSecNow, mStatsType) / 1000;
- power += scanningTimeMs / 1000 * mPowerProfile.getAveragePower(
- PowerProfile.POWER_RADIO_SCANNING);
- BatterySipper bs =
- addEntry(mActivity.getString(R.string.power_cell), DrainType.CELL,
- signalTimeMs, R.drawable.ic_settings_cell_standby, power);
- if (signalTimeMs != 0) {
- bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
- / 1000 * 100.0 / signalTimeMs;
- }
- }
-
- private void aggregateSippers(BatterySipper bs, List<BatterySipper> from, String tag) {
- for (int i=0; i<from.size(); i++) {
- BatterySipper wbs = from.get(i);
- if (DEBUG) Log.i(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
- bs.cpuTime += wbs.cpuTime;
- bs.gpsTime += wbs.gpsTime;
- bs.wifiRunningTime += wbs.wifiRunningTime;
- bs.cpuFgTime += wbs.cpuFgTime;
- bs.wakeLockTime += wbs.wakeLockTime;
- bs.mobileRxBytes += wbs.mobileRxBytes;
- bs.mobileTxBytes += wbs.mobileTxBytes;
- bs.wifiRxBytes += wbs.wifiRxBytes;
- bs.wifiTxBytes += wbs.wifiTxBytes;
- }
- }
-
- private void addWiFiUsage(long uSecNow) {
- long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
- long runningTimeMs = mStats.getGlobalWifiRunningTime(uSecNow, mStatsType) / 1000;
- if (DEBUG) Log.i(TAG, "WIFI runningTime=" + runningTimeMs
- + " app runningTime=" + mAppWifiRunning);
- runningTimeMs -= mAppWifiRunning;
- if (runningTimeMs < 0) runningTimeMs = 0;
- double wifiPower = (onTimeMs * 0 /* TODO */
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
- + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
- if (DEBUG) Log.i(TAG, "WIFI power=" + wifiPower + " from procs=" + mWifiPower);
- BatterySipper bs = addEntry(mActivity.getString(R.string.power_wifi), DrainType.WIFI,
- runningTimeMs, R.drawable.ic_settings_wifi, wifiPower + mWifiPower);
- aggregateSippers(bs, mWifiSippers, "WIFI");
- }
-
- private void addIdleUsage(long uSecNow) {
- long idleTimeMs = (uSecNow - mStats.getScreenOnTime(uSecNow, mStatsType)) / 1000;
- double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
- / 1000;
- addEntry(mActivity.getString(R.string.power_idle), DrainType.IDLE, idleTimeMs,
- R.drawable.ic_settings_phone_idle, idlePower);
- }
-
- private void addBluetoothUsage(long uSecNow) {
- long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
- double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
- / 1000;
- int btPingCount = mStats.getBluetoothPingCount();
- btPower += (btPingCount
- * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
- BatterySipper bs = addEntry(mActivity.getString(R.string.power_bluetooth),
- DrainType.BLUETOOTH, btOnTimeMs, R.drawable.ic_settings_bluetooth,
- btPower + mBluetoothPower);
- aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
- }
-
- private void addUserUsage() {
- for (int i=0; i<mUserSippers.size(); i++) {
- final int userId = mUserSippers.keyAt(i);
- final List<BatterySipper> sippers = mUserSippers.valueAt(i);
- UserInfo info = mUm.getUserInfo(userId);
- Drawable icon;
- String name;
- if (info != null) {
- icon = UserUtils.getUserIcon(mActivity, mUm, info, mActivity.getResources());
- name = info != null ? info.name : null;
- if (name == null) {
- name = Integer.toString(info.id);
- }
- name = mActivity.getResources().getString(
- R.string.running_process_item_user_label, name);
- } else {
- icon = null;
- name = mActivity.getResources().getString(
- R.string.running_process_item_removed_user_label);
- }
- Double userPower = mUserPower.get(userId);
- double power = (userPower != null) ? userPower : 0.0;
- BatterySipper bs = addEntry(name, DrainType.USER, 0, 0, power);
- bs.icon = icon;
- aggregateSippers(bs, sippers, "User");
- }
- }
-
- /**
- * Return estimated power (in mAs) of sending a byte with the mobile radio.
- */
- private double getMobilePowerPerByte() {
- final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
- final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
- / 3600;
-
- final long mobileRx = mStats.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, mStatsType);
- final long mobileTx = mStats.getNetworkActivityCount(NETWORK_MOBILE_TX_BYTES, mStatsType);
- final long mobileData = mobileRx + mobileTx;
-
- final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
- final long mobileBps = radioDataUptimeMs != 0
- ? mobileData * 8 * 1000 / radioDataUptimeMs
- : MOBILE_BPS;
-
- return MOBILE_POWER / (mobileBps / 8);
- }
-
- /**
- * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
- */
- private double getWifiPowerPerByte() {
- final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
- final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
- / 3600;
- return WIFI_POWER / (WIFI_BPS / 8);
- }
-
- private void processMiscUsage() {
- final int which = mStatsType;
- long uSecTime = SystemClock.elapsedRealtime() * 1000;
- final long uSecNow = mStats.computeBatteryRealtime(uSecTime, which);
- final long timeSinceUnplugged = uSecNow;
- if (DEBUG) {
- Log.i(TAG, "Uptime since last unplugged = " + (timeSinceUnplugged / 1000));
- }
-
- addUserUsage();
- addPhoneUsage(uSecNow);
- addScreenUsage(uSecNow);
- addWiFiUsage(uSecNow);
- addBluetoothUsage(uSecNow);
- addIdleUsage(uSecNow); // Not including cellular idle power
- // Don't compute radio usage if it's a wifi-only device
- if (!com.android.settings.Utils.isWifiOnly(mActivity)) {
- addRadioUsage(uSecNow);
- }
- }
-
- private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
- double power) {
- if (power > mMaxPower) mMaxPower = power;
- mTotalPower += power;
- BatterySipper bs = new BatterySipper(mActivity, mRequestQueue, mHandler,
- label, drainType, iconId, null, new double[] {power});
- bs.usageTime = time;
- bs.iconId = iconId;
- mUsageList.add(bs);
- return bs;
- }
-
- public List<BatterySipper> getUsageList() {
- return mUsageList;
- }
-
- static final int MSG_UPDATE_NAME_ICON = 1;
- static final int MSG_REPORT_FULLY_DRAWN = 2;
-
- public double getMaxPower() {
- return mMaxPower;
- }
-
- public double getTotalPower() {
- return mTotalPower;
- }
-
- private void load() {
- try {
- byte[] data = mBatteryInfo.getStatistics();
- Parcel parcel = Parcel.obtain();
- parcel.unmarshall(data, 0, data.length);
- parcel.setDataPosition(0);
- mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
- .createFromParcel(parcel);
- mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException:", e);
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index c8bfa217d..a028adf77 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -24,6 +24,7 @@ import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.os.BatterySipper;
import com.android.settings.R;
/**
@@ -31,11 +32,11 @@ import com.android.settings.R;
* the left for the subsystem/app type.
*/
public class PowerGaugePreference extends Preference {
- private BatterySipper mInfo;
+ private BatteryEntry mInfo;
private int mProgress;
private CharSequence mProgressText;
- public PowerGaugePreference(Context context, Drawable icon, BatterySipper info) {
+ public PowerGaugePreference(Context context, Drawable icon, BatteryEntry info) {
super(context);
setLayoutResource(R.layout.app_percentage_item);
setIcon(icon != null ? icon : new ColorDrawable(0));
@@ -45,11 +46,11 @@ public class PowerGaugePreference extends Preference {
public void setPercent(double percentOfMax, double percentOfTotal) {
mProgress = (int) Math.ceil(percentOfMax);
mProgressText = getContext().getResources().getString(
- R.string.percentage, (int) Math.ceil(percentOfTotal));
+ R.string.percentage, (int) (percentOfTotal+.5));
notifyChanged();
}
- BatterySipper getInfo() {
+ BatteryEntry getInfo() {
return mInfo;
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 45e451655..518fc0eb2 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -34,13 +34,11 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
-import android.preference.PreferenceActivity;
-import android.provider.Settings;
import android.text.TextUtils;
-import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -49,26 +47,23 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.util.FastPrintWriter;
import com.android.settings.DisplaySettings;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.WirelessSettings;
import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.location.LocationSettings;
import com.android.settings.wifi.WifiSettings;
-public class PowerUsageDetail extends Fragment implements Button.OnClickListener {
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
- enum DrainType {
- IDLE,
- CELL,
- PHONE,
- WIFI,
- BLUETOOTH,
- SCREEN,
- APP,
- USER
- }
+public class PowerUsageDetail extends Fragment implements Button.OnClickListener {
// Note: Must match the sequence of the DrainType
private static int[] sDrainTypeDesciptions = new int[] {
@@ -80,8 +75,178 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
R.string.battery_desc_display,
R.string.battery_desc_apps,
R.string.battery_desc_users,
+ R.string.battery_desc_unaccounted,
+ R.string.battery_desc_overcounted,
};
+ public static void startBatteryDetailPage(
+ SettingsActivity caller, BatteryStatsHelper helper, BatteryEntry entry,
+ boolean showLocationButton) {
+ // Initialize mStats if necessary.
+ helper.getStats();
+
+ Bundle args = new Bundle();
+ args.putString(PowerUsageDetail.EXTRA_TITLE, entry.name);
+ args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
+ Math.ceil(entry.sipper.value * 100 / helper.getTotalPower()));
+ args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
+ Math.ceil(entry.sipper.value * 100 / helper.getMaxPower()));
+ args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, helper.getStatsPeriod());
+ args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, entry.defaultPackageName);
+ args.putInt(PowerUsageDetail.EXTRA_ICON_ID, entry.iconId);
+ args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, entry.sipper.noCoveragePercent);
+ if (entry.sipper.uidObj != null) {
+ args.putInt(PowerUsageDetail.EXTRA_UID, entry.sipper.uidObj.getUid());
+ }
+ args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, entry.sipper.drainType);
+ args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
+
+ int[] types;
+ double[] values;
+ switch (entry.sipper.drainType) {
+ case APP:
+ case USER:
+ {
+ BatteryStats.Uid uid = entry.sipper.uidObj;
+ types = new int[] {
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_gps,
+ R.string.usage_type_wifi_running,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_radio_active,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ R.string.usage_type_audio,
+ R.string.usage_type_video,
+ };
+ values = new double[] {
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.gpsTime,
+ entry.sipper.wifiRunningTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.mobileActive,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ 0,
+ 0
+ };
+
+ if (entry.sipper.drainType == BatterySipper.DrainType.APP) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
+ helper.getStats().dumpLocked(caller, printWriter, "", helper.getStatsType(),
+ uid.getUid());
+ printWriter.flush();
+ args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
+
+ result = new StringWriter();
+ printWriter = new FastPrintWriter(result, false, 1024);
+ helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(),
+ uid.getUid());
+ printWriter.flush();
+ args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
+ result.toString());
+ }
+ }
+ break;
+ case CELL:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time,
+ R.string.usage_type_no_coverage,
+ R.string.usage_type_radio_active,
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.noCoveragePercent,
+ entry.sipper.mobileActive
+ };
+ }
+ break;
+ case WIFI:
+ {
+ types = new int[] {
+ R.string.usage_type_wifi_running,
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ };
+ } break;
+ case BLUETOOTH:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time,
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ };
+ } break;
+ case UNACCOUNTED:
+ case OVERCOUNTED:
+ {
+ types = new int[] {
+ R.string.usage_type_total_battery_capacity,
+ R.string.usage_type_computed_power,
+ R.string.usage_type_min_actual_power,
+ R.string.usage_type_max_actual_power,
+ };
+ values = new double[] {
+ helper.getPowerProfile().getBatteryCapacity(),
+ helper.getComputedPower(),
+ helper.getMinDrainedPower(),
+ helper.getMaxDrainedPower(),
+ };
+ } break;
+ default:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time
+ };
+ values = new double[] {
+ entry.sipper.usageTime
+ };
+ }
+ }
+ args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
+ args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
+ caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
+ R.string.details_title, null, null, 0);
+ }
+
public static final int ACTION_DISPLAY_SETTINGS = 1;
public static final int ACTION_WIFI_SETTINGS = 2;
public static final int ACTION_BLUETOOTH_SETTINGS = 3;
@@ -125,7 +290,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
private ViewGroup mDetailsParent;
private ViewGroup mControlsParent;
private long mStartTime;
- private DrainType mDrainType;
+ private BatterySipper.DrainType mDrainType;
private Drawable mAppIcon;
private double mNoCoverage; // Percentage of time that there was no coverage
@@ -175,7 +340,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
final int gaugeValue = args.getInt(EXTRA_GAUGE, 1);
mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
mUid = args.getInt(EXTRA_UID, 0);
- mDrainType = (DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
+ mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0);
String iconPackage = args.getString(EXTRA_ICON_PACKAGE);
int iconId = args.getInt(EXTRA_ICON_ID, 0);
@@ -238,8 +403,8 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
mReportButton.setOnClickListener(this);
// check if error reporting is enabled in secure settings
- int enabled = Settings.Global.getInt(getActivity().getContentResolver(),
- Settings.Global.SEND_ACTION_APP_ERROR, 0);
+ int enabled = android.provider.Settings.Global.getInt(getActivity().getContentResolver(),
+ android.provider.Settings.Global.SEND_ACTION_APP_ERROR, 0);
if (enabled != 0) {
if (mPackages != null && mPackages.length > 0) {
try {
@@ -269,35 +434,35 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
Bundle args = new Bundle();
args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mPackages[0]);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
R.string.application_info_label, null, null, 0);
}
private void doAction(int action) {
- PreferenceActivity pa = (PreferenceActivity)getActivity();
+ SettingsActivity sa = (SettingsActivity)getActivity();
switch (action) {
case ACTION_DISPLAY_SETTINGS:
- pa.startPreferencePanel(DisplaySettings.class.getName(), null,
+ sa.startPreferencePanel(DisplaySettings.class.getName(), null,
R.string.display_settings_title, null, null, 0);
break;
case ACTION_WIFI_SETTINGS:
- pa.startPreferencePanel(WifiSettings.class.getName(), null,
+ sa.startPreferencePanel(WifiSettings.class.getName(), null,
R.string.wifi_settings, null, null, 0);
break;
case ACTION_BLUETOOTH_SETTINGS:
- pa.startPreferencePanel(BluetoothSettings.class.getName(), null,
+ sa.startPreferencePanel(BluetoothSettings.class.getName(), null,
R.string.bluetooth_settings, null, null, 0);
break;
case ACTION_WIRELESS_SETTINGS:
- pa.startPreferencePanel(WirelessSettings.class.getName(), null,
+ sa.startPreferencePanel(WirelessSettings.class.getName(), null,
R.string.radio_controls_title, null, null, 0);
break;
case ACTION_APP_DETAILS:
startApplicationDetailsActivity();
break;
case ACTION_LOCATION_SETTINGS:
- pa.startPreferencePanel(LocationSettings.class.getName(), null,
+ sa.startPreferencePanel(LocationSettings.class.getName(), null,
R.string.location_settings_title, null, null, 0);
break;
case ACTION_FORCE_STOP:
@@ -322,13 +487,19 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener
case R.string.usage_type_data_send:
case R.string.usage_type_data_wifi_recv:
case R.string.usage_type_data_wifi_send:
- final long bytes = (long) (mValues[i]);
- value = Formatter.formatFileSize(getActivity(), bytes);
+ final long packets = (long) (mValues[i]);
+ value = Long.toString(packets);
break;
case R.string.usage_type_no_coverage:
final int percentage = (int) Math.floor(mValues[i]);
value = getActivity().getString(R.string.percentage, percentage);
break;
+ case R.string.usage_type_total_battery_capacity:
+ case R.string.usage_type_computed_power:
+ case R.string.usage_type_min_actual_power:
+ case R.string.usage_type_max_actual_power:
+ value = getActivity().getString(R.string.mah, (long)(mValues[i]));
+ break;
case R.string.usage_type_gps:
mUsesGps = true;
// Fall through
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index dc86b8de2..8a7299413 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -26,8 +26,9 @@ 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;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
@@ -36,9 +37,12 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.PowerProfile;
import com.android.settings.HelpUtils;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import java.util.List;
@@ -59,7 +63,11 @@ public class PowerUsageSummary extends PreferenceFragment {
private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
private static final int MENU_HELP = Menu.FIRST + 2;
+ private UserManager mUm;
+
private PreferenceGroup mAppListGroup;
+ private String mBatteryLevel;
+ private String mBatteryStatus;
private Preference mBatteryStatusPref;
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
@@ -74,13 +82,8 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
- String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent);
- String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(),
- intent);
- String batterySummary = context.getResources().getString(
- R.string.power_usage_level_and_status, batteryLevel, batteryStatus);
- mBatteryStatusPref.setTitle(batterySummary);
+ if (Intent.ACTION_BATTERY_CHANGED.equals(action)
+ && updateBatteryStatus(intent)) {
mStatsHelper.clearStats();
refreshStats();
}
@@ -90,7 +93,8 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mStatsHelper = new BatteryStatsHelper(activity, mHandler);
+ mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE);
+ mStatsHelper = new BatteryStatsHelper(activity);
}
@Override
@@ -107,15 +111,15 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public void onResume() {
super.onResume();
- getActivity().registerReceiver(mBatteryInfoReceiver,
- new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ updateBatteryStatus(getActivity().registerReceiver(mBatteryInfoReceiver,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
refreshStats();
}
@Override
public void onPause() {
- mStatsHelper.pause();
- mHandler.removeMessages(BatteryStatsHelper.MSG_UPDATE_NAME_ICON);
+ BatteryEntry.stopRequestQueue();
+ mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON);
getActivity().unregisterReceiver(mBatteryInfoReceiver);
super.onPause();
}
@@ -123,7 +127,10 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public void onDestroy() {
super.onDestroy();
- mStatsHelper.destroy();
+ if (getActivity().isChangingConfigurations()) {
+ mStatsHelper.storeState();
+ BatteryEntry.clearUidCache();
+ }
}
@Override
@@ -134,8 +141,8 @@ public class PowerUsageSummary extends PreferenceFragment {
byte[] histData = hist.marshall();
Bundle args = new Bundle();
args.putByteArray(BatteryHistoryDetail.EXTRA_STATS, histData);
- PreferenceActivity pa = (PreferenceActivity)getActivity();
- pa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args,
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(BatteryHistoryDetail.class.getName(), args,
R.string.history_details_title, null, null, 0);
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@@ -143,8 +150,9 @@ public class PowerUsageSummary extends PreferenceFragment {
return false;
}
PowerGaugePreference pgp = (PowerGaugePreference) preference;
- BatterySipper sipper = pgp.getInfo();
- mStatsHelper.startBatteryDetailPage((PreferenceActivity) getActivity(), sipper, true);
+ BatteryEntry entry = pgp.getInfo();
+ PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), mStatsHelper,
+ entry, true);
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@@ -194,12 +202,32 @@ public class PowerUsageSummary extends PreferenceFragment {
mAppListGroup.addPreference(notAvailable);
}
+ private boolean updateBatteryStatus(Intent intent) {
+ if (intent != null) {
+ String batteryLevel = com.android.settings.Utils.getBatteryPercentage(intent);
+ String batteryStatus = com.android.settings.Utils.getBatteryStatus(getResources(),
+ intent);
+ if (!batteryLevel.equals(mBatteryLevel) || !batteryStatus.equals(mBatteryStatus)) {
+ mBatteryLevel = batteryLevel;
+ mBatteryStatus = batteryStatus;
+ return true;
+ }
+ }
+ return false;
+ }
+
private void refreshStats() {
mAppListGroup.removeAll();
mAppListGroup.setOrderingAsAdded(false);
mBatteryStatusPref.setOrder(-2);
+ if (mBatteryLevel != null && mBatteryStatus != null) {
+ String batterySummary = getActivity().getResources().getString(
+ R.string.power_usage_level_and_status, mBatteryLevel, mBatteryStatus);
+ mBatteryStatusPref.setTitle(batterySummary);
+ }
mAppListGroup.addPreference(mBatteryStatusPref);
+
BatteryHistoryPreference hist = new BatteryHistoryPreference(
getActivity(), mStatsHelper.getStats());
hist.setOrder(-1);
@@ -210,20 +238,29 @@ public class PowerUsageSummary extends PreferenceFragment {
addNotAvailableMessage();
return;
}
- mStatsHelper.refreshStats(false);
+ int dischargeAmount = mStatsType == BatteryStats.STATS_SINCE_CHARGED
+ ? mStatsHelper.getStats().getHighDischargeAmountSinceCharge()
+ : (mStatsHelper.getStats().getDischargeStartLevel()
+ - mStatsHelper.getStats().getDischargeCurrentLevel());
+ if (dischargeAmount < 0) {
+ dischargeAmount = 0;
+ }
+ mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId());
List<BatterySipper> usageList = mStatsHelper.getUsageList();
- for (BatterySipper sipper : usageList) {
- if (sipper.getSortValue() < MIN_POWER_THRESHOLD) continue;
+ for (int i=0; i<usageList.size(); i++) {
+ BatterySipper sipper = usageList.get(i);
+ if ((sipper.value*60*60) < MIN_POWER_THRESHOLD) continue;
final double percentOfTotal =
- ((sipper.getSortValue() / mStatsHelper.getTotalPower()) * 100);
- if (percentOfTotal < 1) continue;
+ ((sipper.value / mStatsHelper.getTotalPower()) * dischargeAmount);
+ if (((int)(percentOfTotal+.5)) < 1) continue;
+ BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper);
PowerGaugePreference pref =
- new PowerGaugePreference(getActivity(), sipper.getIcon(), sipper);
+ new PowerGaugePreference(getActivity(), entry.getIcon(), entry);
final double percentOfMax =
- (sipper.getSortValue() * 100) / mStatsHelper.getMaxPower();
+ (sipper.value * 100) / mStatsHelper.getMaxPower();
sipper.percent = percentOfTotal;
- pref.setTitle(sipper.name);
- pref.setOrder(Integer.MAX_VALUE - (int) sipper.getSortValue()); // Invert the order
+ pref.setTitle(entry.getLabel());
+ pref.setOrder(i+1);
pref.setPercent(percentOfMax, percentOfTotal);
if (sipper.uidObj != null) {
pref.setKey(Integer.toString(sipper.uidObj.getUid()));
@@ -231,6 +268,8 @@ public class PowerUsageSummary extends PreferenceFragment {
mAppListGroup.addPreference(pref);
if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break;
}
+
+ BatteryEntry.startRequestQueue();
}
Handler mHandler = new Handler() {
@@ -238,17 +277,17 @@ public class PowerUsageSummary extends PreferenceFragment {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case BatteryStatsHelper.MSG_UPDATE_NAME_ICON:
- BatterySipper bs = (BatterySipper) msg.obj;
+ case BatteryEntry.MSG_UPDATE_NAME_ICON:
+ BatteryEntry entry = (BatteryEntry) msg.obj;
PowerGaugePreference pgp =
(PowerGaugePreference) findPreference(
- Integer.toString(bs.uidObj.getUid()));
+ Integer.toString(entry.sipper.uidObj.getUid()));
if (pgp != null) {
- pgp.setIcon(bs.icon);
- pgp.setTitle(bs.name);
+ pgp.setIcon(entry.icon);
+ pgp.setTitle(entry.name);
}
break;
- case BatteryStatsHelper.MSG_REPORT_FULLY_DRAWN:
+ case BatteryEntry.MSG_REPORT_FULLY_DRAWN:
Activity activity = getActivity();
if (activity != null) {
activity.reportFullyDrawn();
diff --git a/src/com/android/settings/indexer/Index.java b/src/com/android/settings/indexer/Index.java
new file mode 100644
index 000000000..19b545f9b
--- /dev/null
+++ b/src/com/android/settings/indexer/Index.java
@@ -0,0 +1,524 @@
+/*
+ * 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.indexer;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.AsyncTask;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.util.Xml;
+import com.android.settings.R;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static com.android.settings.indexer.IndexDatabaseHelper.Tables;
+import static com.android.settings.indexer.IndexDatabaseHelper.IndexColumns;
+
+public class Index {
+
+ private static final String LOG_TAG = "Index";
+
+ // Those indices should match the indices of SELECT_COLUMNS !
+ public static final int COLUMN_INDEX_TITLE = 1;
+ public static final int COLUMN_INDEX_SUMMARY = 2;
+ public static final int COLUMN_INDEX_FRAGMENT_NAME = 4;
+ public static final int COLUMN_INDEX_FRAGMENT_TITLE = 5;
+ public static final int COLUMN_INDEX_ICON = 7;
+
+ // If you change the order of columns here, you SHOULD change the COLUMN_INDEX_XXX values
+ private static final String[] SELECT_COLUMNS = new String[] {
+ IndexColumns.DATA_RANK,
+ IndexColumns.DATA_TITLE,
+ IndexColumns.DATA_SUMMARY,
+ IndexColumns.DATA_KEYWORDS,
+ IndexColumns.FRAGMENT_NAME,
+ IndexColumns.FRAGMENT_TITLE,
+ IndexColumns.INTENT,
+ IndexColumns.ICON
+ };
+
+ private static final String[] MATCH_COLUMNS = {
+ IndexColumns.DATA_TITLE,
+ IndexColumns.DATA_TITLE_NORMALIZED,
+ IndexColumns.DATA_SUMMARY,
+ IndexColumns.DATA_SUMMARY_NORMALIZED,
+ IndexColumns.DATA_KEYWORDS
+ };
+
+ private static final String EMPTY = "";
+ private static final String NON_BREAKING_HYPHEN = "\u2011";
+ private static final String HYPHEN = "-";
+
+ private static Index sInstance;
+
+ private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
+
+ private final UpdateData mUpdateData = new UpdateData();
+
+ private final Context mContext;
+
+ /**
+ * A basic singleton
+ */
+ public static Index getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new Index(context);
+ }
+ return sInstance;
+ }
+
+ public Index(Context context) {
+ mContext = context;
+ }
+
+ public boolean isAvailable() {
+ return mIsAvailable.get();
+ }
+
+ public void addIndexableData(IndexableRef[] array) {
+ synchronized (mUpdateData) {
+ final int count = array.length;
+ for (int n = 0; n < count; n++) {
+ mUpdateData.dataToAdd.add(array[n]);
+ }
+ }
+ }
+
+ public void deleteIndexableData(String[] array) {
+ synchronized (mUpdateData) {
+ final int count = array.length;
+ for (int n = 0; n < count; n++) {
+ mUpdateData.dataToDelete.add(array[n]);
+ }
+ }
+ }
+
+ public boolean update() {
+ synchronized (mUpdateData) {
+ final UpdateIndexTask task = new UpdateIndexTask();
+ task.execute(mUpdateData);
+ try {
+ final boolean result = task.get();
+ mUpdateData.clear();
+ return result;
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
+ return false;
+ } catch (ExecutionException e) {
+ Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
+ return false;
+ }
+ }
+ }
+
+ public Cursor search(String query) {
+ final String sql = buildSQL(query);
+ Log.d(LOG_TAG, "Query: " + sql);
+ return getReadableDatabase().rawQuery(sql, null);
+ }
+
+ private String buildSQL(String query) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(buildSQLForColumn(query, MATCH_COLUMNS));
+ sb.append(" ORDER BY ");
+ sb.append(IndexColumns.DATA_RANK);
+ return sb.toString();
+ }
+
+ private String buildSQLForColumn(String query, String[] columnNames) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("SELECT ");
+ for (int n = 0; n < SELECT_COLUMNS.length; n++) {
+ sb.append(SELECT_COLUMNS[n]);
+ if (n < SELECT_COLUMNS.length - 1) {
+ sb.append(", ");
+ }
+ }
+ sb.append(" FROM ");
+ sb.append(Tables.TABLE_PREFS_INDEX);
+ sb.append(" WHERE ");
+ sb.append(buildWhereStringForColumns(query, columnNames));
+
+ return sb.toString();
+ }
+
+ private String buildWhereStringForColumns(String query, String[] columnNames) {
+ final StringBuilder sb = new StringBuilder(Tables.TABLE_PREFS_INDEX);
+ sb.append(" MATCH ");
+ DatabaseUtils.appendEscapedSQLString(sb, buildMatchStringForColumns(query, columnNames));
+ sb.append(" AND ");
+ sb.append(IndexColumns.LOCALE);
+ sb.append(" = ");
+ DatabaseUtils.appendEscapedSQLString(sb, Locale.getDefault().toString());
+ return sb.toString();
+ }
+
+ private String buildMatchStringForColumns(String query, String[] columnNames) {
+ final String value = query + "*";
+ StringBuilder sb = new StringBuilder();
+ final int count = columnNames.length;
+ for (int n = 0; n < count; n++) {
+ sb.append(columnNames[n]);
+ sb.append(":");
+ sb.append(value);
+ if (n < count - 1) {
+ sb.append(" OR ");
+ }
+ }
+ return sb.toString();
+ }
+
+ private SQLiteDatabase getReadableDatabase() {
+ return IndexDatabaseHelper.getInstance(mContext).getReadableDatabase();
+ }
+
+ private SQLiteDatabase getWritableDatabase() {
+ return IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
+ }
+
+ /**
+ * A private class to describe the update data for the Index database
+ */
+ private class UpdateData {
+ public List<IndexableRef> dataToAdd;
+ public List<String> dataToDelete;
+
+ public UpdateData() {
+ dataToAdd = new ArrayList<IndexableRef>();
+ dataToDelete = new ArrayList<String>();
+ }
+
+ public void clear() {
+ dataToAdd.clear();
+ dataToDelete.clear();
+ }
+ }
+
+ /**
+ * A private class for updating the Index database
+ */
+ private class UpdateIndexTask extends AsyncTask<UpdateData, Integer, Boolean> {
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ mIsAvailable.set(false);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean aBoolean) {
+ super.onPostExecute(aBoolean);
+ mIsAvailable.set(true);
+ }
+
+ @Override
+ protected Boolean doInBackground(UpdateData... params) {
+ boolean result = false;
+
+ final List<IndexableRef> dataToAdd = params[0].dataToAdd;
+ final List<String> dataToDelete = params[0].dataToDelete;
+ final SQLiteDatabase database = getWritableDatabase();
+ final String localeStr = Locale.getDefault().toString();
+
+ try {
+ database.beginTransaction();
+ if (dataToAdd.size() > 0) {
+ processDataToAdd(database, localeStr, dataToAdd);
+ }
+ if (dataToDelete.size() > 0) {
+ processDataToDelete(database, localeStr, dataToDelete);
+ }
+ database.setTransactionSuccessful();
+ result = true;
+ } finally {
+ database.endTransaction();
+ }
+ return result;
+ }
+
+ private boolean processDataToDelete(SQLiteDatabase database, String localeStr,
+ List<String> dataToDelete) {
+
+ boolean result = false;
+ final long current = System.currentTimeMillis();
+
+ final int count = dataToDelete.size();
+ for (int n = 0; n < count; n++) {
+ final String data = dataToDelete.get(n);
+ delete(database, data);
+ }
+
+ final long now = System.currentTimeMillis();
+ Log.d(LOG_TAG, "Deleting data for locale '" + localeStr + "' took " +
+ (now - current) + " millis");
+ return result;
+ }
+
+ private boolean processDataToAdd(SQLiteDatabase database, String localeStr,
+ List<IndexableRef> dataToAdd) {
+ if (isLocaleAlreadyIndexed(database, localeStr)) {
+ Log.d(LOG_TAG, "Locale '" + localeStr + "' is already indexed");
+ return true;
+ }
+
+ boolean result = false;
+ final long current = System.currentTimeMillis();
+
+ final int count = dataToAdd.size();
+ for (int n = 0; n < count; n++) {
+ final IndexableRef ref = dataToAdd.get(n);
+ indexOneRef(database, localeStr, ref);
+ }
+
+ final long now = System.currentTimeMillis();
+ Log.d(LOG_TAG, "Indexing locale '" + localeStr + "' took " +
+ (now - current) + " millis");
+ return result;
+ }
+
+ private void indexOneRef(SQLiteDatabase database, String localeStr, IndexableRef ref) {
+ if (ref.xmlResId > 0) {
+ indexFromResource(database, localeStr, ref.xmlResId, ref.fragmentName,
+ ref.iconResId, ref.rank);
+ } else if (!TextUtils.isEmpty(ref.fragmentName)) {
+ indexRawData(database, localeStr, ref);
+ }
+ }
+
+ private void indexRawData(SQLiteDatabase database, String localeStr, IndexableRef ref) {
+ try {
+ final Class<?> clazz = Class.forName(ref.fragmentName);
+ if (Indexable.class.isAssignableFrom(clazz)) {
+ final Field f = clazz.getField("INDEX_DATA_PROVIDER");
+ final Indexable.IndexDataProvider provider =
+ (Indexable.IndexDataProvider) f.get(null);
+
+ final List<IndexableData> data = provider.getRawDataToIndex(mContext);
+
+ final int size = data.size();
+ for (int i = 0; i < size; i++) {
+ IndexableData raw = data.get(i);
+
+ // Should be the same locale as the one we are processing
+ if (!raw.locale.toString().equalsIgnoreCase(localeStr)) {
+ continue;
+ }
+
+ inserOneRowWithFilteredData(database, localeStr,
+ raw.title,
+ raw.summary,
+ ref.fragmentName,
+ raw.fragmentTitle,
+ ref.iconResId,
+ ref.rank,
+ raw.keywords);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "Cannot find class: " + ref.fragmentName, e);
+ } catch (NoSuchFieldException e) {
+ Log.e(LOG_TAG, "Cannot find field 'INDEX_DATA_PROVIDER'", e);
+ } catch (IllegalAccessException e) {
+ Log.e(LOG_TAG, "Illegal access to field 'INDEX_DATA_PROVIDER'", e);
+ }
+ }
+
+ private boolean isLocaleAlreadyIndexed(SQLiteDatabase database, String locale) {
+ Cursor cursor = null;
+ boolean result = false;
+ final StringBuilder sb = new StringBuilder(IndexColumns.LOCALE);
+ sb.append(" = ");
+ DatabaseUtils.appendEscapedSQLString(sb, locale);
+ try {
+ // We care only for 1 row
+ cursor = database.query(Tables.TABLE_PREFS_INDEX, null,
+ sb.toString(), null, null, null, null, "1");
+ final int count = cursor.getCount();
+ result = (count >= 1);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return result;
+ }
+
+ private void indexFromResource(SQLiteDatabase database, String localeStr, int xmlResId,
+ String fragmentName, int iconResId, int rank) {
+ XmlResourceParser parser = null;
+ try {
+ parser = mContext.getResources().getXml(xmlResId);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ // Parse next until start tag is found
+ }
+
+ String nodeName = parser.getName();
+ if (!"PreferenceScreen".equals(nodeName)) {
+ throw new RuntimeException(
+ "XML document must start with <PreferenceScreen> tag; found"
+ + nodeName + " at " + parser.getPositionDescription());
+ }
+
+ final int outerDepth = parser.getDepth();
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ final String fragmentTitle = getDataTitle(attrs);
+
+ String title = getDataTitle(attrs);
+ String summary = getDataSummary(attrs);
+ String keywords = getDataKeywords(attrs);
+
+ // Insert rows for the main PreferenceScreen node. Rewrite the data for removing
+ // hyphens.
+ inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
+ fragmentTitle, iconResId, rank, keywords);
+
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ title = getDataTitle(attrs);
+ summary = getDataSummary(attrs);
+ keywords = getDataKeywords(attrs);
+
+ // Insert rows for the child nodes of PreferenceScreen
+ inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
+ fragmentTitle, iconResId, rank, keywords);
+ }
+
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException("Error parsing PreferenceScreen", e);
+ } catch (IOException e) {
+ throw new RuntimeException("Error parsing PreferenceScreen", e);
+ } finally {
+ if (parser != null) parser.close();
+ }
+ }
+
+ private void inserOneRowWithFilteredData(SQLiteDatabase database, String locale,
+ String title, String summary, String fragmentName, String fragmentTitle,
+ int iconResId, int rank, String keywords) {
+
+ String updatedTitle;
+ if (title != null) {
+ updatedTitle = title.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
+ }
+ else {
+ updatedTitle = EMPTY;
+ }
+
+ String updatedSummary;
+ if (summary != null) {
+ updatedSummary = summary.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
+ } else {
+ updatedSummary = EMPTY;
+ }
+
+ String normalizedTitle = updatedTitle.replaceAll(HYPHEN, EMPTY);
+ String normalizedSummary = updatedSummary.replaceAll(HYPHEN, EMPTY);
+
+ insertOneRow(database, locale,
+ updatedTitle, normalizedTitle, updatedSummary, normalizedSummary,
+ fragmentName, fragmentTitle, iconResId, rank, keywords);
+ }
+
+ private void insertOneRow(SQLiteDatabase database, String locale,
+ String updatedTitle, String normalizedTitle,
+ String updatedSummary, String normalizedSummary,
+ String fragmentName, String fragmentTitle,
+ int iconResId, int rank, String keywords) {
+
+ if (TextUtils.isEmpty(updatedTitle)) {
+ return;
+ }
+ ContentValues values = new ContentValues();
+ values.put(IndexColumns.LOCALE, locale);
+ values.put(IndexColumns.DATA_RANK, rank);
+ values.put(IndexColumns.DATA_TITLE, updatedTitle);
+ values.put(IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
+ values.put(IndexColumns.DATA_SUMMARY, updatedSummary);
+ values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary);
+ values.put(IndexColumns.DATA_KEYWORDS, keywords);
+ values.put(IndexColumns.FRAGMENT_NAME, fragmentName);
+ values.put(IndexColumns.FRAGMENT_TITLE, fragmentTitle);
+ values.put(IndexColumns.INTENT, "");
+ values.put(IndexColumns.ICON, iconResId);
+
+ database.insertOrThrow(Tables.TABLE_PREFS_INDEX, null, values);
+ }
+
+ private int delete(SQLiteDatabase database, String title) {
+ final String whereClause = IndexColumns.DATA_TITLE + "=?";
+ final String[] whereArgs = new String[] { title };
+
+ return database.delete(Tables.TABLE_PREFS_INDEX, whereClause, whereArgs);
+ }
+
+ private String getDataTitle(AttributeSet attrs) {
+ return getData(attrs,
+ com.android.internal.R.styleable.Preference,
+ com.android.internal.R.styleable.Preference_title);
+ }
+
+ private String getDataSummary(AttributeSet attrs) {
+ return getData(attrs,
+ com.android.internal.R.styleable.Preference,
+ com.android.internal.R.styleable.Preference_summary);
+ }
+
+ private String getDataKeywords(AttributeSet attrs) {
+ return getData(attrs,
+ R.styleable.Preference,
+ R.styleable.Preference_keywords);
+ }
+
+ private String getData(AttributeSet set, int[] attrs, int resId) {
+ final TypedArray sa = mContext.obtainStyledAttributes(set, attrs);
+ final TypedValue tv = sa.peekValue(resId);
+
+ CharSequence data = null;
+ if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+ if (tv.resourceId != 0) {
+ data = mContext.getText(tv.resourceId);
+ } else {
+ data = tv.string;
+ }
+ }
+ return (data != null) ? data.toString() : null;
+ }
+ }
+}
diff --git a/src/com/android/settings/indexer/IndexDatabaseHelper.java b/src/com/android/settings/indexer/IndexDatabaseHelper.java
new file mode 100644
index 000000000..3e6396e88
--- /dev/null
+++ b/src/com/android/settings/indexer/IndexDatabaseHelper.java
@@ -0,0 +1,171 @@
+/*
+ * 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.indexer;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Build;
+import android.util.Log;
+
+public class IndexDatabaseHelper extends SQLiteOpenHelper {
+
+ private static final String TAG = "IndexDatabaseHelper";
+
+ private static final String DATABASE_NAME = "search_index.db";
+ private static final int DATABASE_VERSION = 101;
+
+ public interface Tables {
+ public static final String TABLE_PREFS_INDEX = "prefs_index";
+ public static final String TABLE_META_INDEX = "meta_index";
+ }
+
+ public interface IndexColumns {
+ public static final String LOCALE = "locale";
+ public static final String DATA_RANK = "data_rank";
+ public static final String DATA_TITLE = "data_title";
+ public static final String DATA_TITLE_NORMALIZED = "data_title_normalized";
+ public static final String DATA_SUMMARY = "data_summary";
+ public static final String DATA_SUMMARY_NORMALIZED = "data_summary_normalized";
+ public static final String DATA_KEYWORDS = "data_keywords";
+ public static final String FRAGMENT_NAME = "fragment_name";
+ public static final String FRAGMENT_TITLE = "fragment_title";
+ public static final String INTENT = "intent";
+ public static final String ICON = "icon";
+ }
+
+ public interface MetaColumns {
+ public static final String BUILD = "build";
+ }
+
+ private static final String CREATE_INDEX_TABLE =
+ "CREATE VIRTUAL TABLE " + Tables.TABLE_PREFS_INDEX + " USING fts4" +
+ "(" +
+ IndexColumns.LOCALE +
+ ", " +
+ IndexColumns.DATA_RANK +
+ ", " +
+ IndexColumns.DATA_TITLE +
+ ", " +
+ IndexColumns.DATA_TITLE_NORMALIZED +
+ ", " +
+ IndexColumns.DATA_SUMMARY +
+ ", " +
+ IndexColumns.DATA_SUMMARY_NORMALIZED +
+ ", " +
+ IndexColumns.DATA_KEYWORDS +
+ ", " +
+ IndexColumns.FRAGMENT_NAME +
+ ", " +
+ IndexColumns.FRAGMENT_TITLE +
+ ", " +
+ IndexColumns.INTENT +
+ ", " +
+ IndexColumns.ICON +
+ ");";
+
+ private static final String CREATE_META_TABLE =
+ "CREATE TABLE " + Tables.TABLE_META_INDEX +
+ "(" +
+ MetaColumns.BUILD + " VARCHAR(32) NOT NULL" +
+ ")";
+
+ private static final String INSERT_BUILD_VERSION =
+ "INSERT INTO " + Tables.TABLE_META_INDEX +
+ " VALUES ('" + Build.VERSION.INCREMENTAL + "');";
+
+ private static final String SELECT_BUILD_VERSION =
+ "SELECT " + MetaColumns.BUILD + " FROM " + Tables.TABLE_META_INDEX + " LIMIT 1;";
+
+ private static IndexDatabaseHelper sSingleton;
+
+ public static synchronized IndexDatabaseHelper getInstance(Context context) {
+ if (sSingleton == null) {
+ sSingleton = new IndexDatabaseHelper(context);
+ }
+ return sSingleton;
+ }
+
+ public IndexDatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ bootstrapDB(db);
+ }
+
+ private void bootstrapDB(SQLiteDatabase db) {
+ db.execSQL(CREATE_INDEX_TABLE);
+ db.execSQL(CREATE_META_TABLE);
+ db.execSQL(INSERT_BUILD_VERSION);
+ Log.i(TAG, "Bootstrapped database");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (newVersion > 100) {
+ Log.w(TAG, "Detected schema version 100. " +
+ "Index needs to be rebuilt for schema version 101");
+ // We need to drop the tables and recreate them
+ dropTables(db);
+ bootstrapDB(db);
+ }
+ }
+
+ private String getBuildVersion(SQLiteDatabase db) {
+ String version = null;
+ Cursor cursor = null;
+ try {
+ cursor = db.rawQuery(SELECT_BUILD_VERSION, null);
+ if (cursor.moveToFirst()) {
+ version = cursor.getString(0);
+ }
+ }
+ catch (Exception e) {
+ Log.e(TAG, "Cannot get build version from Index metadata");
+ }
+ finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return version;
+ }
+
+ private void dropTables(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_META_INDEX);
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_PREFS_INDEX);
+ }
+
+ @Override
+ public void onOpen(SQLiteDatabase db) {
+ super.onOpen(db);
+
+ Log.i(TAG, "Using schema version: " + db.getVersion());
+
+ if (!Build.VERSION.INCREMENTAL.equals(getBuildVersion(db))) {
+ Log.w(TAG, "Index needs to be rebuilt as build-version is not the same");
+ // We need to drop the tables and recreate them
+ dropTables(db);
+ bootstrapDB(db);
+ } else {
+ Log.i(TAG, "Index is fine");
+ }
+ }
+}
diff --git a/src/com/android/settings/indexer/Indexable.java b/src/com/android/settings/indexer/Indexable.java
new file mode 100644
index 000000000..1b29b75e3
--- /dev/null
+++ b/src/com/android/settings/indexer/Indexable.java
@@ -0,0 +1,52 @@
+/*
+ * 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.indexer;
+
+import android.content.Context;
+
+import java.util.List;
+
+/**
+ * Interface for classes whose instances can provide data for indexing.
+ *
+ * Classes implementing the Indexable interface must have a static field called
+ * <code>INDEX_DATA_PROVIDER</code>, which is an object implementing the
+ * {@link Indexable.IndexDataProvider Indexable.IndexDataProvider} interface.
+ *
+ * See {@link IndexableRef} and {@link IndexableData}.
+ *
+ */
+public interface Indexable {
+
+ public interface IndexDataProvider {
+ /**
+ * Return a list of references for indexing. See {@link IndexableRef}
+ *
+ * @param context the context
+ * @return a list of {@link IndexableRef} references. Can be null.
+ */
+ List<IndexableRef> getRefsToIndex(Context context);
+
+ /**
+ * Return a list of raw data for indexing. See {@link IndexableData}
+ *
+ * @param context the context
+ * @return a list of {@link IndexableData} references. Can be null.
+ */
+ List<IndexableData> getRawDataToIndex(Context context);
+ }
+}
diff --git a/src/com/android/settings/indexer/IndexableData.java b/src/com/android/settings/indexer/IndexableData.java
new file mode 100644
index 000000000..ca388dede
--- /dev/null
+++ b/src/com/android/settings/indexer/IndexableData.java
@@ -0,0 +1,45 @@
+/*
+ * 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.indexer;
+
+import java.util.Locale;
+
+/**
+ * Indexable Data.
+ *
+ * This is the raw data used by the Indexer and should match its data model.
+ *
+ * See {@link Indexable} and {@link IndexableRef}.
+ */
+public class IndexableData {
+
+ public Locale locale;
+
+ public String title;
+ public String summary;
+ public String keywords;
+
+ public String intentAction;
+ public String intentTargetPackage;
+ public String intentTargetClass;
+
+ public String fragmentTitle;
+
+ public IndexableData() {
+ locale = Locale.getDefault();
+ }
+}
diff --git a/src/com/android/settings/indexer/IndexableRef.java b/src/com/android/settings/indexer/IndexableRef.java
new file mode 100644
index 000000000..c1ebcca63
--- /dev/null
+++ b/src/com/android/settings/indexer/IndexableRef.java
@@ -0,0 +1,46 @@
+/*
+ * 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.indexer;
+
+/**
+ * Indexable Reference.
+ *
+ * This class wraps a set of information representing data that can be indexed for a high
+ * level (see {@link android.preference.PreferenceScreen}).
+ *
+ * rank: is the rank of the data (basically its order in the list of Settings)
+ * xmlResId: is the resource Id of a PreferenceScreen xml file
+ * fragmentName: is the fragment class name associated with the data
+ * iconRedId: is the resource Id of an icon that represents the data
+ *
+ * See {@link Indexable} and {@link IndexableData}.
+ *
+ */
+public class IndexableRef {
+
+ public int rank;
+ public int xmlResId;
+ public String fragmentName;
+ public int iconResId;
+
+ public IndexableRef(int rank, int dataResId, String name, int iconResId) {
+ this.rank = rank;
+ this.xmlResId = dataResId;
+ this.fragmentName = name;
+ this.iconResId = iconResId;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
index 5693e209e..67e32ab56 100644
--- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
+++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnablerActivity.java
@@ -15,13 +15,11 @@
*/
package com.android.settings.inputmethod;
-import android.app.Fragment;
import android.content.Intent;
-import android.preference.PreferenceActivity;
-import com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment;
+import com.android.settings.SettingsActivity;
-public class InputMethodAndSubtypeEnablerActivity extends PreferenceActivity {
+public class InputMethodAndSubtypeEnablerActivity extends SettingsActivity {
@Override
public Intent getIntent() {
final Intent modIntent = new Intent(super.getIntent());
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index aa6430fc9..1d920de78 100644
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -18,6 +18,7 @@ package com.android.settings.inputmethod;
import com.android.internal.inputmethod.InputMethodUtils;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
@@ -31,8 +32,6 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -115,7 +114,7 @@ public class InputMethodPreference extends CheckBoxPreference {
@Override
public boolean onLongClick(View arg0) {
final Bundle bundle = new Bundle();
- bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
+ bundle.putString(android.provider.Settings.EXTRA_INPUT_METHOD_ID, imiId);
startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
0, bundle);
return true;
@@ -147,7 +146,7 @@ public class InputMethodPreference extends CheckBoxPreference {
@Override
public boolean onLongClick(View arg0) {
final Bundle bundle = new Bundle();
- bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
+ bundle.putString(android.provider.Settings.EXTRA_INPUT_METHOD_ID, imiId);
startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
0, bundle);
return true;
@@ -206,13 +205,12 @@ public class InputMethodPreference extends CheckBoxPreference {
public static boolean startFragment(
Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
- if (fragment.getActivity() instanceof PreferenceActivity) {
- PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
- preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
- requestCode);
+ if (fragment.getActivity() instanceof SettingsActivity) {
+ SettingsActivity sa = (SettingsActivity) fragment.getActivity();
+ sa.startPreferencePanel(fragmentClass, extras, 0, null, fragment, requestCode);
return true;
} else {
- Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
+ Log.w(TAG, "Parent isn't Settings, thus there's no way to launch the "
+ "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
+ ")");
return false;
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
index 451b36ea6..c77b2c9f6 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutDialogFragment.java
@@ -17,7 +17,6 @@
package com.android.settings.inputmethod;
import com.android.settings.R;
-import com.android.settings.Settings.KeyboardLayoutPickerActivity;
import android.app.AlertDialog;
import android.app.Activity;
@@ -29,7 +28,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
-import android.content.res.Resources;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
diff --git a/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java b/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
index 86c3e79d8..4f231cbbf 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryAddWordFragment.java
@@ -18,7 +18,6 @@ package com.android.settings.inputmethod;
import android.app.Fragment;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -29,6 +28,7 @@ import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.inputmethod.UserDictionaryAddWordContents.LocaleRenderer;
import java.util.ArrayList;
@@ -137,8 +137,8 @@ public class UserDictionaryAddWordFragment extends Fragment
final long id) {
final LocaleRenderer locale = (LocaleRenderer)parent.getItemAtPosition(pos);
if (locale.isMoreLanguages()) {
- PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
- preferenceActivity.startPreferenceFragment(new UserDictionaryLocalePicker(this), true);
+ SettingsActivity sa = (SettingsActivity)getActivity();
+ sa.startPreferenceFragment(new UserDictionaryLocalePicker(this), true);
} else {
mContents.updateLocale(locale.getLocaleString());
}
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 06a665056..b159e9913 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -22,21 +22,19 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.location.LocationManager;
import android.location.SettingInjectorService;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
-import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.widget.CompoundButton;
import android.widget.Switch;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import java.util.Collections;
import java.util.Comparator;
@@ -63,18 +61,57 @@ public class LocationSettings extends LocationSettingsBase
private PreferenceCategory mCategoryRecentLocationRequests;
/** Receives UPDATE_INTENT */
private BroadcastReceiver mReceiver;
+ private SettingsInjector injector;
public LocationSettings() {
mValidListener = false;
}
@Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final Activity activity = getActivity();
+
+ mSwitch = new Switch(activity);
+ final int padding = activity.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ mSwitch.setPaddingRelative(0, 0, padding, 0);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+
+ // Only show the master switch when we're not being used as Setup Wizard.
+ if (!activity.onIsHidingHeaders()) {
+ activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+ ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END));
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ if (!activity.onIsHidingHeaders()) {
+ activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(null);
+ }
+ }
+
+ @Override
public void onResume() {
super.onResume();
- mSwitch = new Switch(getActivity());
- mSwitch.setOnCheckedChangeListener(this);
mValidListener = true;
createPreferenceHierarchy();
+ mSwitch.setOnCheckedChangeListener(this);
}
@Override
@@ -103,7 +140,7 @@ public class LocationSettings extends LocationSettingsBase
}
private PreferenceScreen createPreferenceHierarchy() {
- final PreferenceActivity activity = (PreferenceActivity) getActivity();
+ final SettingsActivity activity = (SettingsActivity) getActivity();
PreferenceScreen root = getPreferenceScreen();
if (root != null) {
root.removeAll();
@@ -141,22 +178,6 @@ public class LocationSettings extends LocationSettingsBase
addLocationServices(activity, root);
- // Only show the master switch when we're not in multi-pane mode, and not being used as
- // Setup Wizard.
- if (activity.onIsHidingHeaders() || !activity.onIsMultiPane()) {
- final int padding = activity.getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- mSwitch.setPaddingRelative(0, 0, padding, 0);
- activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
- ActionBar.DISPLAY_SHOW_CUSTOM);
- activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
- ActionBar.LayoutParams.WRAP_CONTENT,
- ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END));
- }
-
- setHasOptionsMenu(true);
-
refreshLocationMode();
return root;
}
@@ -166,15 +187,12 @@ public class LocationSettings extends LocationSettingsBase
* category if there are no injected settings.
*
* Reloads the settings whenever receives
- * {@link SettingInjectorService#ACTION_INJECTED_SETTING_CHANGED}. As a safety measure,
- * also reloads on {@link LocationManager#MODE_CHANGED_ACTION} to ensure the settings are
- * up-to-date after mode changes even if an affected app doesn't send the setting changed
- * broadcast.
+ * {@link SettingInjectorService#ACTION_INJECTED_SETTING_CHANGED}.
*/
private void addLocationServices(Context context, PreferenceScreen root) {
PreferenceCategory categoryLocationServices =
(PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES);
- final SettingsInjector injector = new SettingsInjector(context);
+ injector = new SettingsInjector(context);
List<Preference> locationServices = injector.getInjectedSettings();
mReceiver = new BroadcastReceiver() {
@@ -189,7 +207,6 @@ public class LocationSettings extends LocationSettingsBase
IntentFilter filter = new IntentFilter();
filter.addAction(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
- filter.addAction(LocationManager.MODE_CHANGED_ACTION);
context.registerReceiver(mReceiver, filter);
if (locationServices.size() > 0) {
@@ -208,16 +225,16 @@ public class LocationSettings extends LocationSettingsBase
@Override
public void onModeChanged(int mode, boolean restricted) {
switch (mode) {
- case Settings.Secure.LOCATION_MODE_OFF:
+ case android.provider.Settings.Secure.LOCATION_MODE_OFF:
mLocationMode.setSummary(R.string.location_mode_location_off_title);
break;
- case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
+ case android.provider.Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
mLocationMode.setSummary(R.string.location_mode_sensors_only_title);
break;
- case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
+ case android.provider.Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
mLocationMode.setSummary(R.string.location_mode_battery_saving_title);
break;
- case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
+ case android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
mLocationMode.setSummary(R.string.location_mode_high_accuracy_title);
break;
default:
@@ -227,7 +244,7 @@ public class LocationSettings extends LocationSettingsBase
// Restricted user can't change the location mode, so disable the master switch. But in some
// corner cases, the location might still be enabled. In such case the master switch should
// be disabled but checked.
- boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF);
+ boolean enabled = (mode != android.provider.Settings.Secure.LOCATION_MODE_OFF);
mSwitch.setEnabled(!restricted);
mLocationMode.setEnabled(enabled && !restricted);
mCategoryRecentLocationRequests.setEnabled(enabled);
@@ -242,6 +259,9 @@ public class LocationSettings extends LocationSettingsBase
mSwitch.setOnCheckedChangeListener(this);
}
}
+ // As a safety measure, also reloads on location mode change to ensure the settings are
+ // up-to-date even if an affected app doesn't send the setting changed broadcast.
+ injector.reloadStatusMessages();
}
/**
@@ -250,9 +270,9 @@ public class LocationSettings extends LocationSettingsBase
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
- setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
+ setLocationMode(android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
} else {
- setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
+ setLocationMode(android.provider.Settings.Secure.LOCATION_MODE_OFF);
}
}
}
diff --git a/src/com/android/settings/location/LocationSettingsBase.java b/src/com/android/settings/location/LocationSettingsBase.java
index 86c2ee5e8..69fbd5c85 100644
--- a/src/com/android/settings/location/LocationSettingsBase.java
+++ b/src/com/android/settings/location/LocationSettingsBase.java
@@ -16,12 +16,11 @@
package com.android.settings.location;
-import android.app.LoaderManager.LoaderCallbacks;
+import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.CursorLoader;
import android.content.Intent;
-import android.content.Loader;
-import android.database.Cursor;
+import android.content.IntentFilter;
+import android.location.LocationManager;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.Settings;
@@ -33,8 +32,7 @@ import com.android.settings.SettingsPreferenceFragment;
* A base class that listens to location settings change and modifies location
* settings.
*/
-public abstract class LocationSettingsBase extends SettingsPreferenceFragment
- implements LoaderCallbacks<Cursor> {
+public abstract class LocationSettingsBase extends SettingsPreferenceFragment {
private static final String TAG = "LocationSettingsBase";
/** Broadcast intent action when the location mode is about to change. */
private static final String MODE_CHANGING_ACTION =
@@ -42,8 +40,8 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
private static final String NEW_MODE_KEY = "NEW_MODE";
- private static final int LOADER_ID_LOCATION_MODE = 1;
private int mCurrentMode;
+ private BroadcastReceiver mReceiver;
/**
* Whether the fragment is actively running.
@@ -53,17 +51,33 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- getLoaderManager().initLoader(LOADER_ID_LOCATION_MODE, null, this);
+ mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Received location mode change intent: " + intent);
+ }
+ refreshLocationMode();
+ }
+ };
}
@Override
public void onResume() {
super.onResume();
mActive = true;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(LocationManager.MODE_CHANGED_ACTION);
+ getActivity().registerReceiver(mReceiver, filter);
}
@Override
public void onPause() {
+ try {
+ getActivity().unregisterReceiver(mReceiver);
+ } catch (RuntimeException e) {
+ // Ignore exceptions caused by race condition
+ }
super.onPause();
mActive = false;
}
@@ -103,29 +117,10 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
int mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
mCurrentMode = mode;
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG, "Location mode has been changed");
+ }
onModeChanged(mode, isRestricted());
}
}
-
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- switch (id) {
- case LOADER_ID_LOCATION_MODE:
- return new CursorLoader(getActivity(), Settings.Secure.CONTENT_URI, null,
- "(" + Settings.System.NAME + "=?)",
- new String[] { Settings.Secure.LOCATION_MODE }, null);
- default:
- return null;
- }
- }
-
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- refreshLocationMode();
- }
-
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- // Nothing to do here.
- }
}
diff --git a/src/com/android/settings/location/RecentLocationApps.java b/src/com/android/settings/location/RecentLocationApps.java
index 57084348c..164f4e71e 100644
--- a/src/com/android/settings/location/RecentLocationApps.java
+++ b/src/com/android/settings/location/RecentLocationApps.java
@@ -26,10 +26,10 @@ import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.util.Log;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.applications.InstalledAppDetails;
import java.util.ArrayList;
@@ -44,10 +44,10 @@ public class RecentLocationApps {
private static final int RECENT_TIME_INTERVAL_MILLIS = 15 * 60 * 1000;
- private final PreferenceActivity mActivity;
+ private final SettingsActivity mActivity;
private final PackageManager mPackageManager;
- public RecentLocationApps(PreferenceActivity activity) {
+ public RecentLocationApps(SettingsActivity activity) {
mActivity = activity;
mPackageManager = activity.getPackageManager();
}
diff --git a/src/com/android/settings/location/SettingsInjector.java b/src/com/android/settings/location/SettingsInjector.java
index b9190802e..76b3103db 100644
--- a/src/com/android/settings/location/SettingsInjector.java
+++ b/src/com/android/settings/location/SettingsInjector.java
@@ -244,12 +244,12 @@ class SettingsInjector {
}
/**
- * Adds an injected setting to the root with status "Loading...".
+ * Adds an injected setting to the root.
*/
private Preference addServiceSetting(List<Preference> prefs, InjectedSetting info) {
Preference pref = new Preference(mContext);
pref.setTitle(info.title);
- pref.setSummary(R.string.location_loading_injected_setting);
+ pref.setSummary(null);
PackageManager pm = mContext.getPackageManager();
Drawable icon = pm.getDrawable(info.packageName, info.iconId, null);
pref.setIcon(icon);
@@ -425,12 +425,11 @@ class SettingsInjector {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
- String summary = bundle.getString(SettingInjectorService.SUMMARY_KEY);
boolean enabled = bundle.getBoolean(SettingInjectorService.ENABLED_KEY, true);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, setting + ": received " + msg + ", bundle: " + bundle);
}
- preference.setSummary(summary);
+ preference.setSummary(null);
preference.setEnabled(enabled);
mHandler.sendMessage(
mHandler.obtainMessage(WHAT_RECEIVED_STATUS, Setting.this));
diff --git a/src/com/android/settings/nfc/AndroidBeam.java b/src/com/android/settings/nfc/AndroidBeam.java
index 158ca78af..b3cd9c24e 100644
--- a/src/com/android/settings/nfc/AndroidBeam.java
+++ b/src/com/android/settings/nfc/AndroidBeam.java
@@ -21,16 +21,14 @@ import android.app.Activity;
import android.app.Fragment;
import android.nfc.NfcAdapter;
import android.os.Bundle;
-import android.os.Handler;
-import android.preference.PreferenceActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
-import android.widget.ImageView;
import android.widget.Switch;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
public class AndroidBeam extends Fragment
implements CompoundButton.OnCheckedChangeListener {
@@ -46,7 +44,7 @@ public class AndroidBeam extends Fragment
mActionBarSwitch = new Switch(activity);
- if (activity instanceof PreferenceActivity) {
+ if (activity instanceof SettingsActivity) {
final int padding = activity.getResources().getDimensionPixelSize(
R.dimen.action_bar_switch_padding);
mActionBarSwitch.setPaddingRelative(0, 0, padding, 0);
diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java
index f420a82a2..cbe70ae6f 100644
--- a/src/com/android/settings/print/PrintJobSettingsFragment.java
+++ b/src/com/android/settings/print/PrintJobSettingsFragment.java
@@ -80,7 +80,7 @@ public class PrintJobSettingsFragment extends SettingsPreferenceFragment {
Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(
ActivityManager.getCurrentUser());
- getActivity().setTitle(R.string.print_print_job);
+ getActivity().getActionBar().setTitle(R.string.print_print_job);
processArguments();
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index 326dd78c3..d5bfce20e 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -38,13 +38,11 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
-import android.preference.PreferenceActivity;
import android.print.PrintManager;
import android.print.PrinterDiscoverySession;
import android.print.PrinterDiscoverySession.OnPrintersChangeListener;
import android.print.PrinterId;
import android.print.PrinterInfo;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
@@ -56,7 +54,6 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
@@ -65,6 +62,7 @@ import android.widget.SearchView;
import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.print.PrintSettingsFragment.ToggleSwitch;
import com.android.settings.print.PrintSettingsFragment.ToggleSwitch.OnBeforeCheckedChangeListener;
@@ -73,6 +71,8 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+
+import android.widget.CompoundButton.OnCheckedChangeListener;
/**
* Fragment with print service settings.
*/
@@ -130,12 +130,14 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
private PrintersAdapter mPrintersAdapter;
+ // TODO: Showing sub-sub fragment does not handle the activity title
+ // so we do it but this is wrong. Do a real fix when there is time.
+ private CharSequence mOldActivityTitle;
+
private int mLastUnfilteredItemCount;
private boolean mServiceEnabled;
- private AnnounceFilterResult mAnnounceFilterResult;
-
@Override
public void onResume() {
super.onResume();
@@ -147,9 +149,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
@Override
public void onPause() {
mSettingsContentObserver.unregister(getContentResolver());
- if (mAnnounceFilterResult != null) {
- mAnnounceFilterResult.remove();
- }
super.onPause();
}
@@ -163,6 +162,9 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
@Override
public void onDestroyView() {
getActivity().getActionBar().setCustomView(null);
+ if (mOldActivityTitle != null) {
+ getActivity().getActionBar().setTitle(mOldActivityTitle);
+ }
mToggleSwitch.setOnBeforeCheckedChangeListener(null);
super.onDestroyView();
}
@@ -233,7 +235,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
if (emptyView == null) {
emptyView = getActivity().getLayoutInflater().inflate(
R.layout.empty_print_state, contentRoot, false);
- emptyView.setContentDescription(getString(R.string.print_service_disabled));
+ ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon);
+ iconView.setContentDescription(getString(R.string.print_service_disabled));
TextView textView = (TextView) emptyView.findViewById(R.id.message);
textView.setText(R.string.print_service_disabled);
contentRoot.addView(emptyView);
@@ -259,7 +262,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
if (emptyView == null) {
emptyView = getActivity().getLayoutInflater().inflate(
R.layout.empty_print_state, contentRoot, false);
- emptyView.setContentDescription(getString(R.string.print_no_printers_found));
+ ImageView iconView = (ImageView) emptyView.findViewById(R.id.icon);
+ iconView.setContentDescription(getString(R.string.print_no_printers_found));
TextView textView = (TextView) emptyView.findViewById(R.id.message);
textView.setText(R.string.print_no_printers_found);
contentRoot.addView(emptyView);
@@ -324,16 +328,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
mToggleSwitch.setCheckedInternal(enabled);
- // Title.
- PreferenceActivity activity = (PreferenceActivity) getActivity();
- if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
- // PreferenceActivity allows passing as an extra only title by its
- // resource id but we do not have the resource id for the print
- // service label. Therefore, we do it ourselves.
- String title = arguments.getString(PrintSettingsFragment.EXTRA_TITLE);
- getActivity().setTitle(title);
- }
-
// Settings title and intent.
String settingsTitle = arguments.getString(PrintSettingsFragment.EXTRA_SETTINGS_TITLE);
String settingsComponentName = arguments.getString(
@@ -467,8 +461,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
}
public void register(ContentResolver contentResolver) {
- contentResolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.ENABLED_PRINT_SERVICES), false, this);
+ contentResolver.registerContentObserver(android.provider.Settings.Secure.getUriFor(
+ android.provider.Settings.Secure.ENABLED_PRINT_SERVICES), false, this);
}
public void unregister(ContentResolver contentResolver) {
@@ -479,39 +473,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
public abstract void onChange(boolean selfChange, Uri uri);
}
- private final class AnnounceFilterResult implements Runnable {
- private static final int SEARCH_RESULT_ANNOUNCEMENT_DELAY = 1000; // 1 sec
-
- public void post() {
- remove();
- getListView().postDelayed(this, SEARCH_RESULT_ANNOUNCEMENT_DELAY);
- }
-
- public void remove() {
- getListView().removeCallbacks(this);
- }
-
- @Override
- public void run() {
- final int count = getListView().getAdapter().getCount();
- final String text;
- if (count <= 0) {
- text = getString(R.string.print_no_printers_found);
- } else {
- text = getActivity().getResources().getQuantityString(
- R.plurals.print_search_result_count_utterance, count, count);
- }
- getListView().announceForAccessibility(text);
- }
- }
-
- private void announceSearchResult() {
- if (mAnnounceFilterResult == null) {
- mAnnounceFilterResult = new AnnounceFilterResult();
- }
- mAnnounceFilterResult.post();
- }
-
private final class PrintersAdapter extends BaseAdapter
implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
private final Object mLock = new Object();
@@ -563,9 +524,7 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
@Override
@SuppressWarnings("unchecked")
protected void publishResults(CharSequence constraint, FilterResults results) {
- final boolean resultCountChanged;
synchronized (mLock) {
- final int oldPrinterCount = mFilteredPrinters.size();
mLastSearchString = constraint;
mFilteredPrinters.clear();
if (results == null) {
@@ -574,10 +533,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
List<PrinterInfo> printers = (List<PrinterInfo>) results.values;
mFilteredPrinters.addAll(printers);
}
- resultCountChanged = (oldPrinterCount != mFilteredPrinters.size());
- }
- if (resultCountChanged) {
- announceSearchResult();
}
notifyDataSetChanged();
}
diff --git a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
index 5654323c0..0081a1ed3 100644
--- a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
+++ b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
@@ -16,6 +16,7 @@
package com.android.settings.quicklaunch;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
@@ -27,7 +28,6 @@ import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings.Bookmarks;
@@ -40,6 +40,7 @@ import android.view.View;
import android.widget.AdapterView;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
import java.net.URISyntaxException;
@@ -49,7 +50,7 @@ import java.net.URISyntaxException;
* Shows a list of possible shortcuts, the current application each is bound to,
* and allows choosing a new bookmark for a shortcut.
*/
-public class QuickLaunchSettings extends PreferenceActivity implements
+public class QuickLaunchSettings extends SettingsPreferenceFragment implements
AdapterView.OnItemLongClickListener, DialogInterface.OnClickListener {
private static final String TAG = "QuickLaunchSettings";
@@ -91,7 +92,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
private static final String CLEAR_DIALOG_SHORTCUT = "CLEAR_DIALOG_SHORTCUT";
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.quick_launch_settings);
@@ -100,27 +101,35 @@ public class QuickLaunchSettings extends PreferenceActivity implements
mShortcutToPreference = new SparseArray<ShortcutPreference>();
mBookmarksObserver = new BookmarksObserver(mUiHandler);
initShortcutPreferences();
- mBookmarksCursor = managedQuery(Bookmarks.CONTENT_URI, sProjection, null, null);
+ mBookmarksCursor = getActivity().getContentResolver().query(Bookmarks.CONTENT_URI,
+ sProjection, null, null, null);
getListView().setOnItemLongClickListener(this);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
+ mBookmarksCursor = getActivity().getContentResolver().query(Bookmarks.CONTENT_URI,
+ sProjection, null, null, null);
getContentResolver().registerContentObserver(Bookmarks.CONTENT_URI, true,
mBookmarksObserver);
refreshShortcuts();
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
getContentResolver().unregisterContentObserver(mBookmarksObserver);
}
@Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
+ public void onStop() {
+ mBookmarksCursor.close();
+ }
+
+ @Override
+ public void onActivityCreated(Bundle state) {
+ super.onActivityCreated(state);
// Restore the clear dialog's info
mClearDialogBookmarkTitle = state.getString(CLEAR_DIALOG_BOOKMARK_TITLE);
@@ -128,7 +137,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Save the clear dialog's info
@@ -137,12 +146,12 @@ public class QuickLaunchSettings extends PreferenceActivity implements
}
@Override
- protected Dialog onCreateDialog(int id) {
+ public Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_CLEAR_SHORTCUT: {
// Create the dialog for clearing a shortcut
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.quick_launch_clear_dialog_title))
.setIconAttribute(android.R.attr.alertDialogIcon)
.setMessage(getString(R.string.quick_launch_clear_dialog_message,
@@ -156,18 +165,6 @@ public class QuickLaunchSettings extends PreferenceActivity implements
return super.onCreateDialog(id);
}
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- switch (id) {
-
- case DIALOG_CLEAR_SHORTCUT: {
- AlertDialog alertDialog = (AlertDialog) dialog;
- alertDialog.setMessage(getString(R.string.quick_launch_clear_dialog_message,
- mClearDialogShortcut, mClearDialogBookmarkTitle));
- }
- }
- }
-
private void showClearDialog(ShortcutPreference pref) {
if (!pref.hasBookmark()) return;
@@ -197,7 +194,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
// Open the screen to pick a bookmark for this shortcut
ShortcutPreference pref = (ShortcutPreference) preference;
- Intent intent = new Intent(this, BookmarkPicker.class);
+ Intent intent = new Intent(getActivity(), BookmarkPicker.class);
intent.putExtra(BookmarkPicker.EXTRA_SHORTCUT, pref.getShortcut());
startActivityForResult(intent, REQUEST_PICK_BOOKMARK);
@@ -214,8 +211,8 @@ public class QuickLaunchSettings extends PreferenceActivity implements
}
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != RESULT_OK) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != Activity.RESULT_OK) {
return;
}
@@ -253,7 +250,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
}
private ShortcutPreference createPreference(char shortcut) {
- ShortcutPreference pref = new ShortcutPreference(QuickLaunchSettings.this, shortcut);
+ ShortcutPreference pref = new ShortcutPreference(getActivity(), shortcut);
mShortcutGroup.addPreference(pref);
mShortcutToPreference.put(shortcut, pref);
return pref;
@@ -303,7 +300,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
if (shortcut == 0) continue;
ShortcutPreference pref = getOrCreatePreference(shortcut);
- CharSequence title = Bookmarks.getTitle(this, c);
+ CharSequence title = Bookmarks.getTitle(getActivity(), c);
/*
* The title retrieved from Bookmarks.getTitle() will be in
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index 3a3aec461..1d4fe7127 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
import static android.provider.Settings.Secure.TTS_DEFAULT_SYNTH;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.tts.TtsEnginePreference.RadioButtonGroupState;
@@ -30,9 +31,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
-import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
@@ -213,7 +212,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
// Set up the default rate.
try {
- mDefaultRate = Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
+ mDefaultRate = android.provider.Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
} catch (SettingNotFoundException e) {
// Default rate setting not found, initialize it
mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
@@ -223,12 +222,12 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
mCurrentEngine = mTts.getCurrentEngine();
- PreferenceActivity preferenceActivity = null;
- if (getActivity() instanceof PreferenceActivity) {
- preferenceActivity = (PreferenceActivity) getActivity();
+ SettingsActivity activity = null;
+ if (getActivity() instanceof SettingsActivity) {
+ activity = (SettingsActivity) getActivity();
} else {
throw new IllegalStateException("TextToSpeechSettings used outside a " +
- "PreferenceActivity");
+ "Settings");
}
mEnginePreferenceCategory.removeAll();
@@ -236,7 +235,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
List<EngineInfo> engines = mEnginesHelper.getEngines();
for (EngineInfo engine : engines) {
TtsEnginePreference enginePref = new TtsEnginePreference(getActivity(), engine,
- this, preferenceActivity);
+ this, activity);
mEnginePreferenceCategory.addPreference(enginePref);
}
@@ -434,7 +433,8 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
// Default rate
mDefaultRate = Integer.parseInt((String) objValue);
try {
- Settings.Secure.putInt(getContentResolver(), TTS_DEFAULT_RATE, mDefaultRate);
+ android.provider.Settings.Secure.putInt(getContentResolver(),
+ TTS_DEFAULT_RATE, mDefaultRate);
if (mTts != null) {
mTts.setSpeechRate(mDefaultRate / 100.0f);
}
@@ -577,7 +577,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
return;
}
- Settings.Secure.putString(getContentResolver(), TTS_DEFAULT_SYNTH, engine);
+ android.provider.Settings.Secure.putString(getContentResolver(), TTS_DEFAULT_SYNTH, engine);
mAvailableStrLocals = data.getStringArrayListExtra(
TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
diff --git a/src/com/android/settings/tts/TtsEnginePreference.java b/src/com/android/settings/tts/TtsEnginePreference.java
index 486fdf8f1..7e50c4739 100644
--- a/src/com/android/settings/tts/TtsEnginePreference.java
+++ b/src/com/android/settings/tts/TtsEnginePreference.java
@@ -22,7 +22,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.speech.tts.TextToSpeech.EngineInfo;
import android.util.Log;
import android.view.View;
@@ -33,6 +32,7 @@ import android.widget.RadioButton;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
@@ -63,7 +63,7 @@ public class TtsEnginePreference extends Preference {
* The preference activity that owns this preference. Required
* for instantiating the engine specific settings screen.
*/
- private final PreferenceActivity mPreferenceActivity;
+ private final SettingsActivity mSettingsActivity;
/**
* The engine information for the engine this preference represents.
@@ -95,12 +95,12 @@ public class TtsEnginePreference extends Preference {
};
public TtsEnginePreference(Context context, EngineInfo info, RadioButtonGroupState state,
- PreferenceActivity prefActivity) {
+ SettingsActivity prefActivity) {
super(context);
setLayoutResource(R.layout.preference_tts_engine);
mSharedState = state;
- mPreferenceActivity = prefActivity;
+ mSettingsActivity = prefActivity;
mEngineInfo = info;
mPreventRadioButtonCallbacks = false;
@@ -156,10 +156,10 @@ public class TtsEnginePreference extends Preference {
}
// Note that we use this instead of the (easier to use)
- // PreferenceActivity.startPreferenceFragment because the
+ // SettingsActivity.startPreferenceFragment because the
// title will not be updated correctly in the fragment
// breadcrumb since it isn't inflated from the XML layout.
- mPreferenceActivity.startPreferencePanel(
+ mSettingsActivity.startPreferencePanel(
TtsEngineSettingsFragment.class.getName(),
args, 0, mEngineInfo.label, null, 0);
}
diff --git a/src/com/android/settings/tts/TtsEngineSettingsFragment.java b/src/com/android/settings/tts/TtsEngineSettingsFragment.java
index bb5ac7ae4..25ec1fdca 100644
--- a/src/com/android/settings/tts/TtsEngineSettingsFragment.java
+++ b/src/com/android/settings/tts/TtsEngineSettingsFragment.java
@@ -158,12 +158,22 @@ public class TtsEngineSettingsFragment extends SettingsPreferenceFragment implem
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
- mVoiceDataDetails = data;
- updateVoiceDetails();
+ if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+ updateVoiceDetails(data);
+ } else {
+ Log.e(TAG, "CheckVoiceData activity failed");
+ }
}
}
- private void updateVoiceDetails() {
+ private void updateVoiceDetails(Intent data) {
+ if (data == null){
+ Log.e(TAG, "Engine failed voice data integrity check (null return)" +
+ mTts.getCurrentEngine());
+ return;
+ }
+ mVoiceDataDetails = data;
+
if (DBG) Log.d(TAG, "Parsing voice data details, data: " + mVoiceDataDetails.toUri(0));
final ArrayList<String> available = mVoiceDataDetails.getStringArrayListExtra(
diff --git a/src/com/android/settings/users/RestrictionUtils.java b/src/com/android/settings/users/RestrictionUtils.java
index 3ee6d510f..e8d46e9f6 100644
--- a/src/com/android/settings/users/RestrictionUtils.java
+++ b/src/com/android/settings/users/RestrictionUtils.java
@@ -84,8 +84,8 @@ public class RestrictionUtils {
userRestrictions.putBoolean(entry.getKey(), !entry.getSelectedState());
if (entry.getKey().equals(UserManager.DISALLOW_SHARE_LOCATION)
&& !entry.getSelectedState()) {
- Secure.putStringForUser(context.getContentResolver(),
- Secure.LOCATION_PROVIDERS_ALLOWED, "", user.getIdentifier());
+ Secure.putIntForUser(context.getContentResolver(),
+ Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF, user.getIdentifier());
}
}
um.setUserRestrictions(userRestrictions, user);
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index bbae37d03..1a60e782b 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -47,7 +47,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
@@ -67,6 +66,7 @@ import com.android.settings.OwnerInfoSettings;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.SelectableEditTextPreference;
+import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
public class UserSettings extends RestrictedSettingsFragment
@@ -345,8 +345,8 @@ public class UserSettings extends RestrictedSettingsFragment
UserHandle user = new UserHandle(userId);
mUserManager.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
mUserManager.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user);
- Secure.putStringForUser(getContentResolver(),
- Secure.LOCATION_PROVIDERS_ALLOWED, "", userId);
+ Secure.putIntForUser(getContentResolver(),
+ Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF, userId);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
UserSettings.USER_DRAWABLES[
userId % UserSettings.USER_DRAWABLES.length]);
@@ -377,7 +377,7 @@ public class UserSettings extends RestrictedSettingsFragment
Bundle extras = new Bundle();
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
RestrictedProfileSettings.class.getName(),
extras, R.string.user_restrictions_title, null,
null, 0);
@@ -390,7 +390,7 @@ public class UserSettings extends RestrictedSettingsFragment
int titleResId = info.id == UserHandle.USER_OWNER ? R.string.owner_info_settings_title
: (info.isRestricted() ? R.string.profile_info_settings_title
: R.string.user_info_settings_title);
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ ((SettingsActivity) getActivity()).startPreferencePanel(
OwnerInfoSettings.class.getName(),
extras, titleResId, null, null, 0);
}
diff --git a/src/com/android/settings/wfd/WifiDisplaySettings.java b/src/com/android/settings/wfd/WifiDisplaySettings.java
index d7f4708ac..c3f22a79a 100755
--- a/src/com/android/settings/wfd/WifiDisplaySettings.java
+++ b/src/com/android/settings/wfd/WifiDisplaySettings.java
@@ -42,15 +42,12 @@ import android.os.Looper;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.text.Html;
import android.util.Slog;
import android.util.TypedValue;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -59,14 +56,11 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
-import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.app.MediaRouteDialogPresenter;
-import com.android.settings.ProgressCategory;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
diff --git a/src/com/android/settings/wifi/AccessPoint.java b/src/com/android/settings/wifi/AccessPoint.java
index c4d1f7c65..81706c909 100644
--- a/src/com/android/settings/wifi/AccessPoint.java
+++ b/src/com/android/settings/wifi/AccessPoint.java
@@ -60,7 +60,7 @@ class AccessPoint extends Preference {
String ssid;
String bssid;
int security;
- int networkId;
+ int networkId = -1;
boolean wpsAvailable = false;
PskType pskType = PskType.UNKNOWN;
@@ -68,7 +68,7 @@ class AccessPoint extends Preference {
private WifiConfiguration mConfig;
/* package */ScanResult mScanResult;
- private int mRssi;
+ private int mRssi = Integer.MAX_VALUE;
private WifiInfo mInfo;
private DetailedState mState;
@@ -187,7 +187,6 @@ class AccessPoint extends Preference {
bssid = config.BSSID;
security = getSecurity(config);
networkId = config.networkId;
- mRssi = Integer.MAX_VALUE;
mConfig = config;
}
@@ -198,7 +197,6 @@ class AccessPoint extends Preference {
wpsAvailable = security != SECURITY_EAP && result.capabilities.contains("WPS");
if (security == SECURITY_PSK)
pskType = getPskType(result);
- networkId = -1;
mRssi = result.level;
mScanResult = result;
}
@@ -276,6 +274,7 @@ class AccessPoint extends Preference {
if (security == SECURITY_PSK) {
pskType = getPskType(result);
}
+ mScanResult = result;
refresh();
return true;
}
diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java
index bbcd50d5a..4accb040b 100644
--- a/src/com/android/settings/wifi/AdvancedWifiSettings.java
+++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.net.wifi.WifiWatchdogStateMachine;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
@@ -112,7 +111,7 @@ public class AdvancedWifiSettings extends SettingsPreferenceFragment
} else {
poorNetworkDetection.setChecked(Global.getInt(getContentResolver(),
Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
- WifiWatchdogStateMachine.DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED ?
+ WifiManager.DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED ?
1 : 0) == 1);
}
}
diff --git a/src/com/android/settings/wifi/WifiPickerActivity.java b/src/com/android/settings/wifi/WifiPickerActivity.java
index e1e7c51c1..deef8fa1a 100644
--- a/src/com/android/settings/wifi/WifiPickerActivity.java
+++ b/src/com/android/settings/wifi/WifiPickerActivity.java
@@ -16,7 +16,6 @@
package com.android.settings.wifi;
import com.android.settings.ButtonBarHandler;
-import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.wifi.p2p.WifiP2pSettings;
import android.app.Fragment;
@@ -54,8 +53,8 @@ public class WifiPickerActivity extends PreferenceActivity implements ButtonBarH
/**
* Almost dead copy of
- * {@link PreferenceActivity#startWithFragment(String, Bundle, Fragment, int)}, except
- * this has additional codes for button bar handling.
+ * {@link PreferenceActivity#startWithFragment(String, Bundle, Fragment, int)}, except this has
+ * additional codes for button bar handling.
*/
@Override
public void startWithFragment(String fragmentName, Bundle args,
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 1caf58bcd..d6e68a320 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -19,8 +19,13 @@ package com.android.settings.wifi;
import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
+import android.preference.PreferenceActivity;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
+import com.android.settings.SettingsActivity;
+import com.android.settings.indexer.Indexable;
+import com.android.settings.indexer.IndexableData;
+import com.android.settings.indexer.IndexableRef;
import com.android.settings.wifi.p2p.WifiP2pSettings;
import android.app.ActionBar;
@@ -49,9 +54,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
@@ -90,7 +93,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* and menus.
*/
public class WifiSettings extends RestrictedSettingsFragment
- implements DialogInterface.OnClickListener {
+ implements DialogInterface.OnClickListener, Indexable {
private static final String TAG = "WifiSettings";
private static final int MENU_ID_WPS_PBC = Menu.FIRST;
private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
@@ -172,6 +175,8 @@ public class WifiSettings extends RestrictedSettingsFragment
// the action bar uses a different set of controls for Setup Wizard
private boolean mSetupWizardMode;
+ private Switch mSwitch;
+
/* End of "used in Wifi Setup context" */
public WifiSettings() {
@@ -383,35 +388,12 @@ public class WifiSettings extends RestrictedSettingsFragment
if (mSetupWizardMode) {
getView().setSystemUiVisibility(
-// View.STATUS_BAR_DISABLE_BACK |
View.STATUS_BAR_DISABLE_HOME |
View.STATUS_BAR_DISABLE_RECENT |
View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS |
View.STATUS_BAR_DISABLE_CLOCK);
}
- // On/off switch is hidden for Setup Wizard
- if (!mSetupWizardMode) {
- Switch actionBarSwitch = new Switch(activity);
-
- if (activity instanceof PreferenceActivity) {
- PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
- if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) {
- final int padding = activity.getResources().getDimensionPixelSize(
- R.dimen.action_bar_switch_padding);
- actionBarSwitch.setPaddingRelative(0, 0, padding, 0);
- activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
- ActionBar.DISPLAY_SHOW_CUSTOM);
- activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams(
- ActionBar.LayoutParams.WRAP_CONTENT,
- ActionBar.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_VERTICAL | Gravity.END));
- }
- }
-
- mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);
- }
-
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
getListView().setEmptyView(mEmptyView);
@@ -422,6 +404,59 @@ public class WifiSettings extends RestrictedSettingsFragment
}
@Override
+ public void onStart() {
+ super.onStart();
+
+ // On/off switch is hidden for Setup Wizard
+ if (!mSetupWizardMode) {
+ final Activity activity = getActivity();
+
+ mSwitch = new Switch(activity);
+ boolean addSwitch = false;
+
+ if (activity instanceof SettingsActivity) {
+ SettingsActivity sa = (SettingsActivity) activity;
+ addSwitch = !sa.onIsHidingHeaders();
+ } else if (activity instanceof WifiPickerActivity) {
+ PreferenceActivity pa = (PreferenceActivity) activity;
+ addSwitch = pa.onIsHidingHeaders();
+ }
+
+ if (addSwitch) {
+ final int padding = activity.getResources().getDimensionPixelSize(
+ R.dimen.action_bar_switch_padding);
+ mSwitch.setPaddingRelative(0, 0, padding, 0);
+ activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
+ ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ ActionBar.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_VERTICAL | Gravity.END));
+ }
+
+ mWifiEnabler = new WifiEnabler(activity, mSwitch);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ Activity activity = getActivity();
+ boolean onIsHidingHeaders = true;
+ if (activity instanceof SettingsActivity){
+ SettingsActivity sa = (SettingsActivity) activity;
+ onIsHidingHeaders = sa.onIsHidingHeaders();
+ } else if (activity instanceof PreferenceActivity) {
+ PreferenceActivity pa = (PreferenceActivity) activity;
+ onIsHidingHeaders = pa.onIsHidingHeaders();
+ }
+ if (!onIsHidingHeaders) {
+ activity.getActionBar().setDisplayOptions(0, ActionBar.DISPLAY_SHOW_CUSTOM);
+ activity.getActionBar().setCustomView(null);
+ }
+ }
+
+ @Override
public void onResume() {
super.onResume();
if (mWifiEnabler != null) {
@@ -512,8 +547,8 @@ public class WifiSettings extends RestrictedSettingsFragment
showDialog(WPS_PBC_DIALOG_ID);
return true;
case MENU_ID_P2P:
- if (getActivity() instanceof PreferenceActivity) {
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ if (getActivity() instanceof SettingsActivity) {
+ ((SettingsActivity) getActivity()).startPreferencePanel(
WifiP2pSettings.class.getCanonicalName(),
null,
R.string.wifi_p2p_settings_title, null,
@@ -536,8 +571,8 @@ public class WifiSettings extends RestrictedSettingsFragment
}
return true;
case MENU_ID_ADVANCED:
- if (getActivity() instanceof PreferenceActivity) {
- ((PreferenceActivity) getActivity()).startPreferencePanel(
+ if (getActivity() instanceof SettingsActivity) {
+ ((SettingsActivity) getActivity()).startPreferencePanel(
AdvancedWifiSettings.class.getCanonicalName(),
null,
R.string.wifi_advanced_titlebar, null,
@@ -716,7 +751,8 @@ public class WifiSettings extends RestrictedSettingsFragment
switch (wifiState) {
case WifiManager.WIFI_STATE_ENABLED:
// AccessPoints are automatically sorted with TreeSet.
- final Collection<AccessPoint> accessPoints = constructAccessPoints();
+ final Collection<AccessPoint> accessPoints =
+ constructAccessPoints(getActivity(), mWifiManager, mLastInfo, mLastState);
getPreferenceScreen().removeAll();
if(accessPoints.size() == 0) {
addMessagePreference(R.string.wifi_empty_list_wifi_on);
@@ -743,12 +779,12 @@ public class WifiSettings extends RestrictedSettingsFragment
private void setOffMessage() {
if (mEmptyView != null) {
mEmptyView.setText(R.string.wifi_empty_list_wifi_off);
- if (Settings.Global.getInt(getActivity().getContentResolver(),
- Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1) {
+ if (android.provider.Settings.Global.getInt(getActivity().getContentResolver(),
+ android.provider.Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1) {
mEmptyView.append("\n\n");
int resId;
- if (Settings.Secure.isLocationProviderEnabled(getActivity().getContentResolver(),
- LocationManager.NETWORK_PROVIDER)) {
+ if (android.provider.Settings.Secure.isLocationProviderEnabled(
+ getActivity().getContentResolver(), LocationManager.NETWORK_PROVIDER)) {
resId = R.string.wifi_scan_notify_text_location_on;
} else {
resId = R.string.wifi_scan_notify_text_location_off;
@@ -766,23 +802,26 @@ public class WifiSettings extends RestrictedSettingsFragment
}
/** Returns sorted list of access points */
- private List<AccessPoint> constructAccessPoints() {
+ private static List<AccessPoint> constructAccessPoints(Context context,
+ WifiManager wifiManager, WifiInfo lastInfo, DetailedState lastState) {
ArrayList<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
/** Lookup table to more quickly update AccessPoints by only considering objects with the
* correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */
Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
- final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ final List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs) {
- AccessPoint accessPoint = new AccessPoint(getActivity(), config);
- accessPoint.update(mLastInfo, mLastState);
+ AccessPoint accessPoint = new AccessPoint(context, config);
+ if (lastInfo != null && lastState != null) {
+ accessPoint.update(lastInfo, lastState);
+ }
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid, accessPoint);
}
}
- final List<ScanResult> results = mWifiManager.getScanResults();
+ final List<ScanResult> results = wifiManager.getScanResults();
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
@@ -797,7 +836,7 @@ public class WifiSettings extends RestrictedSettingsFragment
found = true;
}
if (!found) {
- AccessPoint accessPoint = new AccessPoint(getActivity(), result);
+ AccessPoint accessPoint = new AccessPoint(context, result);
accessPoints.add(accessPoint);
apMap.put(accessPoint.ssid, accessPoint);
}
@@ -810,7 +849,7 @@ public class WifiSettings extends RestrictedSettingsFragment
}
/** A restricted multimap for use in constructAccessPoints */
- private class Multimap<K,V> {
+ private static class Multimap<K,V> {
private final HashMap<K,List<V>> store = new HashMap<K,List<V>>();
/** retrieve a non-null list of values with key K */
List<V> getAll(K key) {
@@ -1109,10 +1148,10 @@ public class WifiSettings extends RestrictedSettingsFragment
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
- final Resources resources = getContext().getResources();
- float titleHeight = resources.getFraction(R.dimen.setup_title_height, 1, 1);
- float sideMargin = resources.getFraction(R.dimen.setup_border_width, 1, 1);
- int bottom = resources.getDimensionPixelSize(R.dimen.setup_margin_bottom);
+ final Resources res = getContext().getResources();
+ float titleHeight = res.getFraction(R.dimen.setup_title_height, 1, 1);
+ float sideMargin = res.getFraction(R.dimen.setup_border_width, 1, 1);
+ int bottom = res.getDimensionPixelSize(R.dimen.setup_margin_bottom);
setPaddingRelative(
(int) (parentWidth * sideMargin),
0,
@@ -1126,4 +1165,39 @@ public class WifiSettings extends RestrictedSettingsFragment
}
}
+ public static final Indexable.IndexDataProvider INDEX_DATA_PROVIDER =
+ new Indexable.IndexDataProvider() {
+ @Override
+ public List<IndexableRef> getRefsToIndex(Context context) {
+ return null;
+ }
+
+ @Override
+ public List<IndexableData> getRawDataToIndex(Context context) {
+ final List<IndexableData> result = new ArrayList<IndexableData>();
+ final Resources res = context.getResources();
+
+ // Add fragment title
+ IndexableData data = new IndexableData();
+ data.title = res.getString(R.string.wifi_settings);
+ data.fragmentTitle = res.getString(R.string.wifi_settings);
+ result.add(data);
+
+ // Add available Wi-Fi access points
+ WifiManager wifiManager =
+ (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ final Collection<AccessPoint> accessPoints =
+ constructAccessPoints(context, wifiManager, null, null);
+ for (AccessPoint accessPoint : accessPoints) {
+ // We are indexing only the saved Wi-Fi networks.
+ if (accessPoint.getConfig() == null) continue;
+ data = new IndexableData();
+ data.title = accessPoint.getTitle().toString();
+ data.fragmentTitle = res.getString(R.string.wifi_settings);
+ result.add(data);
+ }
+
+ return result;
+ }
+ };
}
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index cd1d72171..879ebf835 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -16,7 +16,6 @@
package com.android.settings.wifi.p2p;
-import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -34,40 +33,32 @@ import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pGroupList;
import android.net.wifi.p2p.WifiP2pManager;
-import android.net.wifi.p2p.WifiP2pManager.GroupInfoListener;
+import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.net.wifi.p2p.WifiP2pManager.PersistentGroupInfoListener;
import android.net.wifi.WpsInfo;
import android.os.Bundle;
-import android.os.Handler;
import android.os.SystemProperties;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.text.InputFilter;
import android.text.TextUtils;
import android.util.Log;
-import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
-import android.widget.Switch;
import android.widget.Toast;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Collection;
-
/*
* Displays Wi-fi p2p settings UI
*/
public class WifiP2pSettings extends SettingsPreferenceFragment
- implements PersistentGroupInfoListener, GroupInfoListener {
+ implements PersistentGroupInfoListener, PeerListListener {
private static final String TAG = "WifiP2pSettings";
private static final boolean DBG = false;
@@ -89,7 +80,6 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
private boolean mWifiP2pEnabled;
private boolean mWifiP2pSearching;
private int mConnectedDevices;
- private WifiP2pGroup mConnectedGroup;
private boolean mLastGroupFormed = false;
private PreferenceGroup mPeersGroup;
@@ -129,9 +119,6 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
WifiP2pManager.EXTRA_NETWORK_INFO);
WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra(
WifiP2pManager.EXTRA_WIFI_P2P_INFO);
- if (mWifiP2pManager != null) {
- mWifiP2pManager.requestGroupInfo(mChannel, WifiP2pSettings.this);
- }
if (networkInfo.isConnected()) {
if (DBG) Log.d(TAG, "Connected");
} else if (mLastGroupFormed != true) {
@@ -298,16 +285,20 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
final PreferenceScreen preferenceScreen = getPreferenceScreen();
preferenceScreen.removeAll();
-
preferenceScreen.setOrderingAsAdded(true);
+
mThisDevicePref = new Preference(getActivity());
+ mThisDevicePref.setPersistent(false);
+ mThisDevicePref.setSelectable(false);
preferenceScreen.addPreference(mThisDevicePref);
mPeersGroup = new PreferenceCategory(getActivity());
mPeersGroup.setTitle(R.string.wifi_p2p_peer_devices);
+ preferenceScreen.addPreference(mPeersGroup);
mPersistentGroup = new PreferenceCategory(getActivity());
mPersistentGroup.setTitle(R.string.wifi_p2p_remembered_groups);
+ preferenceScreen.addPreference(mPersistentGroup);
super.onActivityCreated(savedInstanceState);
}
@@ -316,12 +307,17 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
public void onResume() {
super.onResume();
getActivity().registerReceiver(mReceiver, mIntentFilter);
+ if (mWifiP2pManager != null) {
+ mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this);
+ }
}
@Override
public void onPause() {
super.onPause();
- mWifiP2pManager.stopPeerDiscovery(mChannel, null);
+ if (mWifiP2pManager != null) {
+ mWifiP2pManager.stopPeerDiscovery(mChannel, null);
+ }
getActivity().unregisterReceiver(mReceiver);
}
@@ -506,6 +502,7 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices);
}
+ @Override
public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) {
mPersistentGroup.removeAll();
@@ -528,27 +525,18 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
}
}
- public void onGroupInfoAvailable(WifiP2pGroup group) {
- if (DBG) Log.d(TAG, " group " + group);
- mConnectedGroup = group;
- updateDevicePref();
+ @Override
+ public void onPeersAvailable(WifiP2pDeviceList peers) {
+ if (DBG) Log.d(TAG, "Requested peers are available");
+ mPeers = peers;
+ handlePeersChanged();
}
private void handleP2pStateChanged() {
updateSearchMenu(false);
- if (mWifiP2pEnabled) {
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- preferenceScreen.removeAll();
-
- preferenceScreen.setOrderingAsAdded(true);
- preferenceScreen.addPreference(mThisDevicePref);
-
- mPeersGroup.setEnabled(true);
- preferenceScreen.addPreference(mPeersGroup);
-
- mPersistentGroup.setEnabled(true);
- preferenceScreen.addPreference(mPersistentGroup);
- }
+ mThisDevicePref.setEnabled(mWifiP2pEnabled);
+ mPeersGroup.setEnabled(mWifiP2pEnabled);
+ mPersistentGroup.setEnabled(mWifiP2pEnabled);
}
private void updateSearchMenu(boolean searching) {
@@ -576,10 +564,6 @@ public class WifiP2pSettings extends SettingsPreferenceFragment
} else {
mThisDevicePref.setTitle(mThisDevice.deviceName);
}
-
- mThisDevicePref.setPersistent(false);
- mThisDevicePref.setEnabled(true);
- mThisDevicePref.setSelectable(false);
}
}
}