diff --git a/res/layout/lock_to_app_instructions.xml b/res/layout/lock_to_app_instructions.xml
new file mode 100644
index 00000000000..dfe0970b249
--- /dev/null
+++ b/res/layout/lock_to_app_instructions.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index eef43a76842..5fe0b90c640 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -147,4 +147,7 @@
32dp
16dp
+
+ 16dp
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7afc8c3b946..3a7957951c3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5400,4 +5400,18 @@
On
Off
+
+
+ Lock-to-app
+
+ Lock-to-app locks the display in a single app.\n\n\nTo start Lock-to-app
+
+ 1\t\tTurn the setting on
+
+ 2\t\tStart an app you want
+
+ 3\t\tPress and hold the recent apps button $
+
+ Use screen lock
diff --git a/res/xml/lock_to_app_settings.xml b/res/xml/lock_to_app_settings.xml
new file mode 100644
index 00000000000..f9a0b6c34d5
--- /dev/null
+++ b/res/xml/lock_to_app_settings.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index c8f3e02916f..0dbddea63eb 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -102,4 +102,10 @@
android:persistent="false"
android:fragment="com.android.settings.AdvancedSecuritySettings"/>
+
+
+
diff --git a/src/com/android/settings/LockToAppSettings.java b/src/com/android/settings/LockToAppSettings.java
new file mode 100644
index 00000000000..267972870fc
--- /dev/null
+++ b/src/com/android/settings/LockToAppSettings.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.DynamicDrawableSpan;
+import android.text.style.ImageSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.widget.SwitchBar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Location access settings.
+ */
+public class LockToAppSettings extends SettingsPreferenceFragment
+ implements SwitchBar.OnSwitchChangeListener, Indexable {
+ private static final String TAG = "LockToAppSettings";
+
+ private static final CharSequence KEY_USE_SCREEN_LOCK = "use_screen_lock";
+ private static final int CHANGE_LOCK_METHOD_REQUEST = 123;
+
+ private SwitchBar mSwitchBar;
+ private SwitchPreference mUseScreenLock;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final SettingsActivity activity = (SettingsActivity) getActivity();
+
+ mSwitchBar = activity.getSwitchBar();
+ mSwitchBar.addOnSwitchChangeListener(this);
+ mSwitchBar.show();
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+
+ mSwitchBar.removeOnSwitchChangeListener(this);
+ mSwitchBar.hide();
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (isLockToAppEnabled()) {
+ mSwitchBar.setChecked(true);
+ createPreferenceHierarchy();
+ } else {
+ mSwitchBar.setChecked(false);
+ createSetupInstructions();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.lock_to_app_instructions, null);
+ }
+
+ private boolean isLockToAppEnabled() {
+ try {
+ return Settings.System.getInt(getContentResolver(), Settings.System.LOCK_TO_APP_ENABLED)
+ != 0;
+ } catch (SettingNotFoundException e) {
+ return false;
+ }
+ }
+
+ private boolean isLockScreenEnabled() {
+ try {
+ return Settings.System.getInt(getContentResolver(),
+ Settings.System.LOCK_TO_APP_EXIT_LOCKED) != 0;
+ } catch (SettingNotFoundException e) {
+ return false;
+ }
+ }
+
+ private void setLockToAppEnabled(boolean isEnabled) {
+ Settings.System.putInt(getContentResolver(), Settings.System.LOCK_TO_APP_ENABLED,
+ isEnabled ? 1 : 0);
+ }
+
+ private void setUseLockScreen(boolean useLockScreen) {
+ if (useLockScreen) {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+ if (lockPatternUtils.getKeyguardStoredPasswordQuality()
+ == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
+ chooseLockIntent.putExtra(
+ ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ startActivityForResult(chooseLockIntent, CHANGE_LOCK_METHOD_REQUEST);
+ return;
+ }
+ }
+ setUseLockScreenSetting(useLockScreen);
+ }
+
+ private void setUseLockScreenSetting(boolean useLockScreen) {
+ mUseScreenLock.setChecked(useLockScreen);
+ Settings.System.putInt(getContentResolver(), Settings.System.LOCK_TO_APP_EXIT_LOCKED,
+ useLockScreen ? 1 : 0);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == CHANGE_LOCK_METHOD_REQUEST) {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+ setUseLockScreenSetting(lockPatternUtils.getKeyguardStoredPasswordQuality()
+ != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+ }
+ }
+
+ private PreferenceScreen createPreferenceHierarchy() {
+ PreferenceScreen root = getPreferenceScreen();
+ if (root != null) {
+ root.removeAll();
+ }
+ getView().findViewById(R.id.instructions_area).setVisibility(View.INVISIBLE);
+ addPreferencesFromResource(R.xml.lock_to_app_settings);
+ root = getPreferenceScreen();
+
+ mUseScreenLock = (SwitchPreference) root.findPreference(KEY_USE_SCREEN_LOCK);
+ mUseScreenLock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ setUseLockScreen((boolean) newValue);
+ return true;
+ }
+ });
+ mUseScreenLock.setChecked(isLockScreenEnabled());
+
+ return root;
+ }
+
+ private void createSetupInstructions() {
+ PreferenceScreen root = getPreferenceScreen();
+ if (root != null) {
+ root.removeAll();
+ }
+ final View view = getView();
+ view.findViewById(R.id.instructions_area).setVisibility(View.VISIBLE);
+
+ final Resources r = Resources.getSystem();
+ TextView tv = (TextView) view.findViewById(R.id.lock_to_app_start_step3);
+ ImageSpan imageSpan = new ImageSpan(getActivity(),
+ BitmapFactory.decodeResource(r, com.android.internal.R.drawable.ic_recent),
+ DynamicDrawableSpan.ALIGN_BOTTOM);
+
+ String descriptionString = getResources().getString(R.string.lock_to_app_start_step3);
+ SpannableString description =
+ new SpannableString(descriptionString.replace('$', ' '));
+ int index = descriptionString.indexOf('$');
+ if (index >= 0) {
+ description.setSpan(imageSpan, index, index + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+
+ // Make icon fit.
+ float width = imageSpan.getDrawable().getIntrinsicWidth();
+ float height = imageSpan.getDrawable().getIntrinsicHeight();
+ int lineHeight = tv.getLineHeight();
+ imageSpan.getDrawable().setBounds(0, 0, (int) (lineHeight * width / height), lineHeight);
+
+ tv.setText(description);
+ }
+
+ /**
+ * Listens to the state change of the lock-to-app master switch.
+ */
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ setLockToAppEnabled(isChecked);
+ if (isChecked) {
+ createPreferenceHierarchy();
+ } else {
+ createSetupInstructions();
+ }
+ }
+
+ /**
+ * For search
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List getRawDataToIndex(Context context, boolean enabled) {
+ final List result = new ArrayList();
+
+ final Resources res = context.getResources();
+
+ // Add fragment title
+ SearchIndexableRaw data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.lock_to_app_title);
+ data.screenTitle = res.getString(R.string.lock_to_app_title);
+ result.add(data);
+
+ // Lock-to-app description.
+ data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.lock_to_app_description);
+ data.screenTitle = res.getString(R.string.lock_to_app_title);
+ result.add(data);
+
+ // Lock-to-app use screen lock.
+ data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.lock_to_app_screen_lock);
+ data.screenTitle = res.getString(R.string.lock_to_app_title);
+ result.add(data);
+
+ return result;
+ }
+ };
+}
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index b3d90dd977b..d8f69c3ca5d 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -23,6 +23,7 @@ import com.android.settings.DevelopmentSettings;
import com.android.settings.DeviceInfoSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.HomeSettings;
+import com.android.settings.LockToAppSettings;
import com.android.settings.PrivacySettings;
import com.android.settings.SecuritySettings;
import com.android.settings.WallpaperTypeSettings;
@@ -127,6 +128,7 @@ public final class Ranking {
// Security
sRankMap.put(SecuritySettings.class.getName(), RANK_SECURITY);
sRankMap.put(ChooseLockGeneric.ChooseLockGenericFragment.class.getName(), RANK_SECURITY);
+ sRankMap.put(LockToAppSettings.class.getName(), RANK_SECURITY);
// IMEs
sRankMap.put(InputMethodAndLanguageSettings.class.getName(), RANK_IME);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 5f380ebdb2f..fe4e82dfa3a 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -25,6 +25,7 @@ import com.android.settings.DevelopmentSettings;
import com.android.settings.DeviceInfoSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.HomeSettings;
+import com.android.settings.LockToAppSettings;
import com.android.settings.PrivacySettings;
import com.android.settings.R;
import com.android.settings.SecuritySettings;
@@ -199,6 +200,13 @@ public final class SearchIndexableResources {
ChooseLockGeneric.ChooseLockGenericFragment.class.getName(),
R.drawable.ic_settings_security));
+ sResMap.put(LockToAppSettings.class.getName(),
+ new SearchIndexableResource(
+ Ranking.getRankForClassName(LockToAppSettings.class.getName()),
+ NO_DATA_RES_ID,
+ LockToAppSettings.class.getName(),
+ R.drawable.ic_settings_security));
+
sResMap.put(InputMethodAndLanguageSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(InputMethodAndLanguageSettings.class.getName()),