Merge "Replace "A" icon with underline with simple "A" icon on font size settings screen Bug: 27694339" into nyc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 72f567e..4b976b5 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1550,8 +1550,22 @@
</activity>
<activity android:name=".SetupRedactionInterstitial"
+ android:enabled="false"
+ android:exported="true"
android:taskAffinity="com.android.wizard"
- android:theme="@style/SetupWizardDisableAppStartingTheme"/>
+ android:theme="@style/SetupWizardDisableAppStartingTheme"
+ android:icon="@drawable/ic_suggested_notifications">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.settings.suggested.category.DEFAULT_SETUP_WIZARD_ONLY" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.require_user_type"
+ android:value="primary" />
+ <meta-data android:name="com.android.settings.title"
+ android:resource="@string/notification_suggestion_title" />
+ <meta-data android:name="com.android.settings.summary"
+ android:resource="@string/notification_suggestion_summary" />
+ </activity>
<activity android:name=".notification.RedactionInterstitial"/>
diff --git a/res/drawable/ic_suggested_notifications.xml b/res/drawable/ic_suggested_notifications.xml
new file mode 100644
index 0000000..00bd736
--- /dev/null
+++ b/res/drawable/ic_suggested_notifications.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="@color/suw_color_accent_light">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.0,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0c0.0,1.0 0.89,2.0 2.0,2.0zm6.0,-6.0l0.0,-5.0c0.0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4.0c0.0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.0,0.67 -1.5,1.5l0.0,0.68C7.63,5.36 6.0,7.92 6.0,11.0l0.0,5.0l-2.0,2.0l0.0,1.0l16.0,0.0l0.0,-1.0l-2.0,-2.0z"/>
+</vector>
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index d7e7f95..620b43f 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -132,6 +132,9 @@
<CheckBox style="@style/vpn_value" android:id="@+id/save_login"
android:singleLine="false"
android:text="@string/vpn_save_login"/>
+ <CheckBox style="@style/vpn_value" android:id="@+id/always_on_vpn"
+ android:singleLine="false"
+ android:text="@string/vpn_menu_lockdown"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
diff --git a/res/menu/vpn.xml b/res/menu/vpn.xml
index 22646d1..7b35c70 100644
--- a/res/menu/vpn.xml
+++ b/res/menu/vpn.xml
@@ -20,8 +20,4 @@
android:title="@string/vpn_create"
android:icon="@drawable/ic_menu_add_white"
android:showAsAction="always" />
- <item
- android:id="@+id/vpn_lockdown"
- android:title="@string/vpn_menu_lockdown"
- android:showAsAction="never" />
</menu>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 47fd603..d970857 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7345,4 +7345,9 @@
<!-- Message of the dialog box to confirm resetting rate-limiting in the system service ShortcutManager. [CHAR_LIMIT=none] -->
<string name="confirm_reset_shortcut_manager_throttling_message">Reset ShortcutManager rate-limiting counters?</string>
+ <!-- Title of notification suggestion during optional steps of setup. [CHAR_LIMIT=40] -->
+ <string name="notification_suggestion_title">Control lock screen notifications</string>
+ <!-- Summary of notification suggestion during optional steps of setup. [CHAR_LIMIT=80] -->
+ <string name="notification_suggestion_summary">Show or hide notification content</string>
+
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 7a02ea9..c85a4f1 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -295,6 +295,7 @@
<item name="android:listPreferredItemPaddingStart">@dimen/suw_layout_margin_sides</item>
<item name="android:textAppearanceListItemSmall">@android:style/TextAppearance.Material.Body1</item>
<item name="android:windowAnimationStyle">@style/Animation.SuwWindowAnimation</item>
+ <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
<item name="suwDividerCondition">both</item>
<item name="suwListItemIconColor">?android:attr/colorAccent</item>
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 3d5e271..abbb4c6 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -59,6 +59,12 @@
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
+
+ String action = modIntent.getAction();
+ if (DevicePolicyManager.ACTION_SET_NEW_PASSWORD.equals(action)
+ || DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD.equals(action)) {
+ modIntent.putExtra(EXTRA_HIDE_DRAWER, true);
+ }
return modIntent;
}
@@ -110,6 +116,7 @@
private LockPatternUtils mLockPatternUtils;
private FingerprintManager mFingerprintManager;
private int mUserId;
+ private boolean mHideDrawer = false;
private RemovalCallback mRemovalCallback = new RemovalCallback() {
@Override
@@ -154,6 +161,7 @@
if (getActivity() instanceof ChooseLockGeneric.InternalActivity) {
mPasswordConfirmed = !confirmCredentials;
}
+ mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
mHasChallenge = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
@@ -263,6 +271,7 @@
unlockMethodIntent);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
mForFingerprint);
+ intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST);
} else {
if (mForChangeCredRequiredForBoot) {
@@ -613,6 +622,9 @@
mUserPassword, mUserId);
}
}
+ if (intent != null) {
+ intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
+ }
return intent;
}
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 1376176..0e542e6 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -186,6 +186,7 @@
private static final int MSG_SHOW_ERROR = 1;
private int mUserId;
+ private boolean mHideDrawer = false;
private Handler mHandler = new Handler() {
@Override
@@ -267,6 +268,7 @@
mUserId));
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
+ mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
if (intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
@@ -673,6 +675,7 @@
if (!wasSecureBefore) {
Intent intent = getRedactionInterstitialIntent(getActivity());
if (intent != null) {
+ intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
startActivity(intent);
}
}
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 185e489..1b71685 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -146,6 +146,7 @@
private TextView mFooterLeftButton;
private TextView mFooterRightButton;
protected List<LockPatternView.Cell> mChosenPattern = null;
+ private boolean mHideDrawer = false;
/**
* The patten used during the help screen to show how to draw a pattern.
@@ -384,6 +385,7 @@
w.start(mChooseLockSettingsHelper.utils(), required,
false, 0, LockPatternUtils.stringToPattern(current), current, mUserId);
}
+ mHideDrawer = getActivity().getIntent().getBooleanExtra(EXTRA_HIDE_DRAWER, false);
}
@Override
@@ -674,6 +676,7 @@
if (!wasSecureBefore) {
Intent intent = getRedactionInterstitialIntent(getActivity());
if (intent != null) {
+ intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
startActivity(intent);
}
}
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index b23b41a..21d26eb 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -210,6 +210,8 @@
intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, hasChallenge);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
+ // we should never have a drawer when confirming device credentials.
+ intent.putExtra(SettingsActivity.EXTRA_HIDE_DRAWER, true);
intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
if (external) {
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index 42279fd..cf0403c 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -50,7 +50,7 @@
/**
* Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
*/
-public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
+public abstract class ConfirmDeviceCredentialBaseFragment extends OptionsMenuFragment
implements FingerprintUiHelper.Callback {
public static final String PACKAGE = "com.android.settings";
diff --git a/src/com/android/settings/DeviceAdminSettings.java b/src/com/android/settings/DeviceAdminSettings.java
index ed68119..054ad41 100644
--- a/src/com/android/settings/DeviceAdminSettings.java
+++ b/src/com/android/settings/DeviceAdminSettings.java
@@ -119,7 +119,7 @@
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
-
+ setHasOptionsMenu(true);
Utils.forceCustomPadding(getListView(), true /* additive padding */);
}
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 75a4d67..17d3572 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -57,7 +57,7 @@
*
* This is the initial screen.
*/
-public class MasterClear extends InstrumentedFragment {
+public class MasterClear extends OptionsMenuFragment {
private static final String TAG = "MasterClear";
private static final int KEYGUARD_REQUEST = 55;
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index 7c14bad..d521ded 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -47,7 +47,7 @@
*
* This is the confirmation screen.
*/
-public class MasterClearConfirm extends InstrumentedFragment {
+public class MasterClearConfirm extends OptionsMenuFragment {
private View mContentView;
private boolean mEraseSdCard;
diff --git a/src/com/android/settings/OptionsMenuFragment.java b/src/com/android/settings/OptionsMenuFragment.java
new file mode 100644
index 0000000..2d05c96
--- /dev/null
+++ b/src/com/android/settings/OptionsMenuFragment.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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.os.Bundle;
+
+/**
+ * Base class for a fragment that has the options menu.
+ * SettingsPreferenceFragment automatically sets this, but some activities do not use
+ * preferences, and we need to call setHasOptionsMenu(true) for the back button on action bar.
+ * For preference fragments, use SettingsPreferenceFragment.
+ */
+public abstract class OptionsMenuFragment extends InstrumentedFragment {
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+}
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index fe12924..995fe95 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -50,7 +50,7 @@
*
* This is the initial screen.
*/
-public class ResetNetwork extends InstrumentedFragment {
+public class ResetNetwork extends OptionsMenuFragment {
private static final String TAG = "ResetNetwork";
// Arbitrary to avoid conficts
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 110398f..ece64b4 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -50,7 +50,7 @@
*
* This is the confirmation screen.
*/
-public class ResetNetworkConfirm extends InstrumentedFragment {
+public class ResetNetworkConfirm extends OptionsMenuFragment {
private View mContentView;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index c3efb62..333f6b8 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -684,6 +684,9 @@
mCurrentProfilePassword, mCurrentDevicePassword,
profileQuality, MY_USER_ID);
}
+ final boolean profilePatternVisibility =
+ mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId);
+ mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID);
mCurrentDevicePassword = null;
mCurrentProfilePassword = null;
}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index c4585d1..cecf708 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -199,6 +199,8 @@
public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
":settings:show_fragment_as_subsetting";
+ public static final String EXTRA_HIDE_DRAWER = ":settings:hide_drawer";
+
public static final String META_DATA_KEY_FRAGMENT_CLASS =
"com.android.settings.FRAGMENT_CLASS";
@@ -511,6 +513,9 @@
if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
}
+ if (intent.getBooleanExtra(EXTRA_HIDE_DRAWER, false)) {
+ setIsDrawerPresent(false);
+ }
mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
Context.MODE_PRIVATE);
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index e1cf58b..16df343 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -305,7 +305,7 @@
@Override
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
- if (!preferenceScreen.isAttached()) {
+ if (preferenceScreen != null && !preferenceScreen.isAttached()) {
// Without ids generated, the RecyclerView won't animate changes to the preferences.
preferenceScreen.setShouldUseGeneratedIds(mAnimationAllowed);
}
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index 4f0d4ea..8aaca25 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -18,8 +18,10 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserHandle;
@@ -118,6 +120,12 @@
data.putExtra(EXTRA_PASSWORD_QUALITY,
lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
+ PackageManager packageManager = getPackageManager();
+ ComponentName componentName = new ComponentName("com.android.settings",
+ "com.android.settings.SetupRedactionInterstitial");
+ packageManager.setComponentEnabledSetting(componentName,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
super.onActivityResult(requestCode, resultCode, data);
}
// If the started activity was cancelled (e.g. the user presses back), then this
diff --git a/src/com/android/settings/SetupChooseLockPassword.java b/src/com/android/settings/SetupChooseLockPassword.java
index e1e0d51..00c30bc 100644
--- a/src/com/android/settings/SetupChooseLockPassword.java
+++ b/src/com/android/settings/SetupChooseLockPassword.java
@@ -109,11 +109,7 @@
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
- Intent intent = SetupRedactionInterstitial.createStartIntent(context);
- if (intent != null) {
- SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
- }
- return intent;
+ return null;
}
@Override
diff --git a/src/com/android/settings/SetupChooseLockPattern.java b/src/com/android/settings/SetupChooseLockPattern.java
index 3a548bc..a5eab11 100644
--- a/src/com/android/settings/SetupChooseLockPattern.java
+++ b/src/com/android/settings/SetupChooseLockPattern.java
@@ -105,11 +105,7 @@
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
- Intent intent = SetupRedactionInterstitial.createStartIntent(context);
- if (intent != null) {
- SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
- }
- return intent;
+ return null;
}
@Override
diff --git a/src/com/android/settings/SetupRedactionInterstitial.java b/src/com/android/settings/SetupRedactionInterstitial.java
index e967297..354016d 100644
--- a/src/com/android/settings/SetupRedactionInterstitial.java
+++ b/src/com/android/settings/SetupRedactionInterstitial.java
@@ -39,27 +39,17 @@
*/
public class SetupRedactionInterstitial extends RedactionInterstitial {
- public static Intent createStartIntent(Context ctx) {
- Intent startIntent = RedactionInterstitial.createStartIntent(ctx, UserHandle.myUserId());
- if (startIntent != null) {
- startIntent.setClass(ctx, SetupRedactionInterstitial.class);
- startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
- .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
- }
- return startIntent;
- }
-
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
modIntent.putExtra(EXTRA_SHOW_FRAGMENT,
- SetupEncryptionInterstitialFragment.class.getName());
+ SetupRedactionInterstitialFragment.class.getName());
return modIntent;
}
@Override
protected boolean isValidFragment(String fragmentName) {
- return SetupEncryptionInterstitialFragment.class.getName().equals(fragmentName);
+ return SetupRedactionInterstitialFragment.class.getName().equals(fragmentName);
}
@Override
@@ -68,7 +58,7 @@
super.onApplyThemeResource(theme, resid, first);
}
- public static class SetupEncryptionInterstitialFragment extends RedactionInterstitialFragment
+ public static class SetupRedactionInterstitialFragment extends RedactionInterstitialFragment
implements NavigationBar.NavigationBarListener {
@Override
diff --git a/src/com/android/settings/TrustedCredentialsSettings.java b/src/com/android/settings/TrustedCredentialsSettings.java
index 62394de..e1f0109 100644
--- a/src/com/android/settings/TrustedCredentialsSettings.java
+++ b/src/com/android/settings/TrustedCredentialsSettings.java
@@ -66,7 +66,7 @@
import java.util.HashMap;
import java.util.List;
-public class TrustedCredentialsSettings extends InstrumentedFragment {
+public class TrustedCredentialsSettings extends OptionsMenuFragment {
private static final String TAG = "TrustedCredentialsSettings";
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index e688450..96ef8e9 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -20,7 +20,6 @@
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
-import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
@@ -46,14 +45,13 @@
import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.EnumSet;
-import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
-public class UserCredentialsSettings extends InstrumentedFragment implements OnItemClickListener {
+public class UserCredentialsSettings extends OptionsMenuFragment implements OnItemClickListener {
private static final String TAG = "UserCredentialsSettings";
private View mRootView;
diff --git a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
index daa0c82..a1c8bc5 100644
--- a/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAutoclickPreferenceFragment.java
@@ -25,7 +25,6 @@
import android.widget.Switch;
import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SeekBarPreference;
import com.android.settings.widget.SwitchBar;
diff --git a/src/com/android/settings/applications/ProcStatsData.java b/src/com/android/settings/applications/ProcStatsData.java
index 5e330b8..3c81374 100644
--- a/src/com/android/settings/applications/ProcStatsData.java
+++ b/src/com/android/settings/applications/ProcStatsData.java
@@ -28,11 +28,14 @@
import android.util.Log;
import android.util.SparseArray;
-import com.android.internal.app.IProcessStats;
import com.android.internal.app.ProcessMap;
-import com.android.internal.app.ProcessStats;
-import com.android.internal.app.ProcessStats.ProcessDataCollection;
-import com.android.internal.app.ProcessStats.TotalMemoryUseCollection;
+import com.android.internal.app.procstats.DumpUtils;
+import com.android.internal.app.procstats.IProcessStats;
+import com.android.internal.app.procstats.ProcessState;
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.ProcessStats.ProcessDataCollection;
+import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
+import com.android.internal.app.procstats.ServiceState;
import com.android.internal.util.MemInfoReader;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -142,7 +145,7 @@
long now = SystemClock.uptimeMillis();
- memTotalTime = ProcessStats.dumpSingleTime(null, null, mStats.mMemFactorDurations,
+ memTotalTime = DumpUtils.dumpSingleTime(null, null, mStats.mMemFactorDurations,
mStats.mMemFactor, mStats.mStartTime, now);
ProcessStats.TotalMemoryUseCollection totalMem = new ProcessStats.TotalMemoryUseCollection(
@@ -274,26 +277,26 @@
for (int iv = 0; iv < vpkgs.size(); iv++) {
final ProcessStats.PackageState st = vpkgs.valueAt(iv);
for (int iproc = 0; iproc < st.mProcesses.size(); iproc++) {
- final ProcessStats.ProcessState pkgProc = st.mProcesses.valueAt(iproc);
- final ProcessStats.ProcessState proc = mStats.mProcesses.get(pkgProc.mName,
- pkgProc.mUid);
+ final ProcessState pkgProc = st.mProcesses.valueAt(iproc);
+ final ProcessState proc = mStats.mProcesses.get(pkgProc.getName(),
+ pkgProc.getUid());
if (proc == null) {
Log.w(TAG, "No process found for pkg " + st.mPackageName
- + "/" + st.mUid + " proc name " + pkgProc.mName);
+ + "/" + st.mUid + " proc name " + pkgProc.getName());
continue;
}
- ProcStatsEntry ent = entriesMap.get(proc.mName, proc.mUid);
+ ProcStatsEntry ent = entriesMap.get(proc.getName(), proc.getUid());
if (ent == null) {
ent = new ProcStatsEntry(proc, st.mPackageName, bgTotals, runTotals,
mUseUss);
if (ent.mRunWeight > 0) {
- if (DEBUG) Log.d(TAG, "Adding proc " + proc.mName + "/"
- + proc.mUid + ": time="
+ if (DEBUG) Log.d(TAG, "Adding proc " + proc.getName() + "/"
+ + proc.getUid() + ": time="
+ ProcessStatsUi.makeDuration(ent.mRunDuration) + " ("
+ ((((double) ent.mRunDuration) / memTotalTime) * 100)
+ "%)"
+ " pss=" + ent.mAvgRunMem);
- entriesMap.put(proc.mName, proc.mUid, ent);
+ entriesMap.put(proc.getName(), proc.getUid(), ent);
procEntries.add(ent);
}
} else {
@@ -315,18 +318,18 @@
for (int iv = 0; iv < vpkgs.size(); iv++) {
ProcessStats.PackageState ps = vpkgs.valueAt(iv);
for (int is = 0, NS = ps.mServices.size(); is < NS; is++) {
- ProcessStats.ServiceState ss = ps.mServices.valueAt(is);
- if (ss.mProcessName != null) {
- ProcStatsEntry ent = entriesMap.get(ss.mProcessName,
+ ServiceState ss = ps.mServices.valueAt(is);
+ if (ss.getProcessName() != null) {
+ ProcStatsEntry ent = entriesMap.get(ss.getProcessName(),
uids.keyAt(iu));
if (ent != null) {
if (DEBUG) Log.d(TAG, "Adding service " + ps.mPackageName
- + "/" + ss.mName + "/" + uids.keyAt(iu) + " to proc "
- + ss.mProcessName);
+ + "/" + ss.getName() + "/" + uids.keyAt(iu)
+ + " to proc " + ss.getProcessName());
ent.addService(ss);
} else {
- Log.w(TAG, "No process " + ss.mProcessName + "/" + uids.keyAt(iu)
- + " for service " + ss.mName);
+ Log.w(TAG, "No process " + ss.getProcessName() + "/"
+ + uids.keyAt(iu) + " for service " + ss.getName());
}
}
}
diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java
index 55f7bb8..36d397e 100644
--- a/src/com/android/settings/applications/ProcStatsEntry.java
+++ b/src/com/android/settings/applications/ProcStatsEntry.java
@@ -24,7 +24,9 @@
import android.util.Log;
import android.util.SparseArray;
-import com.android.internal.app.ProcessStats;
+import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.ProcessState;
+import com.android.internal.app.procstats.ServiceState;
import java.util.ArrayList;
import java.util.Collections;
@@ -52,14 +54,14 @@
ArrayMap<String, ArrayList<Service>> mServices = new ArrayMap<String, ArrayList<Service>>(1);
- public ProcStatsEntry(ProcessStats.ProcessState proc, String packageName,
+ public ProcStatsEntry(ProcessState proc, String packageName,
ProcessStats.ProcessDataCollection tmpBgTotals,
ProcessStats.ProcessDataCollection tmpRunTotals, boolean useUss) {
- ProcessStats.computeProcessData(proc, tmpBgTotals, 0);
- ProcessStats.computeProcessData(proc, tmpRunTotals, 0);
- mPackage = proc.mPackage;
- mUid = proc.mUid;
- mName = proc.mName;
+ proc.computeProcessData(tmpBgTotals, 0);
+ proc.computeProcessData(tmpRunTotals, 0);
+ mPackage = proc.getPackage();
+ mUid = proc.getUid();
+ mName = proc.getName();
mPackages.add(packageName);
mBgDuration = tmpBgTotals.totalTime;
mAvgBgMem = useUss ? tmpBgTotals.avgUss : tmpBgTotals.avgPss;
@@ -69,7 +71,7 @@
mAvgRunMem = useUss ? tmpRunTotals.avgUss : tmpRunTotals.avgPss;
mMaxRunMem = useUss ? tmpRunTotals.maxUss : tmpRunTotals.maxPss;
mRunWeight = mAvgRunMem * (double) mRunDuration;
- if (DEBUG) Log.d(TAG, "New proc entry " + proc.mName + ": dur=" + mBgDuration
+ if (DEBUG) Log.d(TAG, "New proc entry " + proc.getName() + ": dur=" + mBgDuration
+ " avgpss=" + mAvgBgMem + " weight=" + mBgWeight);
}
@@ -149,7 +151,7 @@
+ mUid + " in process " + mName);
continue;
}
- ProcessStats.ProcessState pkgProc = pkgState.mProcesses.get(mName);
+ ProcessState pkgProc = pkgState.mProcesses.get(mName);
if (pkgProc == null) {
Log.w(TAG, "No process " + mName + " found in package state "
+ mPackages.get(ipkg) + "/" + mUid);
@@ -252,11 +254,11 @@
}
}
- public void addService(ProcessStats.ServiceState svc) {
- ArrayList<Service> services = mServices.get(svc.mPackage);
+ public void addService(ServiceState svc) {
+ ArrayList<Service> services = mServices.get(svc.getPackage());
if (services == null) {
services = new ArrayList<Service>();
- mServices.put(svc.mPackage, services);
+ mServices.put(svc.getPackage(), services);
}
services.add(new Service(svc));
}
@@ -306,13 +308,12 @@
final String mProcess;
final long mDuration;
- public Service(ProcessStats.ServiceState service) {
- mPackage = service.mPackage;
- mName = service.mName;
- mProcess = service.mProcessName;
- mDuration = ProcessStats.dumpSingleServiceTime(null, null, service,
- ProcessStats.ServiceState.SERVICE_RUN,
- ProcessStats.STATE_NOTHING, 0, 0);
+ public Service(ServiceState service) {
+ mPackage = service.getPackage();
+ mName = service.getName();
+ mProcess = service.getProcessName();
+ mDuration = service.dumpTime(null, null,
+ ServiceState.SERVICE_RUN, ProcessStats.STATE_NOTHING, 0, 0);
}
public Service(Parcel in) {
diff --git a/src/com/android/settings/applications/ProcessStatsBase.java b/src/com/android/settings/applications/ProcessStatsBase.java
index ee53bf9..66c0371 100644
--- a/src/com/android/settings/applications/ProcessStatsBase.java
+++ b/src/com/android/settings/applications/ProcessStatsBase.java
@@ -23,7 +23,7 @@
import android.widget.ArrayAdapter;
import android.widget.Spinner;
-import com.android.internal.app.ProcessStats;
+import com.android.internal.app.procstats.ProcessStats;
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
diff --git a/src/com/android/settings/applications/ProcessStatsMemDetail.java b/src/com/android/settings/applications/ProcessStatsMemDetail.java
index e60a368..6c7b90a 100644
--- a/src/com/android/settings/applications/ProcessStatsMemDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsMemDetail.java
@@ -24,7 +24,7 @@
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.android.internal.app.ProcessStats;
+import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java
index b26f4a7..fd0d7a7 100644
--- a/src/com/android/settings/applications/ProcessStatsUi.java
+++ b/src/com/android/settings/applications/ProcessStatsUi.java
@@ -27,7 +27,7 @@
import android.view.MenuInflater;
import android.view.MenuItem;
-import com.android.internal.app.ProcessStats;
+import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
diff --git a/src/com/android/settings/sim/SimSettings.java b/src/com/android/settings/sim/SimSettings.java
index adc9594..e783923 100644
--- a/src/com/android/settings/sim/SimSettings.java
+++ b/src/com/android/settings/sim/SimSettings.java
@@ -71,6 +71,10 @@
private int mNumSlots;
private Context mContext;
+ private int mPhoneCount = TelephonyManager.getDefault().getPhoneCount();
+ private int[] mCallState = new int[mPhoneCount];
+ private PhoneStateListener[] mPhoneStateListener = new PhoneStateListener[mPhoneCount];
+
public SimSettings() {
super(DISALLOW_CONFIG_SIM);
}
@@ -177,7 +181,12 @@
} else if (sir == null) {
simPref.setSummary(R.string.sim_selection_required_pref);
}
- simPref.setEnabled(mSelectableSubInfos.size() >= 1);
+
+ boolean callStateIdle = isCallStateIdle();
+ final boolean ecbMode = SystemProperties.getBoolean(
+ TelephonyProperties.PROPERTY_INECM_MODE, false);
+ // Enable data preference in msim mode and call state idle
+ simPref.setEnabled((mSelectableSubInfos.size() >= 1) && callStateIdle && !ecbMode);
}
private void updateCallValues() {
@@ -199,10 +208,17 @@
public void onResume() {
super.onResume();
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+ updateSubscriptions();
final TelephonyManager tm =
(TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
- tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
- updateSubscriptions();
+ if (mSelectableSubInfos.size() > 1) {
+ Log.d(TAG, "Register for call state change");
+ for (int i = 0; i < mPhoneCount; i++) {
+ int subId = mSelectableSubInfos.get(i).getSubscriptionId();
+ tm.listen(getPhoneStateListener(i, subId),
+ PhoneStateListener.LISTEN_CALL_STATE);
+ }
+ }
}
@Override
@@ -210,25 +226,30 @@
super.onPause();
mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
- tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ for (int i = 0; i < mPhoneCount; i++) {
+ if (mPhoneStateListener[i] != null) {
+ tm.listen(mPhoneStateListener[i], PhoneStateListener.LISTEN_NONE);
+ mPhoneStateListener[i] = null;
+ }
+ }
}
- private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ private PhoneStateListener getPhoneStateListener(int phoneId, int subId) {
// Disable Sim selection for Data when voice call is going on as changing the default data
// sim causes a modem reset currently and call gets disconnected
// ToDo : Add subtext on disabled preference to let user know that default data sim cannot
// be changed while call is going on
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
- final Preference pref = findPreference(KEY_CELLULAR_DATA);
- if (pref != null) {
- final boolean ecbMode = SystemProperties.getBoolean(
- TelephonyProperties.PROPERTY_INECM_MODE, false);
- pref.setEnabled((state == TelephonyManager.CALL_STATE_IDLE) && !ecbMode);
+ final int i = phoneId;
+ mPhoneStateListener[phoneId] = new PhoneStateListener(subId) {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
+ mCallState[i] = state;
+ updateCellularDataValues();
}
- }
- };
+ };
+ return mPhoneStateListener[phoneId];
+ }
@Override
public boolean onPreferenceTreeClick(final Preference preference) {
@@ -327,4 +348,15 @@
return result;
}
};
+
+ private boolean isCallStateIdle() {
+ boolean callStateIdle = true;
+ for (int i = 0; i < mCallState.length; i++) {
+ if (TelephonyManager.CALL_STATE_IDLE != mCallState[i]) {
+ callStateIdle = false;
+ }
+ }
+ Log.d(TAG, "isCallStateIdle " + callStateIdle);
+ return callStateIdle;
+ }
}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 2163245..af95056 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -140,6 +140,7 @@
private int mRemovingUserId = -1;
private int mAddedUserId = 0;
private boolean mAddingUser;
+ private String mAddingUserName;
private UserCapabilities mUserCaps;
private boolean mShouldUpdateUserList = true;
private final Object mUserLock = new Object();
@@ -402,15 +403,13 @@
}
private UserInfo createRestrictedProfile() {
- UserInfo newUserInfo = mUserManager.createRestrictedProfile(
- getResources().getString(R.string.user_new_profile_name));
+ UserInfo newUserInfo = mUserManager.createRestrictedProfile(mAddingUserName);
assignDefaultPhoto(newUserInfo);
return newUserInfo;
}
private UserInfo createTrustedUser() {
- UserInfo newUserInfo = mUserManager.createUser(
- getResources().getString(R.string.user_new_user_name), 0);
+ UserInfo newUserInfo = mUserManager.createUser(mAddingUserName, 0);
if (newUserInfo != null) {
assignDefaultPhoto(newUserInfo);
}
@@ -418,6 +417,7 @@
}
private void onManageUserClicked(int userId, boolean newUser) {
+ mAddingUser = false;
if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
Bundle extras = new Bundle();
extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
@@ -453,6 +453,7 @@
private void onUserCreated(int userId) {
mAddedUserId = userId;
+ mAddingUser = false;
if (mUserManager.getUserInfo(userId).isRestricted()) {
showDialog(DIALOG_SETUP_PROFILE);
} else {
@@ -653,6 +654,8 @@
private void addUserNow(final int userType) {
synchronized (mUserLock) {
mAddingUser = true;
+ mAddingUserName = userType == USER_TYPE_USER ? getString(R.string.user_new_user_name)
+ : getString(R.string.user_new_profile_name);
//updateUserList();
new Thread() {
public void run() {
@@ -664,10 +667,10 @@
user = createRestrictedProfile();
}
if (user == null) {
+ mAddingUser = false;
return;
}
synchronized (mUserLock) {
- mAddingUser = false;
if (userType == USER_TYPE_USER) {
mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
mHandler.sendMessage(mHandler.obtainMessage(
@@ -775,7 +778,7 @@
UserPreference pref = new UserPreference(getPrefContext(), null,
UserPreference.USERID_UNKNOWN, null, null);
pref.setEnabled(false);
- pref.setTitle(R.string.user_new_user_name);
+ pref.setTitle(mAddingUserName);
pref.setIcon(getEncircledDefaultIcon());
userPreferences.add(pref);
}
@@ -830,7 +833,7 @@
boolean moreUsers = mUserManager.canAddMoreUsers();
mAddUser.setOrder(Preference.DEFAULT_ORDER);
preferenceScreen.addPreference(mAddUser);
- mAddUser.setEnabled(moreUsers);
+ mAddUser.setEnabled(moreUsers && !mAddingUser);
if (!moreUsers) {
mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
} else {
@@ -950,6 +953,7 @@
}
} else if (pref == mEmergencyInfoPreference) {
Intent intent = new Intent(ACTION_EDIT_EMERGENCY_INFO);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
return false;
@@ -990,7 +994,6 @@
@Override
public void onDismiss(DialogInterface dialog) {
synchronized (mUserLock) {
- mAddingUser = false;
mRemovingUserId = -1;
updateUserList();
}
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 6b035fd..a13e29d 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.Editable;
@@ -29,6 +30,7 @@
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.Spinner;
import android.widget.TextView;
@@ -45,7 +47,8 @@
* {@see AppDialog}
*/
class ConfigDialog extends AlertDialog implements TextWatcher,
- View.OnClickListener, AdapterView.OnItemSelectedListener {
+ View.OnClickListener, AdapterView.OnItemSelectedListener,
+ CompoundButton.OnCheckedChangeListener {
private final KeyStore mKeyStore = KeyStore.getInstance();
private final DialogInterface.OnClickListener mListener;
private final VpnProfile mProfile;
@@ -72,6 +75,7 @@
private Spinner mIpsecServerCert;
private CheckBox mSaveLogin;
private CheckBox mShowOptions;
+ private CheckBox mAlwaysOnVpn;
ConfigDialog(Context context, DialogInterface.OnClickListener listener,
VpnProfile profile, boolean editing, boolean exists) {
@@ -108,6 +112,7 @@
mIpsecServerCert = (Spinner) mView.findViewById(R.id.ipsec_server_cert);
mSaveLogin = (CheckBox) mView.findViewById(R.id.save_login);
mShowOptions = (CheckBox) mView.findViewById(R.id.show_options);
+ mAlwaysOnVpn = (CheckBox) mView.findViewById(R.id.always_on_vpn);
// Second, copy values from the profile.
mName.setText(mProfile.name);
@@ -124,13 +129,21 @@
mL2tpSecret.setText(mProfile.l2tpSecret);
mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
mIpsecSecret.setText(mProfile.ipsecSecret);
- loadCertificates(mIpsecUserCert, Credentials.USER_PRIVATE_KEY,
- 0, mProfile.ipsecUserCert);
+ loadCertificates(mIpsecUserCert, Credentials.USER_PRIVATE_KEY, 0, mProfile.ipsecUserCert);
loadCertificates(mIpsecCaCert, Credentials.CA_CERTIFICATE,
R.string.vpn_no_ca_cert, mProfile.ipsecCaCert);
loadCertificates(mIpsecServerCert, Credentials.USER_CERTIFICATE,
R.string.vpn_no_server_cert, mProfile.ipsecServerCert);
mSaveLogin.setChecked(mProfile.saveLogin);
+ mAlwaysOnVpn.setChecked(mProfile.key.equals(VpnUtils.getLockdownVpn()));
+ mAlwaysOnVpn.setOnCheckedChangeListener(this);
+ // Update SaveLogin checkbox after Always-on checkbox is updated
+ updateSaveLoginStatus();
+
+ // Hide lockdown VPN on devices that require IMS authentication
+ if (SystemProperties.getBoolean("persist.radio.imsregrequired", false)) {
+ mAlwaysOnVpn.setVisibility(View.GONE);
+ }
// Third, add listeners to required fields.
mName.addTextChangedListener(this);
@@ -242,6 +255,27 @@
public void onNothingSelected(AdapterView<?> parent) {
}
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ if (compoundButton == mAlwaysOnVpn) {
+ updateSaveLoginStatus();
+ }
+ }
+
+ public boolean isVpnAlwaysOn() {
+ return mAlwaysOnVpn.isChecked();
+ }
+
+ private void updateSaveLoginStatus() {
+ if (mAlwaysOnVpn.isChecked()) {
+ mSaveLogin.setChecked(true);
+ mSaveLogin.setEnabled(false);
+ } else {
+ mSaveLogin.setChecked(mProfile.saveLogin);
+ mSaveLogin.setEnabled(true);
+ }
+ }
+
private void showAdvancedOptions() {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
mShowOptions.setVisibility(View.GONE);
diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java
index d145ba3..fc49fd8 100644
--- a/src/com/android/settings/vpn2/ConfigDialogFragment.java
+++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java
@@ -22,6 +22,7 @@
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
+import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.os.Bundle;
import android.os.RemoteException;
@@ -112,8 +113,10 @@
// Flush out old version of profile
disconnect(profile);
+ updateLockdownVpn(dialog.isVpnAlwaysOn(), profile);
+
// If we are not editing, connect!
- if (!dialog.isEditing()) {
+ if (!dialog.isEditing() && !VpnUtils.isVpnLockdown(profile.key)) {
try {
connect(profile);
} catch (RemoteException e) {
@@ -128,15 +131,7 @@
KeyStore keyStore = KeyStore.getInstance();
keyStore.delete(Credentials.VPN + profile.key, KeyStore.UID_SELF);
- // If this was the current lockdown VPN, clear it.
- if (Arrays.equals(profile.key.getBytes(), keyStore.get(Credentials.LOCKDOWN_VPN))) {
- keyStore.delete(Credentials.LOCKDOWN_VPN);
- try {
- mService.updateLockdownVpn();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to clear lockdown VPN configuration");
- }
- }
+ updateLockdownVpn(false, profile);
}
dismiss();
}
@@ -147,6 +142,30 @@
super.onCancel(dialog);
}
+ private void updateLockdownVpn(boolean isVpnAlwaysOn, VpnProfile profile) {
+ // Save lockdown vpn
+ if (isVpnAlwaysOn) {
+ // Show toast if vpn profile is not valid
+ if (!profile.isValidLockdownProfile()) {
+ Toast.makeText(getContext(), R.string.vpn_lockdown_config_error,
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ // Update only if lockdown vpn has been changed
+ if (!VpnUtils.isVpnLockdown(profile.key)) {
+ final ConnectivityManager conn = ConnectivityManager.from(getActivity());
+ conn.setAlwaysOnVpnPackageForUser(UserHandle.myUserId(), null);
+ VpnUtils.setLockdownVpn(getContext(), profile.key);
+ }
+ } else {
+ // update only if lockdown vpn has been changed
+ if (VpnUtils.isVpnLockdown(profile.key)) {
+ VpnUtils.clearLockdownVpn(getContext());
+ }
+ }
+ }
+
private void connect(VpnProfile profile) throws RemoteException {
try {
mService.startLegacyVpn(profile);
diff --git a/src/com/android/settings/vpn2/LockdownConfigFragment.java b/src/com/android/settings/vpn2/LockdownConfigFragment.java
deleted file mode 100644
index 8f19fa6..0000000
--- a/src/com/android/settings/vpn2/LockdownConfigFragment.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.vpn2;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.security.Credentials;
-import android.security.KeyStore;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.Toast;
-
-import com.android.internal.net.VpnConfig;
-import com.android.internal.net.VpnProfile;
-import com.android.settings.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Dialog to configure always-on VPN.
- */
-public class LockdownConfigFragment extends DialogFragment {
- private List<VpnProfile> mProfiles;
- private List<AppVpnInfo> mApps;
- private List<CharSequence> mTitles;
- private int mCurrentIndex;
-
- private static final String TAG_LOCKDOWN = "lockdown";
- private static final String LOG_TAG = "LockdownConfigFragment";
-
- private static class TitleAdapter extends ArrayAdapter<CharSequence> {
- public TitleAdapter(Context context, List<CharSequence> objects) {
- super(context, com.android.internal.R.layout.select_dialog_singlechoice_material,
- android.R.id.text1, objects);
- }
- }
-
- public static void show(VpnSettings parent) {
- if (!parent.isAdded()) return;
-
- final LockdownConfigFragment dialog = new LockdownConfigFragment();
- dialog.show(parent.getFragmentManager(), TAG_LOCKDOWN);
- }
-
- private void initProfiles(KeyStore keyStore, Resources res) {
- final ConnectivityManager cm = ConnectivityManager.from(getActivity());
- final String lockdownKey = VpnUtils.getLockdownVpn();
- final String alwaysOnPackage = cm.getAlwaysOnVpnPackageForUser(UserHandle.myUserId());
-
- // Legacy VPN has a separate always-on mechanism which takes over the whole device, so
- // this option is restricted to the primary user only.
- if (UserManager.get(getContext()).isPrimaryUser()) {
- mProfiles = VpnSettings.loadVpnProfiles(keyStore, VpnProfile.TYPE_PPTP);
- } else {
- mProfiles = Collections.<VpnProfile>emptyList();
- }
- mApps = VpnSettings.getVpnApps(getActivity(), /* includeProfiles */ false);
-
- mTitles = new ArrayList<>(1 + mProfiles.size() + mApps.size());
- mTitles.add(res.getText(R.string.vpn_lockdown_none));
- mCurrentIndex = 0;
-
- // Add true lockdown VPNs to the list first.
- for (VpnProfile profile : mProfiles) {
- if (TextUtils.equals(profile.key, lockdownKey)) {
- mCurrentIndex = mTitles.size();
- }
- mTitles.add(profile.name);
- }
-
- // Add third-party app VPNs (VpnService) for the current profile to set as always-on.
- for (AppVpnInfo app : mApps) {
- try {
- String appName = VpnConfig.getVpnLabel(getContext(), app.packageName).toString();
- if (TextUtils.equals(app.packageName, alwaysOnPackage)) {
- mCurrentIndex = mTitles.size();
- }
- mTitles.add(appName);
- } catch (PackageManager.NameNotFoundException pkgNotFound) {
- Log.w(LOG_TAG, "VPN package not found: '" + app.packageName + "'", pkgNotFound);
- }
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
- final KeyStore keyStore = KeyStore.getInstance();
-
- initProfiles(keyStore, context.getResources());
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
-
- builder.setTitle(R.string.vpn_menu_lockdown);
-
- final View view = dialogInflater.inflate(R.layout.vpn_lockdown_editor, null, false);
- final ListView listView = (ListView) view.findViewById(android.R.id.list);
- listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
- listView.setAdapter(new TitleAdapter(context, mTitles));
- listView.setItemChecked(mCurrentIndex, true);
- builder.setView(view);
-
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final int newIndex = listView.getCheckedItemPosition();
- if (mCurrentIndex == newIndex) return;
-
- final ConnectivityManager conn = ConnectivityManager.from(getActivity());
-
- if (newIndex == 0) {
- keyStore.delete(Credentials.LOCKDOWN_VPN);
- conn.setAlwaysOnVpnPackageForUser(UserHandle.myUserId(), null);
- } else if (newIndex <= mProfiles.size()) {
- final VpnProfile profile = mProfiles.get(newIndex - 1);
- if (!profile.isValidLockdownProfile()) {
- Toast.makeText(context, R.string.vpn_lockdown_config_error,
- Toast.LENGTH_LONG).show();
- return;
- }
- conn.setAlwaysOnVpnPackageForUser(UserHandle.myUserId(), null);
- keyStore.put(Credentials.LOCKDOWN_VPN, profile.key.getBytes(),
- KeyStore.UID_SELF, /* flags */ 0);
- } else {
- keyStore.delete(Credentials.LOCKDOWN_VPN);
-
- final AppVpnInfo appVpn = mApps.get(newIndex - 1 - mProfiles.size());
- conn.setAlwaysOnVpnPackageForUser(appVpn.userId, appVpn.packageName);
- }
-
- // kick profiles since we changed them
- conn.updateLockdownVpn();
- }
- });
-
- return builder.create();
- }
-}
-
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index 64403dd..f605896 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -80,7 +80,6 @@
private static final int RESCAN_MESSAGE = 0;
private static final int RESCAN_INTERVAL_MS = 1000;
- private static final String EXTRA_PICK_LOCKDOWN = "android.net.vpn.PICK_LOCKDOWN";
private static final NetworkRequest VPN_REQUEST = new NetworkRequest.Builder()
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
@@ -143,11 +142,6 @@
menu.getItem(i).setEnabled(!mUnavailable);
}
}
-
- // Hide lockdown VPN on devices that require IMS authentication
- if (SystemProperties.getBoolean("persist.radio.imsregrequired", false)) {
- menu.findItem(R.id.vpn_lockdown).setVisible(false);
- }
}
@Override
@@ -163,10 +157,6 @@
ConfigDialogFragment.show(this, profile, true /* editing */, false /* exists */);
return true;
}
- case R.id.vpn_lockdown: {
- LockdownConfigFragment.show(this);
- return true;
- }
}
return super.onOptionsItemSelected(item);
}
@@ -186,12 +176,6 @@
getEmptyTextView().setText(R.string.vpn_no_vpns_added);
}
- final boolean pickLockdown = getActivity()
- .getIntent().getBooleanExtra(EXTRA_PICK_LOCKDOWN, false);
- if (pickLockdown) {
- LockdownConfigFragment.show(this);
- }
-
// Start monitoring
mConnectivityManager.registerNetworkCallback(VPN_REQUEST, mNetworkCallback);
diff --git a/src/com/android/settings/vpn2/VpnUtils.java b/src/com/android/settings/vpn2/VpnUtils.java
index 122816a..6afa79b 100644
--- a/src/com/android/settings/vpn2/VpnUtils.java
+++ b/src/com/android/settings/vpn2/VpnUtils.java
@@ -21,7 +21,9 @@
import android.security.KeyStore;
/**
- * Utility functions for vpn
+ * Utility functions for vpn.
+ *
+ * Keystore methods should only be called in system user
*/
public class VpnUtils {
@@ -35,4 +37,15 @@
// Always notify ConnectivityManager after keystore update
context.getSystemService(ConnectivityManager.class).updateLockdownVpn();
}
+
+ public static void setLockdownVpn(Context context, String lockdownKey) {
+ KeyStore.getInstance().put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes(),
+ KeyStore.UID_SELF, /* flags */ 0);
+ // Always notify ConnectivityManager after keystore update
+ context.getSystemService(ConnectivityManager.class).updateLockdownVpn();
+ }
+
+ public static boolean isVpnLockdown(String key) {
+ return key.equals(getLockdownVpn());
+ }
}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 54bd3d0..ee6b503 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -682,7 +682,7 @@
if (TextUtils.isEmpty(ipAddr)) return R.string.wifi_ip_settings_invalid_ip_address;
Inet4Address inetAddr = getIPv4Address(ipAddr);
- if (inetAddr == null) {
+ if (inetAddr == null || inetAddr.equals(Inet4Address.ANY)) {
return R.string.wifi_ip_settings_invalid_ip_address;
}
@@ -697,6 +697,8 @@
// Set the hint as default after user types in ip address
mNetworkPrefixLengthView.setText(mConfigUi.getContext().getString(
R.string.wifi_network_prefix_length_hint));
+ } catch (IllegalArgumentException e) {
+ return R.string.wifi_ip_settings_invalid_ip_address;
}
String gateway = mGatewayView.getText().toString();
@@ -715,6 +717,9 @@
if (gatewayAddr == null) {
return R.string.wifi_ip_settings_invalid_gateway;
}
+ if (gatewayAddr.isMulticastAddress()) {
+ return R.string.wifi_ip_settings_invalid_gateway;
+ }
staticIpConfiguration.gateway = gatewayAddr;
}