Merge "Fixes a crash in setup wizard when adding a lock screen." into nyc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ceea92e..b6fb084 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2449,6 +2449,22 @@
                        android:value="com.android.settings.notification.NotificationAccessSettings" />
         </activity>
 
+        <activity android:name="Settings$VrListenersSettingsActivity"
+                  android:label="@string/vr_listeners_title"
+                  android:taskAffinity="">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.VR_LISTENER_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.applications.VrListenerSettings" />
+        </activity>
+
+
         <activity android:name="Settings$ZenAccessSettingsActivity"
                   android:label="@string/manage_zen_access_title"
                   android:taskAffinity="">
diff --git a/res/layout/setup_redaction_interstitial.xml b/res/layout/setup_redaction_interstitial.xml
index 00d338e..59b7e08 100644
--- a/res/layout/setup_redaction_interstitial.xml
+++ b/res/layout/setup_redaction_interstitial.xml
@@ -72,6 +72,15 @@
                 android:layout_height="wrap_content"
                 android:text="@string/lock_screen_notifications_summary_disable" />
 
+            <!-- CheckBox is styled with SuwRadioButton to make it line up nicely with the radios
+                 above. -->
+            <CheckBox
+                android:id="@+id/lockscreen_remote_input"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/suw_check_box_margin_top"
+                android:text="@string/lockscreen_remote_input"
+                style="@style/SuwRadioButton" />
         </RadioGroup>
 
         <CheckBox
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 62476f7..b9207cd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6019,6 +6019,23 @@
         It will also be able to dismiss notifications or trigger action buttons they contain.
     </string>
 
+    <!-- Title for managing VR (virtual reality) helper services. [CHAR LIMIT=50] -->
+    <string name="vr_listeners_title">VR helper services</string>
+
+    <!-- String to show in the list of vr listeners, when none is installed -->
+    <string name="no_vr_listeners">No installed apps have requested to be run as VR helper services.</string>
+
+    <!-- Title for a warning message about security implications of enabling a VR
+          listener, displayed as a dialog message. [CHAR LIMIT=NONE] -->
+    <string name="vr_listener_security_warning_title">Allow VR service access for
+         <xliff:g id="service" example="VrCore">%1$s</xliff:g>?</string>
+    <!-- Summary for a warning message about security implications of enabling a VR
+          listener, displayed as a dialog message. [CHAR LIMIT=NONE] -->
+    <string name="vr_listener_security_warning_summary">
+        <xliff:g id="vr_listener_name">%1$s</xliff:g> will be able to run when you are using
+        applications in virtual reality mode.
+    </string>
+
     <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
     <string name="manage_zen_access_title">Do Not Disturb access</string>
 
@@ -6883,6 +6900,8 @@
     <!-- Description of allowing overlay setting [CHAR LIMIT=NONE] -->
     <string name="allow_overlay_description">This permission allows an app to display on top of other apps you\u2019re using and may interfere with your use of the interface in other applications, or change what you think you are seeing in other applications.</string>
 
+    <!-- Keyword for VR settinsg -->
+    <string name="keywords_vr_listener">vr virtual reality listener stereo helper service</string>
     <!-- Keyword for SYSTEM_ALERT_WINDOW -->
     <string name="keywords_system_alert_window">system alert window dialog draw on top other apps</string>
     <!-- Main settings screen item's title to go into the overlay settings screen [CHAR LIMIT=30] -->
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 9b404df..5adf20c 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -49,6 +49,16 @@
     </PreferenceScreen>
 
     <PreferenceScreen
+        android:key="enabled_vr_listeners"
+        android:title="@string/vr_listeners_title"
+        android:fragment="com.android.settings.applications.VrListenerSettings"
+        settings:keywords="@string/keywords_vr_listener">
+        <extra
+            android:name="classname"
+            android:value="com.android.settings.Settings$VrListenersSettingsActivity" />
+    </PreferenceScreen>
+
+    <PreferenceScreen
         android:key="write_settings_apps"
         android:title="@string/write_settings"
         android:fragment="com.android.settings.applications.ManageApplications"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 95aa700..458fa2f 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -95,6 +95,7 @@
     public static class NotificationStationActivity extends SettingsActivity { /* empty */ }
     public static class UserSettingsActivity extends SettingsActivity { /* empty */ }
     public static class NotificationAccessSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class VrListenerSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ConditionProviderSettingsActivity extends SettingsActivity { /* empty */ }
     public static class UsbSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 0338020..43bcb57 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -42,6 +42,7 @@
 import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
+import android.util.Log;
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settings.wifi.WifiApDialog;
@@ -65,6 +66,8 @@
 
     private static final int DIALOG_AP_SETTINGS = 1;
 
+    private static final String TAG = "TetheringSettings";
+
     private SwitchPreference mUsbTether;
 
     private WifiApEnabler mWifiApEnabler;
@@ -95,6 +98,8 @@
     private WifiConfiguration mWifiConfig = null;
     private ConnectivityManager mCm;
 
+    private boolean mRestartWifiApAfterConfigChange;
+
     private boolean mUsbConnected;
     private boolean mMassStorageActive;
 
@@ -141,7 +146,7 @@
         mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS);
         mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
 
-        mCm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+        mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
 
         mUsbRegexs = mCm.getTetherableUsbRegexs();
         mWifiRegexs = mCm.getTetherableWifiRegexs();
@@ -183,6 +188,8 @@
 
         mCreateNetwork = findPreference(WIFI_AP_SSID_AND_SECURITY);
 
+        mRestartWifiApAfterConfigChange = false;
+
         if (mWifiConfig == null) {
             final String s = activity.getString(
                     com.android.internal.R.string.wifi_tether_configure_ssid_default);
@@ -222,6 +229,12 @@
                 updateState(available.toArray(new String[available.size()]),
                         active.toArray(new String[active.size()]),
                         errored.toArray(new String[errored.size()]));
+                if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED
+                        && mRestartWifiApAfterConfigChange) {
+                    mRestartWifiApAfterConfigChange = false;
+                    Log.d(TAG, "Restarting WifiAp due to prior config change.");
+                    startTethering(TETHERING_WIFI);
+                }
             } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
                 mMassStorageActive = true;
                 updateState();
@@ -391,8 +404,9 @@
         }
 
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter == null)
+        if (adapter == null) {
             return;
+        }
         int btState = adapter.getState();
         if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
             mBluetoothTether.setEnabled(false);
@@ -402,8 +416,8 @@
             mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
         } else {
             BluetoothPan bluetoothPan = mBluetoothPan.get();
-            if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null &&
-                    bluetoothPan.isTetheringOn()) {
+            if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null
+                    && bluetoothPan.isTetheringOn()) {
                 mBluetoothTether.setChecked(true);
                 mBluetoothTether.setEnabled(true);
                 int bluetoothTethered = bluetoothPan.getConnectedDevices().size();
@@ -506,11 +520,12 @@
                  * TODO: update config on a running access point when framework support is added
                  */
                 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
-                    mWifiManager.setWifiApEnabled(null, false);
-                    mWifiManager.setWifiApEnabled(mWifiConfig, true);
-                } else {
-                    mWifiManager.setWifiApConfiguration(mWifiConfig);
+                    Log.d("TetheringSettings",
+                            "Wifi AP config changed while enabled, stop and restart");
+                    mRestartWifiApAfterConfigChange = true;
+                    mCm.stopTethering(TETHERING_WIFI);
                 }
+                mWifiManager.setWifiApConfiguration(mWifiConfig);
                 int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);
                 mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),
                         mWifiConfig.SSID,
diff --git a/src/com/android/settings/applications/VrListenerSettings.java b/src/com/android/settings/applications/VrListenerSettings.java
new file mode 100644
index 0000000..571e85d
--- /dev/null
+++ b/src/com/android/settings/applications/VrListenerSettings.java
@@ -0,0 +1,51 @@
+/*
+ * 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.applications;
+
+import android.provider.Settings;
+import android.service.vr.VrListenerService;
+
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.utils.ManagedServiceSettings;
+
+public class VrListenerSettings extends ManagedServiceSettings {
+    private static final String TAG = VrListenerSettings.class.getSimpleName();
+    private static final Config CONFIG = getVrListenerConfig();
+
+    private static final Config getVrListenerConfig() {
+        final Config c = new Config();
+        c.tag = TAG;
+        c.setting = Settings.Secure.ENABLED_VR_LISTENERS;
+        c.intentAction = VrListenerService.SERVICE_INTERFACE;
+        c.permission = android.Manifest.permission.BIND_VR_LISTENER_SERVICE;
+        c.noun = "vr listener";
+        c.warningDialogTitle = R.string.vr_listener_security_warning_title;
+        c.warningDialogSummary = R.string.vr_listener_security_warning_summary;
+        c.emptyText = R.string.no_vr_listeners;
+        return c;
+    }
+
+    @Override
+    protected Config getConfig() {
+        return CONFIG;
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return MetricsEvent.VR_MANAGE_LISTENERS;
+    }
+}
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index dd5ecf1..2226bc2 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -272,6 +272,7 @@
                     suggestion.intent.getComponent(),
                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                     PackageManager.DONT_KILL_APP);
+            mSuggestionParser.markCategoryDone(suggestion.category);
         }
     }
 
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
index 2656f17..b414627 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
@@ -175,7 +175,7 @@
         if (!isChangingConfigurations()) {
             if (mSidecar != null) {
                 mSidecar.cancelEnrollment();
-                getFragmentManager().beginTransaction().remove(mSidecar).commit();
+                getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
             }
             finish();
         }
@@ -186,7 +186,7 @@
         if (mSidecar != null) {
             mSidecar.setListener(null);
             mSidecar.cancelEnrollment();
-            getFragmentManager().beginTransaction().remove(mSidecar).commit();
+            getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
             mSidecar = null;
         }
         super.onBackPressed();
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index b40fbda..0111a38 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -23,6 +23,8 @@
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settings.R;
+import com.android.settings.utils.ManagedServiceSettings;
+import com.android.settings.utils.ServiceListing;
 
 public class NotificationAccessSettings extends ManagedServiceSettings {
     private static final String TAG = NotificationAccessSettings.class.getSimpleName();
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index f1546aa..d38c580 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -42,7 +42,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settings.R;
-import com.android.settings.notification.ManagedServiceSettings.Config;
+import com.android.settings.utils.ManagedServiceSettings.Config;
+import com.android.settings.utils.ServiceListing;
 
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
index 8ae2274..05f42d8 100644
--- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java
+++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java
@@ -35,6 +35,7 @@
 import android.widget.TextView;
 
 import com.android.settings.R;
+import com.android.settings.utils.ServiceListing;
 
 import java.lang.ref.WeakReference;
 import java.text.Collator;
diff --git a/src/com/android/settings/print/PrintSettingsFragment.java b/src/com/android/settings/print/PrintSettingsFragment.java
index 44bdf0c..fb80f2932 100644
--- a/src/com/android/settings/print/PrintSettingsFragment.java
+++ b/src/com/android/settings/print/PrintSettingsFragment.java
@@ -584,21 +584,24 @@
             // updated until this function is called again
             List<PrintServiceInfo> services =
                     printManager.getPrintServices(PrintManager.ALL_SERVICES);
-            final int serviceCount = services.size();
-            for (int i = 0; i < serviceCount; i++) {
-                PrintServiceInfo service = services.get(i);
 
-                ComponentName componentName = new ComponentName(
-                        service.getResolveInfo().serviceInfo.packageName,
-                        service.getResolveInfo().serviceInfo.name);
+            if (services != null) {
+                final int serviceCount = services.size();
+                for (int i = 0; i < serviceCount; i++) {
+                    PrintServiceInfo service = services.get(i);
 
-                data = new SearchIndexableRaw(context);
-                data.key = componentName.flattenToString();
-                data.title = service.getResolveInfo().loadLabel(packageManager).toString();
-                data.summaryOn = context.getString(R.string.print_feature_state_on);
-                data.summaryOff = context.getString(R.string.print_feature_state_off);
-                data.screenTitle = screenTitle;
-                indexables.add(data);
+                    ComponentName componentName = new ComponentName(
+                            service.getResolveInfo().serviceInfo.packageName,
+                            service.getResolveInfo().serviceInfo.name);
+
+                    data = new SearchIndexableRaw(context);
+                    data.key = componentName.flattenToString();
+                    data.title = service.getResolveInfo().loadLabel(packageManager).toString();
+                    data.summaryOn = context.getString(R.string.print_feature_state_on);
+                    data.summaryOff = context.getString(R.string.print_feature_state_off);
+                    data.screenTitle = screenTitle;
+                    indexables.add(data);
+                }
             }
 
             return indexables;
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 1560326..4b060a0 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -40,10 +40,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceScreen;
 import android.util.Log;
@@ -61,7 +59,6 @@
 import com.android.settings.DimmableIconPreference;
 import com.android.settings.OwnerInfoSettings;
 import com.android.settings.R;
-import com.android.settings.SelectableEditTextPreference;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
@@ -144,7 +141,7 @@
     private int mAddedUserId = 0;
     private boolean mAddingUser;
     private UserCapabilities mUserCaps;
-
+    private boolean mShouldUpdateUserList = true;
     private final Object mUserLock = new Object();
     private UserManager mUserManager;
     private SparseArray<Bitmap> mUserIcons = new SparseArray<Bitmap>();
@@ -236,12 +233,13 @@
         mLockScreenSettings = (PreferenceGroup) findPreference("lock_screen_settings");
         mAddUserWhenLocked = (RestrictedSwitchPreference) findPreference("add_users_when_locked");
         mEmergencyInfoPreference = findPreference(KEY_EMERGENCY_INFO);
-        loadProfile();
         setHasOptionsMenu(true);
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
-        context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null,
-                mHandler);
+        context.registerReceiverAsUser(mUserChangeReceiver, UserHandle.ALL, filter, null, mHandler);
+        loadProfile();
+        updateUserList();
+        mShouldUpdateUserList = false;
     }
 
     @Override
@@ -250,8 +248,16 @@
 
         if (!mUserCaps.mEnabled) return;
 
-        loadProfile();
-        updateUserList();
+        if (mShouldUpdateUserList) {
+            loadProfile();
+            updateUserList();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        mShouldUpdateUserList = true;
+        super.onPause();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
similarity index 98%
rename from src/com/android/settings/notification/ManagedServiceSettings.java
rename to src/com/android/settings/utils/ManagedServiceSettings.java
index 56c7b69..e198955 100644
--- a/src/com/android/settings/notification/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.notification;
+package com.android.settings.utils;
 
 import android.annotation.Nullable;
 import android.app.AlertDialog;
@@ -34,6 +34,7 @@
 import android.view.View;
 import android.widget.TextView;
 import com.android.settings.R;
+import com.android.settings.notification.EmptyTextSettings;
 
 import java.util.Collections;
 import java.util.List;
diff --git a/src/com/android/settings/notification/ServiceListing.java b/src/com/android/settings/utils/ServiceListing.java
similarity index 98%
rename from src/com/android/settings/notification/ServiceListing.java
rename to src/com/android/settings/utils/ServiceListing.java
index 161611d..dfca5a3 100644
--- a/src/com/android/settings/notification/ServiceListing.java
+++ b/src/com/android/settings/utils/ServiceListing.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.notification;
+package com.android.settings.utils;
 
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
@@ -32,7 +32,7 @@
 import android.provider.Settings;
 import android.util.Slog;
 
-import com.android.settings.notification.ManagedServiceSettings.Config;
+import com.android.settings.utils.ManagedServiceSettings.Config;
 
 import java.util.ArrayList;
 import java.util.Arrays;