summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings')
-rw-r--r--src/com/android/settings/AppHeader.java1
-rw-r--r--src/com/android/settings/ChooseLockGeneric.java50
-rw-r--r--src/com/android/settings/ChooseLockPassword.java1
-rw-r--r--src/com/android/settings/DataUsageSummary.java54
-rw-r--r--src/com/android/settings/DevelopmentSettings.java5
-rw-r--r--src/com/android/settings/FingerprintEnroll.java73
-rw-r--r--src/com/android/settings/FingerprintSettings.java235
-rw-r--r--src/com/android/settings/SecuritySettings.java15
-rw-r--r--src/com/android/settings/Settings.java1
-rw-r--r--src/com/android/settings/SettingsActivity.java4
-rw-r--r--src/com/android/settings/SetupChooseLockGeneric.java2
-rw-r--r--src/com/android/settings/Utils.java21
-rw-r--r--src/com/android/settings/WifiCallingSettings.java275
-rw-r--r--src/com/android/settings/WirelessSettings.java17
-rw-r--r--src/com/android/settings/applications/AppInfoBase.java30
-rw-r--r--src/com/android/settings/applications/AppLaunchSettings.java6
-rw-r--r--src/com/android/settings/applications/AppPermissionSettings.java1
-rw-r--r--src/com/android/settings/applications/AppStorageSettings.java8
-rw-r--r--src/com/android/settings/applications/ApplicationsState.java176
-rw-r--r--src/com/android/settings/applications/HeaderPreference.java1
-rwxr-xr-xsrc/com/android/settings/applications/InstalledAppDetails.java98
-rw-r--r--src/com/android/settings/applications/ManageApplications.java60
-rw-r--r--src/com/android/settings/bluetooth/BluetoothDevicePreference.java56
-rw-r--r--src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java2
-rw-r--r--src/com/android/settings/bluetooth/DockService.java1
-rw-r--r--src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java7
-rw-r--r--src/com/android/settings/notification/NotificationSettings.java2
-rw-r--r--src/com/android/settings/search/Ranking.java2
-rw-r--r--src/com/android/settings/search/SearchIndexableResources.java8
-rw-r--r--src/com/android/settings/users/UserSettings.java9
-rw-r--r--src/com/android/settings/wifi/WifiApDialog.java45
-rw-r--r--src/com/android/settings/wifi/WifiSettingsForSetupWizard.java4
32 files changed, 1062 insertions, 208 deletions
diff --git a/src/com/android/settings/AppHeader.java b/src/com/android/settings/AppHeader.java
index 5cd126a..cd76e80 100644
--- a/src/com/android/settings/AppHeader.java
+++ b/src/com/android/settings/AppHeader.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.settings;
import android.app.Activity;
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index bfb328d..aeb3827 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -35,6 +35,8 @@ import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.security.KeyStore;
+import android.service.fingerprint.FingerprintManager;
+import android.service.fingerprint.FingerprintManagerReceiver;
import android.util.EventLog;
import android.util.Log;
import android.util.MutableBoolean;
@@ -72,26 +74,24 @@ public class ChooseLockGeneric extends SettingsActivity {
}
public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
+ private static final String TAG = "ChooseLockGenericFragment";
private static final int MIN_PASSWORD_LENGTH = 4;
- private static final String KEY_UNLOCK_BACKUP_INFO = "unlock_backup_info";
private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
- private static final int CONFIRM_EXISTING_REQUEST = 100;
- private static final int ENABLE_ENCRYPTION_REQUEST = 102;
- private static final int CHOOSE_LOCK_REQUEST = 103;
private static final String PASSWORD_CONFIRMED = "password_confirmed";
-
private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
- private static final String TAG = "ChooseLockGenericFragment";
public static final String MINIMUM_QUALITY_KEY = "minimum_quality";
+ public static final String HIDE_DISABLED_PREFS = "hide_disabled_prefs";
public static final String ENCRYPT_REQUESTED_QUALITY = "encrypt_requested_quality";
public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
- private static final boolean ALWAY_SHOW_TUTORIAL = true;
+ private static final int CONFIRM_EXISTING_REQUEST = 100;
+ private static final int ENABLE_ENCRYPTION_REQUEST = 101;
+ private static final int CHOOSE_LOCK_REQUEST = 102;
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private DevicePolicyManager mDPM;
@@ -102,11 +102,14 @@ public class ChooseLockGeneric extends SettingsActivity {
private boolean mEncryptionRequestDisabled;
private boolean mRequirePassword;
private LockPatternUtils mLockPatternUtils;
+ private FingerprintManager mFingerprintManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mFingerprintManager =
+ (FingerprintManager) getActivity().getSystemService(Context.FINGERPRINT_SERVICE);
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mKeyStore = KeyStore.getInstance();
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this.getActivity());
@@ -219,12 +222,14 @@ public class ChooseLockGeneric extends SettingsActivity {
// If caller didn't specify password quality, show UI and allow the user to choose.
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
quality = upgradeQuality(quality);
+ final boolean hideDisabledPrefs = intent.getBooleanExtra(
+ HIDE_DISABLED_PREFS, false);
final PreferenceScreen prefScreen = getPreferenceScreen();
if (prefScreen != null) {
prefScreen.removeAll();
}
addPreferencesFromResource(R.xml.security_settings_picker);
- disableUnusablePreferences(quality);
+ disableUnusablePreferences(quality, hideDisabledPrefs);
updatePreferenceSummaryIfNeeded();
} else {
updateUnlockMethodAndFinish(quality, false);
@@ -261,9 +266,11 @@ public class ChooseLockGeneric extends SettingsActivity {
* implementation is in disableUnusablePreferenceImpl.
*
* @param quality the requested quality.
+ * @param hideDisabledPrefs if false preferences show why they were disabled; otherwise
+ * they're not shown at all.
*/
- protected void disableUnusablePreferences(final int quality) {
- disableUnusablePreferencesImpl(quality, false /* hideDisabled */);
+ protected void disableUnusablePreferences(final int quality, boolean hideDisabledPrefs) {
+ disableUnusablePreferencesImpl(quality, hideDisabledPrefs);
}
/***
@@ -391,13 +398,36 @@ public class ChooseLockGeneric extends SettingsActivity {
} else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
mChooseLockSettingsHelper.utils().clearLock();
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);
+ removeAllFingerprintTemplates();
getActivity().setResult(Activity.RESULT_OK);
finish();
} else {
+ removeAllFingerprintTemplates();
finish();
}
}
+ // TODO: This is only required because we used to enforce clients have a listener,
+ // which is no longer required in the new API. Remove when that happens.
+ FingerprintManagerReceiver mReceiver = new FingerprintManagerReceiver() {
+ public void onRemoved(int fingerprintId) {
+ Log.v(TAG, "onRemoved(id=" + fingerprintId + ")");
+ }
+ };
+
+ private void removeAllFingerprintTemplates() {
+ if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
+ mFingerprintManager.startListening(mReceiver);
+ mFingerprintManager.remove(0 /* all fingerprint templates */);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mFingerprintManager.stopListening();
+ }
+
@Override
protected int getHelpResource() {
return R.string.help_url_choose_lockscreen;
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index b85daa7..0a0aebd 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -432,7 +432,6 @@ public class ChooseLockPassword extends SettingsActivity {
} else if (mUiStage == Stage.NeedToConfirm) {
if (mFirstPin.equals(pin)) {
boolean wasSecureBefore = mLockPatternUtils.isSecure();
- mLockPatternUtils.clearLock();
final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
mLockPatternUtils.setCredentialRequiredToDecrypt(required);
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index cba0879..3ab1d23 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -62,6 +62,7 @@ import android.content.Intent;
import android.content.Loader;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -120,6 +121,7 @@ import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TabHost;
+import android.widget.Toast;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabContentFactory;
import android.widget.TabHost.TabSpec;
@@ -142,7 +144,6 @@ import com.android.settings.sim.SimSettings;
import com.android.settings.widget.ChartDataUsageView;
import com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
import com.android.settings.widget.ChartNetworkSeriesView;
-
import com.google.android.collect.Lists;
import libcore.util.Objects;
@@ -191,6 +192,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
"data_usage_disable_mobile_limit";
private static final String DATA_USAGE_CYCLE_KEY = "data_usage_cycle";
+ public static final String EXTRA_SHOW_APP_IMMEDIATE_PKG = "showAppImmediatePkg";
+
private static final int LOADER_CHART_DATA = 2;
private static final int LOADER_SUMMARY = 3;
@@ -281,6 +284,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private UidDetailProvider mUidDetailProvider;
+ // Indicates request to show app immediately rather than list.
+ private String mShowAppImmediatePkg;
+
/**
* Local cache of data enabled for subId, used to work around delays.
*/
@@ -332,6 +338,13 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mShowEthernet = true;
}
+ mUidDetailProvider = new UidDetailProvider(context);
+
+ Bundle arguments = getArguments();
+ if (arguments != null) {
+ mShowAppImmediatePkg = arguments.getString(EXTRA_SHOW_APP_IMMEDIATE_PKG);
+ }
+
setHasOptionsMenu(true);
}
@@ -342,7 +355,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
final Context context = inflater.getContext();
final View view = inflater.inflate(R.layout.data_usage_summary, container, false);
- mUidDetailProvider = new UidDetailProvider(context);
mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
mTabsContainer = (ViewGroup) view.findViewById(R.id.tabs_container);
@@ -448,9 +460,34 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
mListView.setOnItemClickListener(mListListener);
mListView.setAdapter(mAdapter);
+ showRequestedAppIfNeeded();
+
return view;
}
+ private void showRequestedAppIfNeeded() {
+ if (mShowAppImmediatePkg == null) {
+ return;
+ }
+ try {
+ int uid = getActivity().getPackageManager().getPackageUid(mShowAppImmediatePkg,
+ UserHandle.myUserId());
+ AppItem app = new AppItem(uid);
+ app.addUid(uid);
+
+ final UidDetail detail = mUidDetailProvider.getUidDetail(app.key, true);
+ // When we are going straight to an app then we are coming from App Info and want
+ // a header at the top.
+ AppHeader.createAppHeader(getActivity(), detail.icon, detail.label, null);
+ AppDetailsFragment.show(DataUsageSummary.this, app, detail.label, false);
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Could not find " + mShowAppImmediatePkg, e);
+ Toast.makeText(getActivity(), getString(R.string.unknown_app), Toast.LENGTH_LONG)
+ .show();
+ getActivity().finish();
+ }
+ }
+
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
@@ -639,6 +676,10 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
* only be assigned after initial layout is complete.
*/
private void ensureLayoutTransitions() {
+ if (mShowAppImmediatePkg != null) {
+ // If we are skipping right to showing an app, we don't care about transitions.
+ return;
+ }
// skip when already setup
if (mChart.getLayoutTransition() != null) return;
@@ -1887,6 +1928,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
private static final String EXTRA_APP = "app";
public static void show(DataUsageSummary parent, AppItem app, CharSequence label) {
+ show(parent, app, label, true);
+ }
+
+ public static void show(DataUsageSummary parent, AppItem app, CharSequence label,
+ boolean addToBack) {
if (!parent.isAdded()) return;
final Bundle args = new Bundle();
@@ -1897,7 +1943,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
fragment.setTargetFragment(parent, 0);
final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
ft.add(fragment, TAG_APP_DETAILS);
- ft.addToBackStack(TAG_APP_DETAILS);
+ if (addToBack) {
+ ft.addToBackStack(TAG_APP_DETAILS);
+ }
ft.setBreadCrumbTitle(
parent.getResources().getString(R.string.data_usage_app_summary_title));
ft.commitAllowingStateLoss();
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index a4002ab..b5b33f4 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -728,7 +728,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
return !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
}
- private boolean showEnableMultiWindowPreference() {
+ private static boolean showEnableMultiWindowPreference() {
return !"user".equals(Build.TYPE);
}
@@ -1781,6 +1781,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
if (!showEnableOemUnlockPreference()) {
keys.add(ENABLE_OEM_UNLOCK);
}
+ if (!showEnableMultiWindowPreference()) {
+ keys.add(ENABLE_MULTI_WINDOW_KEY);
+ }
return keys;
}
};
diff --git a/src/com/android/settings/FingerprintEnroll.java b/src/com/android/settings/FingerprintEnroll.java
index 24f479e..865fcdc 100644
--- a/src/com/android/settings/FingerprintEnroll.java
+++ b/src/com/android/settings/FingerprintEnroll.java
@@ -21,10 +21,12 @@ import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.os.Bundle;
import android.os.PowerManager;
@@ -80,11 +82,13 @@ public class FingerprintEnroll extends SettingsActivity {
}
public static class FingerprintEnrollFragment extends Fragment implements View.OnClickListener {
+ private static final int PROGRESS_BAR_MAX = 10000;
private static final String TAG = "FingerprintEnroll";
private static final boolean DEBUG = true;
private static final int CONFIRM_REQUEST = 101;
private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102;
private static final long ENROLL_TIMEOUT = 300*1000;
+ private static final int FINISH_DELAY = 250;
private PowerManager mPowerManager;
private FingerprintManager mFingerprintManager;
@@ -98,6 +102,15 @@ public class FingerprintEnroll extends SettingsActivity {
private ProgressBar mProgressBar;
private ImageView mFingerprintAnimator;
private ObjectAnimator mProgressAnim;
+
+ // Give the user a chance to see progress completed before jumping to the next stage.
+ Runnable mDelayedFinishRunnable = new Runnable() {
+ @Override
+ public void run() {
+ updateStage(Stage.EnrollingFinish);
+ }
+ };
+
private final AnimatorListener mProgressAnimationListener = new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@@ -107,8 +120,8 @@ public class FingerprintEnroll extends SettingsActivity {
@Override
public void onAnimationEnd(Animator animation) {
- if (mProgressBar.getProgress() >= 100) {
- updateStage(Stage.EnrollingFinish);
+ if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
+ mContentView.postDelayed(mDelayedFinishRunnable, FINISH_DELAY);
}
}
@@ -133,12 +146,17 @@ public class FingerprintEnroll extends SettingsActivity {
R.id.fingerprint_enroll_button_next
};
- private static final int VIEWS_ENROLL_START[] = {
+ private static final int VIEWS_ENROLL_FIND_SENSOR[] = {
R.id.fingerprint_sensor_location,
- R.id.fingerprint_progress_bar
+ R.id.fingerprint_enroll_button_area,
+ R.id.fingerprint_enroll_button_next
};
- private static final int VIEWS_ENROLL_PROGRESS[] = {
+ private static final int VIEWS_ENROLL_START[] = {
+ R.id.fingerprint_animator,
+ };
+
+ private static final int VIEWS_ENROLL_REPEAT[] = {
R.id.fingerprint_animator,
R.id.fingerprint_progress_bar
};
@@ -149,17 +167,21 @@ public class FingerprintEnroll extends SettingsActivity {
R.id.fingerprint_enroll_button_add,
R.id.fingerprint_enroll_button_next
};
+ private static final boolean ALWAYS_SHOW_FIND_SCREEN = true;
- enum Stage {
- EnrollingOnboarding(R.string.security_settings_fingerprint_enroll_onboard_title,
+ private enum Stage {
+ EnrollingOnboard(R.string.security_settings_fingerprint_enroll_onboard_title,
R.string.security_settings_fingerprint_enroll_onboard_message,
VIEWS_ENROLL_ONBOARD),
+ EnrollingFindSensor(R.string.security_settings_fingerprint_enroll_find_sensor_title,
+ R.string.security_settings_fingerprint_enroll_find_sensor_message,
+ VIEWS_ENROLL_FIND_SENSOR),
EnrollingStart(R.string.security_settings_fingerprint_enroll_start_title,
R.string.security_settings_fingerprint_enroll_start_message,
VIEWS_ENROLL_START),
EnrollingRepeat(R.string.security_settings_fingerprint_enroll_repeat_title,
R.string.security_settings_fingerprint_enroll_repeat_message,
- VIEWS_ENROLL_PROGRESS),
+ VIEWS_ENROLL_REPEAT),
EnrollingFinish(R.string.security_settings_fingerprint_enroll_finish_title,
R.string.security_settings_fingerprint_enroll_finish_message,
VIEWS_ENROLL_FINISH);
@@ -196,22 +218,29 @@ public class FingerprintEnroll extends SettingsActivity {
}
private void startFingerprintAnimator() {
- AnimationDrawable drawable = (AnimationDrawable) mFingerprintAnimator.getDrawable();
- drawable.start();
+ final Drawable d = mFingerprintAnimator.getDrawable();
+ if (d instanceof AnimationDrawable) {
+ ((AnimationDrawable) d).start();
+ }
}
private void stopFingerprintAnimator() {
- AnimationDrawable drawable = (AnimationDrawable) mFingerprintAnimator.getDrawable();
- drawable.stop();
- drawable.setLevel(0);
+ final Drawable d = mFingerprintAnimator.getDrawable();
+ if (d instanceof AnimationDrawable) {
+ final AnimationDrawable drawable = (AnimationDrawable) d;
+ drawable.stop();
+ drawable.setLevel(0);
+ }
}
private void onStageChanged(Stage stage) {
// Update state
switch (stage) {
- case EnrollingOnboarding:
+ case EnrollingOnboard: // pass through
+ case EnrollingFindSensor:
mEnrollmentSteps = -1;
mEnrolling = false;
+ mFingerprintManager.stopListening();
break;
case EnrollingStart:
@@ -288,7 +317,7 @@ public class FingerprintEnroll extends SettingsActivity {
}
if (remaining >= 0) {
int progress = Math.max(0, mEnrollmentSteps + 1 - remaining);
- updateProgress(100*progress / (mEnrollmentSteps + 1));
+ updateProgress(PROGRESS_BAR_MAX * progress / (mEnrollmentSteps + 1));
// Treat fingerprint like a touch event
mPowerManager.userActivity(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER,
@@ -371,7 +400,7 @@ public class FingerprintEnroll extends SettingsActivity {
if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
if (resultCode == RESULT_FINISHED) {
// The lock pin/pattern/password was set. Start enrolling!
- updateStage(Stage.EnrollingStart);
+ updateStage(Stage.EnrollingFindSensor);
}
}
}
@@ -401,7 +430,10 @@ public class FingerprintEnroll extends SettingsActivity {
LockPatternUtils utils = new LockPatternUtils(activity);
if (!utils.isSecure()) {
// Device doesn't have any security. Set that up first.
- updateStage(Stage.EnrollingOnboarding);
+ updateStage(Stage.EnrollingOnboard);
+ } else if (ALWAYS_SHOW_FIND_SCREEN
+ || mFingerprintManager.getEnrolledFingerprints().size() == 0) {
+ updateStage(Stage.EnrollingFindSensor);
} else {
updateStage(Stage.EnrollingStart);
}
@@ -415,8 +447,10 @@ public class FingerprintEnroll extends SettingsActivity {
updateStage(Stage.EnrollingStart);
break;
case R.id.fingerprint_enroll_button_next:
- if (mStage == Stage.EnrollingOnboarding) {
+ if (mStage == Stage.EnrollingOnboard) {
launchChooseLock();
+ } else if (mStage == Stage.EnrollingFindSensor) {
+ updateStage(Stage.EnrollingStart);
} else if (mStage == Stage.EnrollingFinish) {
getActivity().finish();
} else {
@@ -429,6 +463,9 @@ public class FingerprintEnroll extends SettingsActivity {
private void launchChooseLock() {
Intent intent = new Intent();
intent.setClassName("com.android.settings", ChooseLockGeneric.class.getName());
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
}
}
diff --git a/src/com/android/settings/FingerprintSettings.java b/src/com/android/settings/FingerprintSettings.java
new file mode 100644
index 0000000..f91fcfa
--- /dev/null
+++ b/src/com/android/settings/FingerprintSettings.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2015 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.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.service.fingerprint.FingerprintManager;
+import android.service.fingerprint.FingerprintManagerReceiver;
+import android.service.fingerprint.FingerprintManager.FingerprintItem;
+import android.util.Log;
+import android.widget.EditText;
+
+import com.android.settings.search.Indexable;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Settings screen for fingerprints
+ */
+public class FingerprintSettings extends SettingsActivity {
+
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, FingerprintSettingsFragment.class.getName());
+ return modIntent;
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ if (FingerprintSettingsFragment.class.getName().equals(fragmentName)) return true;
+ return false;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ CharSequence msg = getText(R.string.security_settings_fingerprint_preference_title);
+ setTitle(msg);
+ }
+
+ public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
+ implements OnPreferenceChangeListener, Indexable {
+ private static final String TAG = "FingerprintSettings";
+ private static final String KEY_FINGERPRINT_ITEM = "key_fingerprint_item";
+ private static final String KEY_USAGE_CATEGORY = "fingerprint_usage_category";
+ private static final String KEY_FINGERPRINT_ADD = "key_fingerprint_add";
+ private static final String KEY_MANAGE_CATEGORY = "fingerprint_manage_category";
+ private static final String KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE =
+ "fingerprint_enable_keyguard_toggle";
+
+ private static final int ADD_FINGERPRINT_REQUEST = 10;
+
+ private static final boolean ENABLE_USAGE_CATEGORY = false;
+
+ private FingerprintManager mFingerprintManager;
+ private HashMap<Preference, FingerprintItem> mFingerprintMap
+ = new HashMap<Preference, FingerprintManager.FingerprintItem>();
+ private EditText mDialogTextField;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mFingerprintManager = (FingerprintManager) getActivity().getSystemService(
+ Context.FINGERPRINT_SERVICE);
+ mFingerprintManager.startListening(new FingerprintManagerReceiver() {
+ @Override
+ public void onRemoved(int fingerprintId) {
+ Log.v(TAG, "Fingerprint template " + fingerprintId + " removed");
+ // TODO: this is a bit wasteful; just remove the fingerprint id item
+ createPreferenceHierarchy();
+ }
+ @Override
+ public void onProcessed(int fingerprintId) {
+ Log.v(TAG, "Fingerprint " + fingerprintId + " detected");
+ }
+ });
+ }
+
+ /**
+ * Important!
+ *
+ * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
+ * logic or adding/removing preferences here.
+ */
+ private PreferenceScreen createPreferenceHierarchy() {
+ PreferenceScreen root = getPreferenceScreen();
+ if (root != null) {
+ root.removeAll();
+ }
+ addPreferencesFromResource(R.xml.security_settings_fingerprint);
+ root = getPreferenceScreen();
+
+ // Fingerprint items
+ PreferenceGroup manageCategory = (PreferenceGroup) root.findPreference(
+ KEY_MANAGE_CATEGORY);
+ if (manageCategory != null) {
+ addFingerprintItemPreferences(manageCategory);
+ }
+
+ // Fingerprint usage options
+ PreferenceGroup usageCategory = (PreferenceGroup) root.findPreference(
+ KEY_USAGE_CATEGORY);
+ if (usageCategory != null) {
+ Preference toggle = root.findPreference(KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE);
+ toggle.setOnPreferenceChangeListener(this);
+ if (!ENABLE_USAGE_CATEGORY) {
+ root.removePreference(usageCategory);
+ } else {
+ toggle.setOnPreferenceChangeListener(this);
+ }
+ }
+
+ return root;
+ }
+
+ private void addFingerprintItemPreferences(PreferenceGroup manageFingerprintCategory) {
+ manageFingerprintCategory.removeAll();
+ List<FingerprintItem> items = mFingerprintManager.getEnrolledFingerprints();
+ final int fingerprintCount = items.size();
+ mFingerprintMap.clear();
+ for (int i = 0; i < fingerprintCount; i++) {
+ Preference pref = new Preference(manageFingerprintCategory.getContext());
+ pref.setKey(KEY_FINGERPRINT_ITEM);
+ FingerprintItem item = items.get(i);
+ pref.setTitle(item.name);
+ manageFingerprintCategory.addPreference(pref);
+ pref.setOnPreferenceChangeListener(this);
+ mFingerprintMap.put(pref, item);
+ }
+ Preference addPreference = new Preference(manageFingerprintCategory.getContext());
+ addPreference.setKey(KEY_FINGERPRINT_ADD);
+ addPreference.setTitle(R.string.fingerprint_add_title);
+ manageFingerprintCategory.addPreference(addPreference);
+ addPreference.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Make sure we reload the preference hierarchy since fingerprints may be added,
+ // deleted or renamed.
+ createPreferenceHierarchy();
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference pref) {
+ final String key = pref.getKey();
+ if (KEY_FINGERPRINT_ADD.equals(key)) {
+ Intent intent = new Intent();
+ intent.setClassName("com.android.settings", FingerprintEnroll.class.getName());
+ startActivityForResult(intent, ADD_FINGERPRINT_REQUEST);
+ } else if (KEY_FINGERPRINT_ITEM.equals(key)) {
+ final FingerprintItem item = mFingerprintMap.get(pref);
+ showRenameDeleteDialog(item.name, pref, item.id);
+ return super.onPreferenceTreeClick(preferenceScreen, pref);
+ }
+ return true;
+ }
+
+ private void showRenameDeleteDialog(final CharSequence name, Preference pref,
+ final int fpId) {
+ final Activity activity = getActivity();
+ AlertDialog dialog = new AlertDialog.Builder(activity)
+ .setView(R.layout.fingerprint_rename_dialog)
+ .setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String newName = mDialogTextField.getText().toString();
+ if (!newName.equals(name)) {
+ Log.v(TAG, "Would rename " + name + " to " + newName);
+ mFingerprintManager.rename(fpId, newName);
+ }
+ dialog.dismiss();
+ }
+ })
+ .setNegativeButton(R.string.security_settings_fingerprint_enroll_dialog_delete,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.v(TAG, "Removing fpId " + fpId);
+ mFingerprintManager.remove(fpId);
+ dialog.dismiss();
+ }
+ })
+ .create();
+ dialog.show();
+ mDialogTextField = (EditText) dialog.findViewById(R.id.fingerprint_rename_field);
+ mDialogTextField.setText(name);
+ mDialogTextField.selectAll();
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ boolean result = true;
+ final String key = preference.getKey();
+ if (KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE.equals(key)) {
+ // TODO
+ } else {
+ Log.v(TAG, "Unknown key:" + key);
+ }
+ return result;
+ }
+
+ @Override
+ protected int getHelpResource() {
+ return R.string.help_url_security;
+ }
+ }
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 95826e4..053e7f0 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -67,8 +67,9 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
*/
public class SecuritySettings extends SettingsPreferenceFragment
implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable {
+
+ private static final String TAG = "SecuritySettings";
private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
- static final String TAG = "SecuritySettings";
private static final Intent TRUST_AGENT_INTENT =
new Intent(TrustAgentService.SERVICE_INTERFACE);
@@ -81,6 +82,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
private static final String KEY_ADVANCED_SECURITY = "advanced_security";
private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
+ private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
@@ -337,21 +339,22 @@ public class SecuritySettings extends SettingsPreferenceFragment
return;
}
Preference fingerprintPreference = new Preference(securityCategory.getContext());
- fingerprintPreference.setKey(KEY_TRUST_AGENT);
+ fingerprintPreference.setKey(KEY_FINGERPRINT_SETTINGS);
fingerprintPreference.setTitle(R.string.security_settings_fingerprint_preference_title);
Intent intent = new Intent();
List<FingerprintItem> items = fpm.getEnrolledFingerprints();
int fingerprintCount = items.size();
+ final String clazz;
if (fingerprintCount > 0) {
fingerprintPreference.setSummary(getResources().getQuantityString(
R.plurals.security_settings_fingerprint_preference_summary,
fingerprintCount, fingerprintCount));
- // TODO: Launch fingerprintSettings instead...
- intent.setClassName("com.android.settings", FingerprintEnroll.class.getName());
+ clazz = FingerprintSettings.class.getName();
} else {
- // No fingerprints registered, launch directly into fingerprint enrollment wizard
- intent.setClassName("com.android.settings", FingerprintEnroll.class.getName());
+ // No fingerprints registered, launch directly into enrollment wizard
+ clazz = FingerprintEnroll.class.getName();
}
+ intent.setClassName("com.android.settings", clazz);
fingerprintPreference.setIntent(intent);
securityCategory.addPreference(fingerprintPreference);
}
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index d41c387..b16fe81 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -100,5 +100,6 @@ public class Settings extends SettingsActivity {
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 8eacc32..db080c6 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -112,6 +112,7 @@ import com.android.settings.wifi.AdvancedWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
import com.android.settings.wifi.p2p.WifiP2pSettings;
+import com.android.settings.WifiCallingSettings;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -301,7 +302,8 @@ public class SettingsActivity extends Activity
NotificationAppList.class.getName(),
AppNotificationSettings.class.getName(),
OtherSoundSettings.class.getName(),
- ApnSettings.class.getName()
+ ApnSettings.class.getName(),
+ WifiCallingSettings.class.getName()
};
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index 94ff8d6..f29f08a 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -110,7 +110,7 @@ public class SetupChooseLockGeneric extends ChooseLockGeneric
* @param quality the requested quality.
*/
@Override
- protected void disableUnusablePreferences(final int quality) {
+ protected void disableUnusablePreferences(final int quality, boolean hideDisabled) {
// At this part of the flow, the user has already indicated they want to add a pin,
// pattern or password, so don't show "None" or "Slide". We disable them here and set
// the HIDE_DISABLED flag to true to hide them. This only happens for setup wizard.
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 5a2618e..16037c5 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -67,6 +67,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -133,6 +134,8 @@ public final class Utils {
private static final int SECONDS_PER_HOUR = 60 * 60;
private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+ private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<Bitmap>();
+
/**
* Finds a matching activity for a preference's intent. If a matching
* activity is not found, it will remove the preference.
@@ -1083,4 +1086,22 @@ public final class Utils {
return (sm.getStorageBytesUntilLow(context.getFilesDir()) < 0);
}
+
+ /**
+ * Returns a default user icon (as a {@link Bitmap}) for the given user.
+ *
+ * Note that for guest users, you should pass in {@code UserHandle.USER_NULL}.
+ * @param userId the user id or {@code UserHandle.USER_NULL} for a non-user specific icon
+ */
+ public static Bitmap getDefaultUserIconAsBitmap(int userId) {
+ Bitmap bitmap = null;
+ // Try finding the corresponding bitmap in the dark bitmap cache
+ bitmap = sDarkDefaultUserBitmapCache.get(userId);
+ if (bitmap == null) {
+ bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(userId, false));
+ // Save it to cache
+ sDarkDefaultUserBitmapCache.put(userId, bitmap);
+ }
+ return bitmap;
+ }
}
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
new file mode 100644
index 0000000..dacdc7b
--- /dev/null
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 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.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.SwitchPreference;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.widget.Switch;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.settings.widget.SwitchBar;
+
+/**
+ * "Wi-Fi Calling settings" screen. This preference screen lets you
+ * enable/disable Wi-Fi Calling, change mode, enable/disable
+ * handover while on roaming.
+ */
+public class WifiCallingSettings extends SettingsPreferenceFragment
+ implements SwitchBar.OnSwitchChangeListener,
+ Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "WifiCallingSettings";
+
+ //String keys for preference lookup
+ private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
+ private static final String BUTTON_WFC_ROAM = "wifi_calling_roam";
+
+ //UI objects
+ private SwitchBar mSwitchBar;
+ private Switch mSwitch;
+ private ListPreference mButtonWfcMode;
+ private SwitchPreference mButtonWfcRoam;
+
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ /*
+ * Enable/disable controls when in/out of a call and depending on
+ * TTY mode and TTY support over VoLTE.
+ * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
+ * java.lang.String)
+ */
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+ boolean isNonTtyOrTtyOnVolteEnabled = ImsManager
+ .isNonTtyOrTtyOnVolteEnabled(activity);
+ final SwitchBar switchBar = activity.getSwitchBar();
+ boolean isWfcEnabled = switchBar.getSwitch().isChecked()
+ && isNonTtyOrTtyOnVolteEnabled;
+
+ switchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
+ && isNonTtyOrTtyOnVolteEnabled);
+
+ Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
+ int wfcMode = ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY;
+ if (pref != null) {
+ pref.setEnabled(isWfcEnabled
+ && (state == TelephonyManager.CALL_STATE_IDLE));
+ ListPreference prefWfcMode = (ListPreference) pref;
+ wfcMode = Integer.valueOf(prefWfcMode.getValue()).intValue();
+ }
+ pref = getPreferenceScreen().findPreference(BUTTON_WFC_ROAM);
+ if (pref != null) {
+ pref.setEnabled(isWfcEnabled
+ && (wfcMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY)
+ && (state == TelephonyManager.CALL_STATE_IDLE));
+ }
+ }
+ };
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+
+ mSwitchBar = activity.getSwitchBar();
+ mSwitch = mSwitchBar.getSwitch();
+ mSwitchBar.show();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ mSwitchBar.hide();
+ }
+
+ private void showAlert(Intent intent) {
+ Context context = getActivity();
+
+ CharSequence title = intent.getCharSequenceExtra(ImsPhone.EXTRA_KEY_ALERT_TITLE);
+ CharSequence message = intent.getCharSequenceExtra(ImsPhone.EXTRA_KEY_ALERT_MESSAGE);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setMessage(message)
+ .setTitle(title)
+ .setIcon(android.R.drawable.stat_sys_warning)
+ .setPositiveButton(android.R.string.ok, null);
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ private IntentFilter mIntentFilter;
+
+ private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(ImsPhone.REGISTRATION_ERROR)) {
+ // If this fragment is active then we are immediately
+ // showing alert on screen. There is no need to add
+ // notification in this case.
+ //
+ // In order to communicate to ImsPhone that it should
+ // not show notification, we are changing result code here.
+ setResultCode(Activity.RESULT_CANCELED);
+
+ showAlert(intent);
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.wifi_calling_settings);
+
+ mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
+ mButtonWfcMode.setOnPreferenceChangeListener(this);
+
+ mButtonWfcRoam = (SwitchPreference) findPreference(BUTTON_WFC_ROAM);
+ mButtonWfcRoam.setOnPreferenceChangeListener(this);
+
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(ImsPhone.REGISTRATION_ERROR);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ final Context context = getActivity();
+
+ if (ImsManager.isWfcEnabledByPlatform(context)) {
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+ mSwitchBar.addOnSwitchChangeListener(this);
+ }
+
+ // NOTE: Buttons will be enabled/disabled in mPhoneStateListener
+ boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context)
+ && ImsManager.isNonTtyOrTtyOnVolteEnabled(context);
+ mSwitch.setChecked(wfcEnabled);
+
+ int wfcMode = ImsManager.getWfcMode(context);
+ mButtonWfcMode.setValue(Integer.toString(wfcMode));
+ mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode));
+
+ mButtonWfcRoam.setChecked(wfcEnabled
+ && (wfcMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY)
+ && ImsManager.isWfcRoamingEnabledByUser(context));
+
+ context.registerReceiver(mIntentReceiver, mIntentFilter);
+
+ Intent intent = getActivity().getIntent();
+ if (intent.getBooleanExtra(ImsPhone.EXTRA_KEY_ALERT_SHOW, false)) {
+ showAlert(intent);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ final Context context = getActivity();
+
+ if (ImsManager.isWfcEnabledByPlatform(getActivity())) {
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ }
+
+ context.unregisterReceiver(mIntentReceiver);
+ }
+
+ /**
+ * Listens to the state change of the switch.
+ */
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ final Context context = getActivity();
+
+ ImsManager.setWfcSetting(context, isChecked);
+
+ int wfcMode = ImsManager.getWfcMode(context);
+ mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode));
+ mButtonWfcMode.setEnabled(isChecked);
+ boolean wfcHandoffEnabled = (wfcMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY);
+ mButtonWfcRoam.setEnabled(isChecked && wfcHandoffEnabled);
+ mButtonWfcRoam.setChecked(isChecked && wfcHandoffEnabled
+ && ImsManager.isWfcRoamingEnabledByUser(context));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final Context context = getActivity();
+ if (preference == mButtonWfcMode) {
+ mButtonWfcMode.setValue((String) newValue);
+ int buttonMode = Integer.valueOf((String) newValue);
+ int currentMode = ImsManager.getWfcMode(context);
+ if (buttonMode != currentMode) {
+ ImsManager.setWfcMode(context, buttonMode);
+ mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode));
+ }
+ boolean wfcHandoffEnabled =
+ (buttonMode != ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY);
+ mButtonWfcRoam.setEnabled(wfcHandoffEnabled);
+ mButtonWfcRoam.setChecked(wfcHandoffEnabled &&
+ ImsManager.isWfcRoamingEnabledByUser(context));
+ } else if (preference == mButtonWfcRoam) {
+ SwitchPreference wfcRoamPref = (SwitchPreference) preference;
+ wfcRoamPref.setChecked(!wfcRoamPref.isChecked());
+ ImsManager.setWfcRoamingSetting(context, wfcRoamPref.isChecked());
+ }
+ return true;
+ }
+
+ static int getWfcModeSummary(Context context, int wfcMode) {
+ int resId = R.string.wifi_calling_off_summary;
+ if (ImsManager.isWfcEnabledByUser(context)) {
+ switch (wfcMode) {
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+ resId = R.string.wfc_mode_wifi_only_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+ resId = R.string.wfc_mode_cellular_preferred_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+ resId = R.string.wfc_mode_wifi_preferred_summary;
+ break;
+ default:
+ Log.e(TAG, "Unexpected WFC mode value: " + wfcMode);
+ }
+ }
+ return resId;
+ }
+}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 0bd6b29..71cd322 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -47,6 +47,8 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.internal.telephony.TelephonyIntents;
@@ -54,6 +56,7 @@ import com.android.internal.telephony.TelephonyProperties;
import com.android.settings.nfc.NfcEnabler;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
+import com.android.settings.WifiCallingSettings;
import java.util.ArrayList;
import java.util.Arrays;
@@ -76,6 +79,7 @@ public class WirelessSettings extends SettingsPreferenceFragment
private static final String KEY_SMS_APPLICATION = "sms_application";
private static final String KEY_TOGGLE_NSD = "toggle_nsd"; //network service discovery
private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
+ private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
public static final String EXIT_ECM_RESULT = "exit_ecm_result";
public static final int REQUEST_CODE_EXIT_ECM = 1;
@@ -95,6 +99,7 @@ public class WirelessSettings extends SettingsPreferenceFragment
private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage";
private AppListPreference mSmsApplicationPreference;
+ private PreferenceScreen mButtonWfc;
/**
* Invoked on each preference click in this hierarchy, overrides
@@ -272,6 +277,12 @@ public class WirelessSettings extends SettingsPreferenceFragment
initSmsApplicationSetting();
}
+ if (ImsManager.isWfcEnabledByPlatform(activity)) {
+ mButtonWfc = (PreferenceScreen) findPreference(KEY_WFC_SETTINGS);
+ } else {
+ removePreference(KEY_WFC_SETTINGS);
+ }
+
// Remove NSD checkbox by default
getPreferenceScreen().removePreference(nsd);
//mNsdEnabler = new NsdEnabler(activity, nsd);
@@ -413,6 +424,12 @@ public class WirelessSettings extends SettingsPreferenceFragment
if (mNsdEnabler != null) {
mNsdEnabler.resume();
}
+
+ final Context context = getActivity();
+ if (ImsManager.isWfcEnabledByPlatform(context)) {
+ mButtonWfc.setSummary(WifiCallingSettings.getWfcModeSummary(
+ context, ImsManager.getWfcMode(context)));
+ }
}
@Override
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 2203a21..28f2925 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.settings.applications;
import android.app.Activity;
@@ -29,6 +30,7 @@ import android.hardware.usb.IUsbManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceFragment;
import android.util.Log;
@@ -52,6 +54,7 @@ public abstract class AppInfoBase extends PreferenceFragment
private ApplicationsState.Session mSession;
protected ApplicationsState.AppEntry mAppEntry;
protected PackageInfo mPackageInfo;
+ protected int mUserId;
protected String mPackageName;
protected IUsbManager mUsbManager;
@@ -114,7 +117,8 @@ public abstract class AppInfoBase extends PreferenceFragment
mPackageName = intent.getData().getSchemeSpecificPart();
}
}
- mAppEntry = mState.getEntry(mPackageName);
+ mUserId = UserHandle.myUserId();
+ mAppEntry = mState.getEntry(mPackageName, mUserId);
if (mAppEntry != null) {
// Get application info again to refresh changed properties of application
try {
@@ -151,15 +155,29 @@ public abstract class AppInfoBase extends PreferenceFragment
protected abstract AlertDialog createDialog(int id, int errorCode);
@Override
- public void onRunningStateChanged(boolean running) { }
+ public void onRunningStateChanged(boolean running) {
+ // No op.
+ }
+
@Override
- public void onRebuildComplete(ArrayList<AppEntry> apps) { }
+ public void onRebuildComplete(ArrayList<AppEntry> apps) {
+ // No op.
+ }
+
@Override
- public void onPackageIconChanged() { }
+ public void onPackageIconChanged() {
+ // No op.
+ }
+
@Override
- public void onPackageSizeChanged(String packageName) { }
+ public void onPackageSizeChanged(String packageName) {
+ // No op.
+ }
+
@Override
- public void onAllSizesComputed() { }
+ public void onAllSizesComputed() {
+ // No op.
+ }
@Override
public void onPackageListChanged() {
diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java
index 6379102..c31d8ad 100644
--- a/src/com/android/settings/applications/AppLaunchSettings.java
+++ b/src/com/android/settings/applications/AppLaunchSettings.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.settings.applications;
import android.app.AlertDialog;
@@ -41,7 +42,6 @@ import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener {
@@ -167,9 +167,9 @@ public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListe
private static boolean hasPreferredActivities(PackageManager pm, String packageName) {
// Get list of preferred activities
- List<ComponentName> prefActList = Collections.emptyList();
+ List<ComponentName> prefActList = new ArrayList<>();
// Intent list cannot be null. so pass empty list
- List<IntentFilter> intentList = Collections.emptyList();
+ List<IntentFilter> intentList = new ArrayList<>();
pm.getPreferredActivities(intentList, prefActList, packageName);
if (localLOGV) {
Log.i(TAG, "Have " + prefActList.size() + " number of activities in preferred list");
diff --git a/src/com/android/settings/applications/AppPermissionSettings.java b/src/com/android/settings/applications/AppPermissionSettings.java
index a5b4895..496faf5 100644
--- a/src/com/android/settings/applications/AppPermissionSettings.java
+++ b/src/com/android/settings/applications/AppPermissionSettings.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.settings.applications;
import android.app.AlertDialog;
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 5ae5e8f..72fa805 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -45,7 +45,7 @@ import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.applications.ApplicationsState.Callbacks;
public class AppStorageSettings extends AppInfoWithHeader implements OnClickListener, Callbacks {
- private static final String TAG = "AppStorageSettings";
+ private static final String TAG = AppStorageSettings.class.getSimpleName();
//internal constants used in Handler
private static final int OP_SUCCESSFUL = 1;
@@ -345,7 +345,7 @@ public class AppStorageSettings extends AppInfoWithHeader implements OnClickList
if (result == PackageManager.MOVE_SUCCEEDED) {
Log.i(TAG, "Moved resources for " + packageName);
// Refresh size information again.
- mState.requestSize(mAppEntry.info.packageName);
+ mState.requestSize(mPackageName, mUserId);
} else {
showDialogInner(DLG_MOVE_FAILED, result);
}
@@ -362,7 +362,7 @@ public class AppStorageSettings extends AppInfoWithHeader implements OnClickList
mClearDataButton.setText(R.string.clear_user_data_text);
if(result == OP_SUCCESSFUL) {
Log.i(TAG, "Cleared user data for package : "+packageName);
- mState.requestSize(mAppEntry.info.packageName);
+ mState.requestSize(mPackageName, mUserId);
} else {
mClearDataButton.setEnabled(true);
}
@@ -443,7 +443,7 @@ public class AppStorageSettings extends AppInfoWithHeader implements OnClickList
break;
case MSG_CLEAR_CACHE:
// Refresh size info
- mState.requestSize(mPackageName);
+ mState.requestSize(mPackageName, mUserId);
break;
case MSG_PACKAGE_MOVE:
processMoveMsg(msg);
diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java
index 9c51181..3f25d47 100644
--- a/src/com/android/settings/applications/ApplicationsState.java
+++ b/src/com/android/settings/applications/ApplicationsState.java
@@ -1,15 +1,18 @@
package com.android.settings.applications;
+import android.app.AppGlobals;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
@@ -17,10 +20,13 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.format.Formatter;
import android.util.Log;
+import android.util.SparseArray;
import java.io.File;
import java.text.Collator;
@@ -140,7 +146,7 @@ public class ApplicationsState {
boolean ensureIconLocked(Context context, PackageManager pm) {
if (this.icon == null) {
if (this.apkFile.exists()) {
- this.icon = this.info.loadIcon(pm);
+ this.icon = getBadgedIcon(pm);
return true;
} else {
this.mounted = false;
@@ -152,12 +158,18 @@ public class ApplicationsState {
// its icon.
if (this.apkFile.exists()) {
this.mounted = true;
- this.icon = this.info.loadIcon(pm);
+ this.icon = getBadgedIcon(pm);
return true;
}
}
return false;
}
+
+ private Drawable getBadgedIcon(PackageManager pm) {
+ // Do badging ourself so that it comes from the user of the app not the current user.
+ return pm.getUserBadgedIcon(pm.loadUnbadgedItemIcon(info, info),
+ new UserHandle(UserHandle.getUserId(info.uid)));
+ }
}
public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() {
@@ -265,6 +277,8 @@ public class ApplicationsState {
final Context mContext;
final PackageManager mPm;
+ final IPackageManager mIpm;
+ final UserManager mUm;
final int mRetrieveFlags;
PackageIntentReceiver mPackageIntentReceiver;
@@ -276,11 +290,14 @@ public class ApplicationsState {
final ArrayList<Session> mSessions = new ArrayList<Session>();
final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>();
final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();
- final HashMap<String, AppEntry> mEntriesMap = new HashMap<String, AppEntry>();
+ // Map: userid => (Map: package name => AppEntry)
+ final SparseArray<HashMap<String, AppEntry>> mEntriesMap =
+ new SparseArray<HashMap<String, AppEntry>>();
final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
long mCurId = 1;
String mCurComputingSizePkg;
+ int mCurComputingSizeUserId;
boolean mSessionsChanged;
// Temporary for dispatching session callbacks. Only touched by main thread.
@@ -301,6 +318,11 @@ public class ApplicationsState {
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(this, sdFilter);
+ // Register for events related to user creation/deletion.
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_ADDED);
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(this, userFilter);
}
void unregisterReceiver() {
mContext.unregisterReceiver(this);
@@ -311,15 +333,21 @@ public class ApplicationsState {
if (Intent.ACTION_PACKAGE_ADDED.equals(actionStr)) {
Uri data = intent.getData();
String pkgName = data.getEncodedSchemeSpecificPart();
- addPackage(pkgName);
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ addPackage(pkgName, mEntriesMap.keyAt(i));
+ }
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(actionStr)) {
Uri data = intent.getData();
String pkgName = data.getEncodedSchemeSpecificPart();
- removePackage(pkgName);
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ removePackage(pkgName, mEntriesMap.keyAt(i));
+ }
} else if (Intent.ACTION_PACKAGE_CHANGED.equals(actionStr)) {
Uri data = intent.getData();
String pkgName = data.getEncodedSchemeSpecificPart();
- invalidatePackage(pkgName);
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ invalidatePackage(pkgName, mEntriesMap.keyAt(i));
+ }
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr) ||
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(actionStr)) {
// When applications become available or unavailable (perhaps because
@@ -336,9 +364,15 @@ public class ApplicationsState {
boolean avail = Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr);
if (avail) {
for (String pkgName : pkgList) {
- invalidatePackage(pkgName);
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ invalidatePackage(pkgName, mEntriesMap.keyAt(i));
+ }
}
}
+ } else if (Intent.ACTION_USER_ADDED.equals(actionStr)) {
+ addUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
+ } else if (Intent.ACTION_USER_REMOVED.equals(actionStr)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
}
}
}
@@ -426,6 +460,11 @@ public class ApplicationsState {
private ApplicationsState(Application app) {
mContext = app;
mPm = mContext.getPackageManager();
+ mIpm = AppGlobals.getPackageManager();
+ mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
+ for (UserHandle user : mUm.getUserProfiles()) {
+ mEntriesMap.put(user.getIdentifier(), new HashMap<String, AppEntry>());
+ }
mThread = new HandlerThread("ApplicationsState.Loader",
Process.THREAD_PRIORITY_BACKGROUND);
mThread.start();
@@ -630,15 +669,22 @@ public class ApplicationsState {
mPackageIntentReceiver = new PackageIntentReceiver();
mPackageIntentReceiver.registerReceiver();
}
- mApplications = mPm.getInstalledApplications(mRetrieveFlags);
- if (mApplications == null) {
- mApplications = new ArrayList<ApplicationInfo>();
+ mApplications = new ArrayList<ApplicationInfo>();
+ for (UserHandle user : mUm.getUserProfiles()) {
+ try {
+ ParceledListSlice<ApplicationInfo> list =
+ mIpm.getInstalledApplications(mRetrieveFlags, user.getIdentifier());
+ mApplications.addAll(list.getList());
+ } catch (RemoteException e) {
+ }
}
if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
// If an interesting part of the configuration has changed, we
// should completely reload the app entries.
- mEntriesMap.clear();
+ for (int i = 0; i < mEntriesMap.size(); i++) {
+ mEntriesMap.valueAt(i).clear();
+ }
mAppEntries.clear();
} else {
for (int i=0; i<mAppEntries.size(); i++) {
@@ -659,7 +705,8 @@ public class ApplicationsState {
}
mHaveDisabledApps = true;
}
- final AppEntry entry = mEntriesMap.get(info.packageName);
+ int userId = UserHandle.getUserId(info.uid);
+ final AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
if (entry != null) {
entry.info = info;
}
@@ -683,6 +730,10 @@ public class ApplicationsState {
return;
}
}
+ doPauseLocked();
+ }
+
+ void doPauseLocked() {
mResumed = false;
if (mPackageIntentReceiver != null) {
mPackageIntentReceiver.unregisterReceiver();
@@ -690,10 +741,10 @@ public class ApplicationsState {
}
}
- AppEntry getEntry(String packageName) {
+ AppEntry getEntry(String packageName, int userId) {
if (DEBUG_LOCKING) Log.v(TAG, "getEntry about to acquire lock...");
synchronized (mEntriesMap) {
- AppEntry entry = mEntriesMap.get(packageName);
+ AppEntry entry = mEntriesMap.get(userId).get(packageName);
if (entry == null) {
for (int i=0; i<mApplications.size(); i++) {
ApplicationInfo info = mApplications.get(i);
@@ -717,12 +768,12 @@ public class ApplicationsState {
}
}
- void requestSize(String packageName) {
+ void requestSize(String packageName, int userId) {
if (DEBUG_LOCKING) Log.v(TAG, "requestSize about to acquire lock...");
synchronized (mEntriesMap) {
- AppEntry entry = mEntriesMap.get(packageName);
+ AppEntry entry = mEntriesMap.get(userId).get(packageName);
if (entry != null) {
- mPm.getPackageSizeInfo(packageName, mBackgroundHandler.mStatsObserver);
+ mPm.getPackageSizeInfo(packageName, userId, mBackgroundHandler.mStatsObserver);
}
if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
}
@@ -741,16 +792,18 @@ public class ApplicationsState {
return sum;
}
- int indexOfApplicationInfoLocked(String pkgName) {
+ int indexOfApplicationInfoLocked(String pkgName, int userId) {
for (int i=mApplications.size()-1; i>=0; i--) {
- if (mApplications.get(i).packageName.equals(pkgName)) {
+ ApplicationInfo appInfo = mApplications.get(i);
+ if (appInfo.packageName.equals(pkgName)
+ && UserHandle.getUserId(appInfo.uid) == userId) {
return i;
}
}
return -1;
}
- void addPackage(String pkgName) {
+ void addPackage(String pkgName, int userId) {
try {
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "addPackage acquired lock");
@@ -762,12 +815,15 @@ public class ApplicationsState {
if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: not resumed");
return;
}
- if (indexOfApplicationInfoLocked(pkgName) >= 0) {
+ if (indexOfApplicationInfoLocked(pkgName, userId) >= 0) {
if (DEBUG) Log.i(TAG, "Package already exists!");
if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: already exists");
return;
}
- ApplicationInfo info = mPm.getApplicationInfo(pkgName, mRetrieveFlags);
+ ApplicationInfo info = mIpm.getApplicationInfo(pkgName, mRetrieveFlags, userId);
+ if (info == null) {
+ return;
+ }
if (!info.enabled) {
if (info.enabledSetting
!= PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
@@ -784,20 +840,20 @@ public class ApplicationsState {
}
if (DEBUG_LOCKING) Log.v(TAG, "addPackage releasing lock");
}
- } catch (NameNotFoundException e) {
+ } catch (RemoteException e) {
}
}
- void removePackage(String pkgName) {
+ void removePackage(String pkgName, int userId) {
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "removePackage acquired lock");
- int idx = indexOfApplicationInfoLocked(pkgName);
+ int idx = indexOfApplicationInfoLocked(pkgName, userId);
if (DEBUG) Log.i(TAG, "removePackage: " + pkgName + " @ " + idx);
if (idx >= 0) {
- AppEntry entry = mEntriesMap.get(pkgName);
+ AppEntry entry = mEntriesMap.get(userId).get(pkgName);
if (DEBUG) Log.i(TAG, "removePackage: " + entry);
if (entry != null) {
- mEntriesMap.remove(pkgName);
+ mEntriesMap.get(userId).remove(pkgName);
mAppEntries.remove(entry);
}
ApplicationInfo info = mApplications.get(idx);
@@ -819,18 +875,53 @@ public class ApplicationsState {
}
}
- void invalidatePackage(String pkgName) {
- removePackage(pkgName);
- addPackage(pkgName);
+ void invalidatePackage(String pkgName, int userId) {
+ removePackage(pkgName, userId);
+ addPackage(pkgName, userId);
}
-
+
+ void addUser(int userId) {
+ if (mUm.getUserProfiles().contains(new UserHandle(userId))) {
+ synchronized (mEntriesMap) {
+ mEntriesMap.put(userId, new HashMap<String, AppEntry>());
+ if (mResumed) {
+ // If resumed, Manually pause, then cause a resume to repopulate the app list.
+ // This is the simplest way to reload the packages so that the new user
+ // is included. Otherwise the list will be repopulated on next resume.
+ doPauseLocked();
+ doResumeIfNeededLocked();
+ }
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ }
+ }
+ }
+
+ void removeUser(int userId) {
+ synchronized (mEntriesMap) {
+ HashMap<String, AppEntry> userMap = mEntriesMap.get(userId);
+ if (userMap != null) {
+ for (AppEntry appEntry : userMap.values()) {
+ mAppEntries.remove(appEntry);
+ mApplications.remove(appEntry.info);
+ }
+ mEntriesMap.remove(userId);
+ if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
+ }
+ }
+ }
+ }
+
AppEntry getEntryLocked(ApplicationInfo info) {
- AppEntry entry = mEntriesMap.get(info.packageName);
+ int userId = UserHandle.getUserId(info.uid);
+ AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
if (DEBUG) Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
if (entry == null) {
if (DEBUG) Log.i(TAG, "Creating AppEntry for " + info.packageName);
entry = new AppEntry(mContext, info, mCurId++);
- mEntriesMap.put(info.packageName, entry);
+ mEntriesMap.get(userId).put(info.packageName, entry);
mAppEntries.add(entry);
} else if (entry.info != info) {
entry.info = info;
@@ -880,7 +971,12 @@ public class ApplicationsState {
boolean sizeChanged = false;
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted acquired lock");
- AppEntry entry = mEntriesMap.get(stats.packageName);
+ HashMap<String, AppEntry> userMap = mEntriesMap.get(stats.userHandle);
+ if (userMap == null) {
+ // The user must have been removed.
+ return;
+ }
+ AppEntry entry = userMap.get(stats.packageName);
if (entry != null) {
synchronized (entry) {
entry.sizeStale = false;
@@ -922,7 +1018,8 @@ public class ApplicationsState {
}
}
if (mCurComputingSizePkg == null
- || mCurComputingSizePkg.equals(stats.packageName)) {
+ || (mCurComputingSizePkg.equals(stats.packageName)
+ && mCurComputingSizeUserId == stats.userHandle)) {
mCurComputingSizePkg = null;
sendEmptyMessage(MSG_LOAD_SIZES);
}
@@ -966,7 +1063,8 @@ public class ApplicationsState {
mMainHandler.sendMessage(m);
}
ApplicationInfo info = mApplications.get(i);
- if (mEntriesMap.get(info.packageName) == null) {
+ int userId = UserHandle.getUserId(info.uid);
+ if (mEntriesMap.get(userId).get(info.packageName) == null) {
numDone++;
getEntryLocked(info);
}
@@ -1035,7 +1133,9 @@ public class ApplicationsState {
}
entry.sizeLoadStart = now;
mCurComputingSizePkg = entry.info.packageName;
- mPm.getPackageSizeInfo(mCurComputingSizePkg, mStatsObserver);
+ mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
+ mPm.getPackageSizeInfo(mCurComputingSizePkg,
+ mCurComputingSizeUserId, mStatsObserver);
}
if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
return;
diff --git a/src/com/android/settings/applications/HeaderPreference.java b/src/com/android/settings/applications/HeaderPreference.java
index 57fe9f3..a3d4bde 100644
--- a/src/com/android/settings/applications/HeaderPreference.java
+++ b/src/com/android/settings/applications/HeaderPreference.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.settings.applications;
import android.content.Context;
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index d77d63f..7f20b32 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -19,23 +19,33 @@ package com.android.settings.applications;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.LoaderManager.LoaderCallbacks;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.Loader;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkTemplate;
+import android.net.TrafficStats;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.provider.Settings;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -44,10 +54,14 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.settings.DataUsageSummary;
+import com.android.settings.DataUsageSummary.AppItem;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
+import com.android.settings.net.ChartData;
+import com.android.settings.net.ChartDataLoader;
import com.android.settings.notification.NotificationAppList;
import com.android.settings.notification.NotificationAppList.AppRow;
import com.android.settings.notification.NotificationAppList.Backend;
@@ -76,6 +90,8 @@ public class InstalledAppDetails extends AppInfoBase
public static final int REQUEST_UNINSTALL = 0;
private static final int SUB_INFO_FRAGMENT = 1;
+ private static final int LOADER_CHART_DATA = 2;
+
private static final int DLG_FORCE_STOP = DLG_BASE + 1;
private static final int DLG_DISABLE = DLG_BASE + 2;
private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
@@ -109,6 +125,9 @@ public class InstalledAppDetails extends AppInfoBase
// Used for updating notification preference.
private final Backend mBackend = new Backend();
+ private ChartData mChartData;
+ private INetworkStatsSession mStatsSession;
+
private boolean handleDisableable(Button button) {
boolean disableable = false;
// Try to prevent the user from bricking their phone
@@ -207,6 +226,37 @@ public class InstalledAppDetails extends AppInfoBase
setHasOptionsMenu(true);
addPreferencesFromResource(R.xml.installed_app_details);
+
+ INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ try {
+ mStatsSession = statsService.openSession();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ AppItem app = new AppItem(mAppEntry.info.uid);
+ app.addUid(mAppEntry.info.uid);
+ getLoaderManager().restartLoader(LOADER_CHART_DATA,
+ ChartDataLoader.buildArgs(NetworkTemplate.buildTemplateMobileWildcard(), app),
+ mDataCallbacks);
+ }
+
+ @Override
+ public void onPause() {
+ getLoaderManager().destroyLoader(LOADER_CHART_DATA);
+ super.onPause();
+ }
+
+ @Override
+ public void onDestroy() {
+ TrafficStats.closeQuietly(mStatsSession);
+
+ super.onDestroy();
}
public void onActivityCreated(Bundle savedInstanceState) {
@@ -223,8 +273,6 @@ public class InstalledAppDetails extends AppInfoBase
mLaunchPreference.setOnPreferenceClickListener(this);
mDataPreference = findPreference(KEY_DATA);
mDataPreference.setOnPreferenceClickListener(this);
- // Data isn't ready, lets just pull it for now.
- getPreferenceScreen().removePreference(mDataPreference);
}
private void handleHeader() {
@@ -384,6 +432,7 @@ public class InstalledAppDetails extends AppInfoBase
mPm, context));
mNotificationPreference.setSummary(getNotificationSummary(mAppEntry, context,
mBackend));
+ mDataPreference.setSummary(getDataSummary());
if (!mInitialized) {
// First time init: are we displaying an uninstalled app?
@@ -410,6 +459,18 @@ public class InstalledAppDetails extends AppInfoBase
return true;
}
+ private CharSequence getDataSummary() {
+ if (mChartData != null) {
+ long totalBytes = mChartData.detail.getTotalBytes();
+ Context context = getActivity();
+ return getString(R.string.data_summary_format,
+ Formatter.formatFileSize(context, totalBytes),
+ DateUtils.formatDateTime(context, mChartData.detail.getStart(),
+ DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH));
+ }
+ return getString(R.string.computing_size);
+ }
+
@Override
protected AlertDialog createDialog(int id, int errorCode) {
switch (id) {
@@ -482,8 +543,9 @@ public class InstalledAppDetails extends AppInfoBase
ActivityManager am = (ActivityManager)getActivity().getSystemService(
Context.ACTIVITY_SERVICE);
am.forceStopPackage(pkgName);
- mState.invalidatePackage(pkgName);
- ApplicationsState.AppEntry newEnt = mState.getEntry(pkgName);
+ int userId = UserHandle.getUserId(mAppEntry.info.uid);
+ mState.invalidatePackage(pkgName, userId);
+ ApplicationsState.AppEntry newEnt = mState.getEntry(pkgName, userId);
if (newEnt != null) {
mAppEntry = newEnt;
}
@@ -578,7 +640,13 @@ public class InstalledAppDetails extends AppInfoBase
} else if (preference == mLaunchPreference) {
startAppInfoFragment(AppLaunchSettings.class, mLaunchPreference.getTitle());
} else if (preference == mDataPreference) {
- // Not yet.
+ Bundle args = new Bundle();
+ args.putString(DataUsageSummary.EXTRA_SHOW_APP_IMMEDIATE_PKG,
+ mAppEntry.info.packageName);
+
+ SettingsActivity sa = (SettingsActivity) getActivity();
+ sa.startPreferencePanel(DataUsageSummary.class.getName(), args, -1,
+ getString(R.string.app_data_usage), this, SUB_INFO_FRAGMENT);
} else {
return false;
}
@@ -626,6 +694,26 @@ public class InstalledAppDetails extends AppInfoBase
}
}
+ private final LoaderCallbacks<ChartData> mDataCallbacks = new LoaderCallbacks<ChartData>() {
+
+ @Override
+ public Loader<ChartData> onCreateLoader(int id, Bundle args) {
+ return new ChartDataLoader(getActivity(), mStatsSession, args);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<ChartData> loader, ChartData data) {
+ mChartData = data;
+ mDataPreference.setSummary(getDataSummary());
+ }
+
+ @Override
+ public void onLoaderReset(Loader<ChartData> loader) {
+ mChartData = null;
+ mDataPreference.setSummary(getDataSummary());
+ }
+ };
+
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 45431eb..0152755 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -35,6 +35,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
@@ -70,13 +71,12 @@ import android.widget.Spinner;
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.UserSpinnerAdapter;
import com.android.settings.Settings.RunningServicesActivity;
import com.android.settings.Settings.StorageUseActivity;
+import com.android.settings.UserSpinnerAdapter;
+import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.deviceinfo.StorageMeasurement;
-import com.android.settings.Utils;
import java.util.ArrayList;
import java.util.Comparator;
@@ -135,8 +135,7 @@ interface AppClickListener {
* intent.
*/
public class ManageApplications extends Fragment implements
- AppClickListener, DialogInterface.OnClickListener,
- DialogInterface.OnDismissListener, OnItemSelectedListener {
+ AppClickListener, DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
static final String TAG = "ManageApplications";
static final boolean DEBUG = false;
@@ -451,6 +450,7 @@ public class ManageApplications extends Fragment implements
private LayoutInflater mInflater;
private String mCurrentPkgName;
+ private int mCurrentUid;
private Menu mOptionsMenu;
@@ -472,7 +472,6 @@ public class ManageApplications extends Fragment implements
private View mRootView;
private ViewPager mViewPager;
private ViewGroup mPinnedHeader;
- private UserSpinnerAdapter mProfileSpinnerAdapter;
private Spinner mSpinner;
private Context mContext;
@@ -911,9 +910,6 @@ public class ManageApplications extends Fragment implements
mTabs.add(tab);
mNumTabs = mTabs.size();
-
- final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mProfileSpinnerAdapter = Utils.createUserSpinnerAdapter(um, mContext);
}
@@ -926,14 +922,6 @@ public class ManageApplications extends Fragment implements
container, false);
mContentContainer = container;
mRootView = rootView;
- mPinnedHeader = (ViewGroup) mRootView.findViewById(R.id.pinned_header);
- if (mProfileSpinnerAdapter != null) {
- mSpinner = (Spinner) inflater.inflate(R.layout.spinner_view, null);
- mSpinner.setAdapter(mProfileSpinnerAdapter);
- mSpinner.setOnItemSelectedListener(this);
- mPinnedHeader.addView(mSpinner);
- mPinnedHeader.setVisibility(View.VISIBLE);
- }
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
MyPagerAdapter adapter = new MyPagerAdapter();
mViewPager.setAdapter(adapter);
@@ -1029,31 +1017,10 @@ public class ManageApplications extends Fragment implements
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
- mApplicationsState.requestSize(mCurrentPkgName);
- }
- }
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- UserHandle selectedUser = mProfileSpinnerAdapter.getUserHandle(position);
- if (selectedUser.getIdentifier() != UserHandle.myUserId()) {
- Intent intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- int currentTab = mViewPager.getCurrentItem();
- intent.putExtra(EXTRA_LIST_TYPE, mTabs.get(currentTab).mListType);
- mContext.startActivityAsUser(intent, selectedUser);
- // Go back to default selection, which is the first one; this makes sure that pressing
- // the back button takes you into a consistent state
- mSpinner.setSelection(0);
+ mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
}
}
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // Nothing to do
- }
-
private void updateNumTabs() {
int newNum = mApplicationsState.haveDisabledApps() ? mTabs.size() : (mTabs.size()-1);
if (newNum != mNumTabs) {
@@ -1076,13 +1043,13 @@ public class ManageApplications extends Fragment implements
// utility method used to start sub activity
private void startApplicationDetailsActivity() {
- // start new fragment to display extended information
- Bundle args = new Bundle();
- args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);
-
- SettingsActivity sa = (SettingsActivity) getActivity();
- sa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
- R.string.application_info_label, null, this, INSTALLED_APP_DETAILS);
+ // TODO: Figure out if there is a way where we can spin up the profile's settings
+ // process ahead of time, to avoid a long load of data when user clicks on a managed app.
+ // Maybe when they load the list of apps that contains managed profile apps.
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ intent.setData(Uri.fromParts("package", mCurrentPkgName, null));
+ getActivity().startActivityAsUser(intent,
+ new UserHandle(UserHandle.getUserId(mCurrentUid)));
}
@Override
@@ -1273,6 +1240,7 @@ public class ManageApplications extends Fragment implements
if (tab.mApplications != null && tab.mApplications.getCount() > position) {
ApplicationsState.AppEntry entry = tab.mApplications.getAppEntry(position);
mCurrentPkgName = entry.info.packageName;
+ mCurrentUid = entry.info.uid;
startApplicationDetailsActivity();
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index 67c026b..0bb54b2 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -112,7 +112,7 @@ public final class BluetoothDevicePreference extends Preference implements
*/
setTitle(mCachedDevice.getName());
- int summaryResId = getConnectionSummary();
+ int summaryResId = mCachedDevice.getConnectionSummary();
if (summaryResId != 0) {
setSummary(summaryResId);
} else {
@@ -232,60 +232,6 @@ public final class BluetoothDevicePreference extends Preference implements
}
}
- private int getConnectionSummary() {
- final CachedBluetoothDevice cachedDevice = mCachedDevice;
-
- boolean profileConnected = false; // at least one profile is connected
- boolean a2dpNotConnected = false; // A2DP is preferred but not connected
- boolean headsetNotConnected = false; // Headset is preferred but not connected
-
- for (LocalBluetoothProfile profile : cachedDevice.getProfiles()) {
- int connectionStatus = cachedDevice.getProfileConnectionState(profile);
-
- switch (connectionStatus) {
- case BluetoothProfile.STATE_CONNECTING:
- case BluetoothProfile.STATE_DISCONNECTING:
- return Utils.getConnectionStateSummary(connectionStatus);
-
- case BluetoothProfile.STATE_CONNECTED:
- profileConnected = true;
- break;
-
- case BluetoothProfile.STATE_DISCONNECTED:
- if (profile.isProfileReady()) {
- if (profile instanceof A2dpProfile) {
- a2dpNotConnected = true;
- } else if (profile instanceof HeadsetProfile) {
- headsetNotConnected = true;
- }
- }
- break;
- }
- }
-
- if (profileConnected) {
- if (a2dpNotConnected && headsetNotConnected) {
- return R.string.bluetooth_connected_no_headset_no_a2dp;
- } else if (a2dpNotConnected) {
- return R.string.bluetooth_connected_no_a2dp;
- } else if (headsetNotConnected) {
- return R.string.bluetooth_connected_no_headset;
- } else {
- return R.string.bluetooth_connected;
- }
- }
-
- switch (cachedDevice.getBondState()) {
- case BluetoothDevice.BOND_BONDING:
- return R.string.bluetooth_pairing;
-
- case BluetoothDevice.BOND_BONDED:
- case BluetoothDevice.BOND_NONE:
- default:
- return 0;
- }
- }
-
private int getBtClassDrawable() {
BluetoothClass btClass = mCachedDevice.getBtClass();
if (btClass != null) {
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
index b2a703d..f07a9f2 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
@@ -220,4 +220,6 @@ public abstract class DeviceListPreferenceFragment extends
updateProgressUi(false);
}
}
+
+ public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
}
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
index c4f6485..020ca0c 100644
--- a/src/com/android/settings/bluetooth/DockService.java
+++ b/src/com/android/settings/bluetooth/DockService.java
@@ -937,6 +937,7 @@ public final class DockService extends Service implements ServiceListener {
public void onBluetoothStateChanged(int bluetoothState) { }
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { }
public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { }
+ public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { }
@Override
public void onScanningStateChanged(boolean started) {
diff --git a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java b/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
index ada476e..8f10bdf 100644
--- a/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
+++ b/src/com/android/settings/inputmethod/InputMethodSettingValuesWrapper.java
@@ -186,13 +186,16 @@ class InputMethodSettingValuesWrapper {
if (imi.isAuxiliaryIme()) {
return false;
}
- if (InputMethodUtils.isValidSystemDefaultIme(true /* isSystemReady */, imi, context)) {
+ final Locale systemLocale = context.getResources().getConfiguration().locale;
+ if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
+ true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
+ InputMethodUtils.SUBTYPE_MODE_ANY)) {
return true;
}
if (mAsciiCapableEnabledImis.isEmpty()) {
Log.w(TAG, "ascii capable subtype enabled imi not found. Fall back to English"
+ " Keyboard subtype.");
- return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH.getLanguage(),
+ return InputMethodUtils.containsSubtypeOf(imi, Locale.ENGLISH, false /* checkCountry */,
InputMethodUtils.SUBTYPE_MODE_KEYBOARD);
}
return mAsciiCapableEnabledImis.contains(imi);
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java
index b392484..41ae0ab 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/NotificationSettings.java
@@ -71,6 +71,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
private static final String KEY_PHONE_RINGTONE = "ringtone";
private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone";
private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+ private static final String KEY_WIFI_DISPLAY = "wifi_display";
private static final String KEY_NOTIFICATION = "notification";
private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications";
@@ -601,6 +602,7 @@ public class NotificationSettings extends SettingsPreferenceFragment implements
} else {
rt.add(KEY_RING_VOLUME);
rt.add(KEY_PHONE_RINGTONE);
+ rt.add(KEY_WIFI_DISPLAY);
rt.add(KEY_VIBRATE_WHEN_RINGING);
}
return rt;
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 6abbc3d..0022338 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -47,6 +47,7 @@ import com.android.settings.voice.VoiceInputSettings;
import com.android.settings.wifi.AdvancedWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
+import com.android.settings.WifiCallingSettings;
import java.util.HashMap;
@@ -104,6 +105,7 @@ public final class Ranking {
// Other wireless settinfs
sRankMap.put(WirelessSettings.class.getName(), RANK_WIRELESS);
+ sRankMap.put(WifiCallingSettings.class.getName(), RANK_WIRELESS);
// Home
sRankMap.put(HomeSettings.class.getName(), RANK_HOME);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 502480d..d774469 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -49,6 +49,7 @@ import com.android.settings.voice.VoiceInputSettings;
import com.android.settings.wifi.AdvancedWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
+import com.android.settings.WifiCallingSettings;
import java.util.Collection;
import java.util.HashMap;
@@ -270,6 +271,13 @@ public final class SearchIndexableResources {
NO_DATA_RES_ID,
DeviceInfoSettings.class.getName(),
R.drawable.ic_settings_about));
+
+ sResMap.put(WifiCallingSettings.class.getName(),
+ new SearchIndexableResource(
+ Ranking.getRankForClassName(WifiCallingSettings.class.getName()),
+ R.xml.wifi_calling_settings,
+ WifiCallingSettings.class.getName(),
+ R.drawable.ic_settings_wireless));
}
private SearchIndexableResources() {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index dbd0481..e54ea9f 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -872,8 +872,7 @@ public class UserSettings extends SettingsPreferenceFragment
for (int userId : values[0]) {
Bitmap bitmap = mUserManager.getUserIcon(userId);
if (bitmap == null) {
- bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(userId,
- /* light= */ false));
+ bitmap = Utils.getDefaultUserIconAsBitmap(userId);
}
mUserIcons.append(userId, bitmap);
}
@@ -889,15 +888,13 @@ public class UserSettings extends SettingsPreferenceFragment
}
private void assignDefaultPhoto(UserInfo user) {
- Bitmap bitmap = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(user.id,
- /* light= */ false));
+ Bitmap bitmap = Utils.getDefaultUserIconAsBitmap(user.id);
mUserManager.setUserIcon(user.id, bitmap);
}
private Drawable getEncircledDefaultIcon() {
if (mDefaultIconDrawable == null) {
- mDefaultIconDrawable = encircle(UserIcons.convertToBitmap(
- UserIcons.getDefaultUserIcon(UserHandle.USER_NULL, /* light= */ false)));
+ mDefaultIconDrawable = encircle(Utils.getDefaultUserIconAsBitmap(UserHandle.USER_NULL));
}
return mDefaultIconDrawable;
}
diff --git a/src/com/android/settings/wifi/WifiApDialog.java b/src/com/android/settings/wifi/WifiApDialog.java
index fb8026a..eee3db9 100644
--- a/src/com/android/settings/wifi/WifiApDialog.java
+++ b/src/com/android/settings/wifi/WifiApDialog.java
@@ -22,6 +22,7 @@ import android.content.DialogInterface;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
@@ -32,9 +33,13 @@ import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
+import android.widget.RadioGroup;
+import android.widget.RadioButton;
import com.android.settings.R;
+import android.util.Log;
+
/**
* Dialog to configure the SSID and security settings
* for Access Point operation
@@ -53,8 +58,14 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
private TextView mSsid;
private int mSecurityTypeIndex = OPEN_INDEX;
private EditText mPassword;
+ private RadioGroup mChannel;
+ private RadioButton mChannel2G;
+ private RadioButton mChannel5G;
WifiConfiguration mWifiConfig;
+ WifiManager mWifiManager;
+
+ private static final String TAG = "WifiApDialog";
public WifiApDialog(Context context, DialogInterface.OnClickListener listener,
WifiConfiguration wifiConfig) {
@@ -64,6 +75,7 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
if (wifiConfig != null) {
mSecurityTypeIndex = getSecurityTypeIndex(wifiConfig);
}
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
public static int getSecurityTypeIndex(WifiConfiguration wifiConfig) {
@@ -85,6 +97,16 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
*/
config.SSID = mSsid.getText().toString();
+ //obtain the band configure
+ if (mChannel2G.isChecked()) {
+ config.apBand = 0;
+ } else if(mChannel5G.isChecked()) {
+ config.apBand = 1;
+ } else {
+ Log.e("TAG", "AP band configure error!");
+ return null;
+ }
+
switch (mSecurityTypeIndex) {
case OPEN_INDEX:
config.allowedKeyManagement.set(KeyMgmt.NONE);
@@ -118,15 +140,36 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
mSsid = (TextView) mView.findViewById(R.id.ssid);
mPassword = (EditText) mView.findViewById(R.id.password);
+ mChannel = (RadioGroup) mView.findViewById(R.id.choose_channel);
+ mChannel2G = (RadioButton) mView.findViewById(R.id.ap_2G_band);
+ mChannel5G = (RadioButton) mView.findViewById(R.id.ap_5G_band);
+
+ String countryCode = mWifiManager.getCountryCode();
+ if (!mWifiManager.is5GHzBandSupported() || countryCode == null) {
+ //If no country code, 5GHz AP is forbidden
+ Log.e(TAG," NO country code, forbid 5GHz");
+ mChannel5G.setVisibility(View.INVISIBLE);
+ mWifiConfig.apBand = 0;
+ } else {
+ mChannel5G.setVisibility(View.VISIBLE);
+ }
+
+
setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
setButton(DialogInterface.BUTTON_NEGATIVE,
context.getString(R.string.wifi_cancel), mListener);
if (mWifiConfig != null) {
mSsid.setText(mWifiConfig.SSID);
+ if (mWifiConfig.apBand == 0) {
+ mChannel2G.setChecked(true);
+ } else {
+ mChannel5G.setChecked(true);
+ }
+
mSecurity.setSelection(mSecurityTypeIndex);
if (mSecurityTypeIndex == WPA2_INDEX) {
- mPassword.setText(mWifiConfig.preSharedKey);
+ mPassword.setText(mWifiConfig.preSharedKey);
}
}
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index efa56d7..5716bec 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -73,7 +73,9 @@ public class WifiSettingsForSetupWizard extends WifiSettings {
final Intent intent = getActivity().getIntent();
if (intent.getBooleanExtra(EXTRA_SHOW_WIFI_REQUIRED_INFO, false)) {
- view.findViewById(R.id.wifi_required_info).setVisibility(View.VISIBLE);
+ final View requiredInfo =
+ inflater.inflate(R.layout.setup_wifi_required_info, list, false);
+ list.addHeaderView(requiredInfo, null, false);
}
return view;