Merge remote-tracking branch 'goog/stage-aosp-master' into HEAD

This commit is contained in:
Bill Yi
2017-10-24 11:32:26 -07:00
1180 changed files with 62213 additions and 26378 deletions

View File

@@ -146,7 +146,8 @@ public class ApnEditor extends SettingsPreferenceFragment
Telephony.Carriers.ROAMING_PROTOCOL, // 20
Telephony.Carriers.MVNO_TYPE, // 21
Telephony.Carriers.MVNO_MATCH_DATA, // 22
Telephony.Carriers.EDITED // 23
Telephony.Carriers.EDITED, // 23
Telephony.Carriers.USER_EDITABLE //24
};
private static final int ID_INDEX = 0;
@@ -172,6 +173,7 @@ public class ApnEditor extends SettingsPreferenceFragment
private static final int MVNO_TYPE_INDEX = 21;
private static final int MVNO_MATCH_DATA_INDEX = 22;
private static final int EDITED_INDEX = 23;
private static final int USER_EDITABLE_INDEX = 24;
@Override
@@ -282,7 +284,8 @@ public class ApnEditor extends SettingsPreferenceFragment
Log.d(TAG, "onCreate: EDITED " + mCursor.getInt(EDITED_INDEX));
// if it's not a USER_EDITED apn, check if it's read-only
if (mCursor.getInt(EDITED_INDEX) != Telephony.Carriers.USER_EDITED &&
apnTypesMatch(mReadOnlyApnTypes, mCursor.getString(TYPE_INDEX))) {
(mCursor.getInt(USER_EDITABLE_INDEX) == 0 ||
apnTypesMatch(mReadOnlyApnTypes, mCursor.getString(TYPE_INDEX)))) {
Log.d(TAG, "onCreate: apnTypesMatch; read-only APN");
mReadOnlyApn = true;
disableAllFields();

View File

@@ -193,7 +193,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
mUnavailable = isUiRestricted();
setHasOptionsMenu(!mUnavailable);
if (mUnavailable) {
addPreferencesFromResource(R.xml.empty_settings);
addPreferencesFromResource(R.xml.placeholder_prefs);
return;
}

View File

@@ -29,6 +29,7 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.CustomDialogPreference;
public class BugreportPreference extends CustomDialogPreference {

View File

@@ -47,14 +47,16 @@ import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils;
import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.security.ConfigureKeyGuardDialog;
import com.android.settings.vpn2.VpnUtils;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
/**
* CredentialStorage handles KeyStore reset, unlock, and install.
*
@@ -72,14 +74,14 @@ import java.io.IOException;
* KeyGuard: ON
* Action: confirm key guard
* Notes: user had key guard but no keystore and upgraded from pre-ICS
* OR user had key guard and pre-ICS keystore password which was then reset
* OR user had key guard and pre-ICS keystore password which was then reset
*
* KeyStore: LOCKED
* KeyGuard: OFF/ON
* Action: old unlock dialog
* Notes: assume old password, need to use it to unlock.
* if unlock, ensure key guard before install.
* if reset, treat as UNINITALIZED/OFF
* if unlock, ensure key guard before install.
* if reset, treat as UNINITALIZED/OFF
*
* KeyStore: UNLOCKED
* KeyGuard: OFF
@@ -101,7 +103,7 @@ public final class CredentialStorage extends Activity {
// This is the minimum acceptable password quality. If the current password quality is
// lower than this, keystore should not be activated.
static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
public static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;
@@ -169,7 +171,8 @@ public final class CredentialStorage extends Activity {
}
case UNLOCKED: {
if (!checkKeyGuardQuality()) {
new ConfigureKeyGuardDialog();
final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
return;
}
installIfAvailable();
@@ -188,7 +191,8 @@ public final class CredentialStorage extends Activity {
private void ensureKeyGuard() {
if (!checkKeyGuardQuality()) {
// key guard not setup, doing so will initialize keystore
new ConfigureKeyGuardDialog();
final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
// will return to onResume after Activity
return;
}
@@ -306,8 +310,7 @@ public final class CredentialStorage extends Activity {
* Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
*/
private class ResetDialog
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
{
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private boolean mResetConfirmed;
private ResetDialog() {
@@ -321,11 +324,13 @@ public final class CredentialStorage extends Activity {
dialog.show();
}
@Override public void onClick(DialogInterface dialog, int button) {
@Override
public void onClick(DialogInterface dialog, int button) {
mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
@Override public void onDismiss(DialogInterface dialog) {
@Override
public void onDismiss(DialogInterface dialog) {
if (mResetConfirmed) {
mResetConfirmed = false;
if (confirmKeyGuard(CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST)) {
@@ -342,7 +347,8 @@ public final class CredentialStorage extends Activity {
*/
private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {
@Override protected Boolean doInBackground(Void... unused) {
@Override
protected Boolean doInBackground(Void... unused) {
// Clear all the users credentials could have been installed in for this user.
new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId());
@@ -362,14 +368,15 @@ public final class CredentialStorage extends Activity {
}
}
@Override protected void onPostExecute(Boolean success) {
@Override
protected void onPostExecute(Boolean success) {
if (success) {
Toast.makeText(CredentialStorage.this,
R.string.credentials_erased, Toast.LENGTH_SHORT).show();
R.string.credentials_erased, Toast.LENGTH_SHORT).show();
clearLegacyVpnIfEstablished();
} else {
Toast.makeText(CredentialStorage.this,
R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
}
finish();
}
@@ -383,42 +390,6 @@ public final class CredentialStorage extends Activity {
}
}
/**
* Prompt for key guard configuration confirmation.
*/
private class ConfigureKeyGuardDialog
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
{
private boolean mConfigureConfirmed;
private ConfigureKeyGuardDialog() {
AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
.setTitle(android.R.string.dialog_alert_title)
.setMessage(R.string.credentials_configure_lock_screen_hint)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
dialog.setOnDismissListener(this);
dialog.show();
}
@Override public void onClick(DialogInterface dialog, int button) {
mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
@Override public void onDismiss(DialogInterface dialog) {
if (mConfigureConfirmed) {
mConfigureConfirmed = false;
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
MIN_PASSWORD_QUALITY);
startActivity(intent);
return;
}
finish();
}
}
/**
* Check that the caller is either certinstaller or Settings running in a profile of this user.
*/
@@ -504,8 +475,7 @@ public final class CredentialStorage extends Activity {
* On unsuccessful unlock, retry by calling handleUnlockOrInstall.
*/
private class UnlockDialog implements TextWatcher,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener
{
DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private boolean mUnlockConfirmed;
private final Button mButton;
@@ -544,21 +514,26 @@ public final class CredentialStorage extends Activity {
mButton.setEnabled(false);
}
@Override public void afterTextChanged(Editable editable) {
@Override
public void afterTextChanged(Editable editable) {
mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0);
}
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override public void onTextChanged(CharSequence s,int start, int before, int count) {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override public void onClick(DialogInterface dialog, int button) {
@Override
public void onClick(DialogInterface dialog, int button) {
mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
}
@Override public void onDismiss(DialogInterface dialog) {
@Override
public void onDismiss(DialogInterface dialog) {
if (mUnlockConfirmed) {
mUnlockConfirmed = false;
mError.setVisibility(View.VISIBLE);
@@ -567,16 +542,16 @@ public final class CredentialStorage extends Activity {
if (error == KeyStore.NO_ERROR) {
mRetriesRemaining = -1;
Toast.makeText(CredentialStorage.this,
R.string.credentials_enabled,
Toast.LENGTH_SHORT).show();
R.string.credentials_enabled,
Toast.LENGTH_SHORT).show();
// aha, now we are unlocked, switch to key guard.
// we'll end up back in onResume to install
ensureKeyGuard();
} else if (error == KeyStore.UNINITIALIZED) {
mRetriesRemaining = -1;
Toast.makeText(CredentialStorage.this,
R.string.credentials_erased,
Toast.LENGTH_SHORT).show();
R.string.credentials_erased,
Toast.LENGTH_SHORT).show();
// we are reset, we can now set new password with key guard
handleUnlockOrInstall();
} else if (error >= KeyStore.WRONG_PASSWORD) {

View File

@@ -888,7 +888,7 @@ public class CryptKeeper extends Activity implements TextView.OnEditorActionList
mPasswordEntry.setEnabled(false);
setBackFunctionality(false);
if (password.length() >= LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
if (password.length() >= LockPatternUtils.MIN_LOCK_PASSWORD_SIZE) {
new DecryptTask().execute(password);
} else {
// Allow user to make as many of these as they want.

View File

@@ -37,6 +37,8 @@ import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
public class CryptKeeperSettings extends InstrumentedPreferenceFragment {
private static final String TAG = "CryptKeeper";

View File

@@ -1,112 +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;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v14.preference.PreferenceDialogFragment;
import android.support.v7.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
public class CustomDialogPreference extends DialogPreference {
private CustomPreferenceDialogFragment mFragment;
public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomDialogPreference(Context context) {
super(context);
}
public boolean isDialogOpen() {
return getDialog() != null && getDialog().isShowing();
}
public Dialog getDialog() {
return mFragment != null ? mFragment.getDialog() : null;
}
protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
DialogInterface.OnClickListener listener) {
}
protected void onDialogClosed(boolean positiveResult) {
}
protected void onClick(DialogInterface dialog, int which) {
}
protected void onBindDialogView(View view) {
}
private void setFragment(CustomPreferenceDialogFragment fragment) {
mFragment = fragment;
}
public static class CustomPreferenceDialogFragment extends PreferenceDialogFragment {
public static CustomPreferenceDialogFragment newInstance(String key) {
final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
private CustomDialogPreference getCustomizablePreference() {
return (CustomDialogPreference) getPreference();
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
getCustomizablePreference().setFragment(this);
getCustomizablePreference().onPrepareDialogBuilder(builder, this);
}
@Override
public void onDialogClosed(boolean positiveResult) {
getCustomizablePreference().onDialogClosed(positiveResult);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
getCustomizablePreference().onBindDialogView(view);
}
@Override
public void onClick(DialogInterface dialog, int which) {
super.onClick(dialog, which);
getCustomizablePreference().onClick(dialog, which);
}
}
}

View File

@@ -1,118 +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;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v14.preference.EditTextPreferenceDialogFragment;
import android.support.v7.preference.EditTextPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
public class CustomEditTextPreference extends EditTextPreference {
private CustomPreferenceDialogFragment mFragment;
public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomEditTextPreference(Context context) {
super(context);
}
public EditText getEditText() {
return mFragment != null ? (EditText) mFragment.getDialog().findViewById(android.R.id.edit)
: null;
}
public boolean isDialogOpen() {
return getDialog() != null && getDialog().isShowing();
}
public Dialog getDialog() {
return mFragment != null ? mFragment.getDialog() : null;
}
protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
DialogInterface.OnClickListener listener) {
}
protected void onDialogClosed(boolean positiveResult) {
}
protected void onClick(DialogInterface dialog, int which) {
}
protected void onBindDialogView(View view) {
}
private void setFragment(CustomPreferenceDialogFragment fragment) {
mFragment = fragment;
}
public static class CustomPreferenceDialogFragment extends EditTextPreferenceDialogFragment {
public static CustomPreferenceDialogFragment newInstance(String key) {
final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
final Bundle b = new Bundle(1);
b.putString(ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
private CustomEditTextPreference getCustomizablePreference() {
return (CustomEditTextPreference) getPreference();
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
getCustomizablePreference().onBindDialogView(view);
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
getCustomizablePreference().setFragment(this);
getCustomizablePreference().onPrepareDialogBuilder(builder, this);
}
@Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
getCustomizablePreference().onDialogClosed(positiveResult);
}
@Override
public void onClick(DialogInterface dialog, int which) {
super.onClick(dialog, which);
getCustomizablePreference().onClick(dialog, which);
}
}
}

View File

@@ -24,7 +24,6 @@ import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.deviceinfo.AdditionalSystemUpdatePreferenceController;
@@ -42,6 +41,7 @@ import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
import com.android.settings.deviceinfo.SecurityPatchPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.Arrays;

View File

@@ -17,18 +17,18 @@
package com.android.settings;
import android.content.Context;
import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.display.AmbientDisplayPreferenceController;
import com.android.settings.display.AutoBrightnessPreferenceController;
import com.android.settings.display.AutoRotatePreferenceController;
import com.android.settings.display.BrightnessLevelPreferenceController;
import com.android.settings.display.CameraGesturePreferenceController;
import com.android.settings.display.DozePreferenceController;
import com.android.settings.display.ColorModePreferenceController;
import com.android.settings.display.FontSizePreferenceController;
import com.android.settings.display.LiftToWakePreferenceController;
import com.android.settings.display.NightDisplayPreferenceController;
@@ -39,10 +39,9 @@ import com.android.settings.display.ThemePreferenceController;
import com.android.settings.display.TimeoutPreferenceController;
import com.android.settings.display.VrDisplayPreferenceController;
import com.android.settings.display.WallpaperPreferenceController;
import com.android.settings.gestures.DoubleTapScreenPreferenceController;
import com.android.settings.gestures.PickupGesturePreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.List;
@@ -50,12 +49,11 @@ import java.util.List;
public class DisplaySettings extends DashboardFragment {
private static final String TAG = "DisplaySettings";
public static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
public static final String KEY_DISPLAY_SIZE = "screen_zoom";
private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
private static final String KEY_PICK_UP = "gesture_pick_up_display_summary";
private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_display_summary";
private static final String KEY_AMBIENT_DISPLAY = "ambient_display";
@Override
public int getMetricsCategory() {
@@ -92,25 +90,24 @@ public class DisplaySettings extends DashboardFragment {
Context context, Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new AutoBrightnessPreferenceController(context, KEY_AUTO_BRIGHTNESS));
controllers.add(new AutoRotatePreferenceController(context));
controllers.add(new AutoRotatePreferenceController(context, lifecycle));
controllers.add(new CameraGesturePreferenceController(context));
controllers.add(new DozePreferenceController(context));
controllers.add(new FontSizePreferenceController(context));
controllers.add(new LiftToWakePreferenceController(context));
controllers.add(new NightDisplayPreferenceController(context));
controllers.add(new NightModePreferenceController(context));
controllers.add(new ScreenSaverPreferenceController(context));
AmbientDisplayConfiguration ambientDisplayConfig = new AmbientDisplayConfiguration(context);
controllers.add(new PickupGesturePreferenceController(
context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(), KEY_PICK_UP));
controllers.add(new DoubleTapScreenPreferenceController(
context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(),
KEY_DOUBLE_TAP_SCREEN));
controllers.add(new AmbientDisplayPreferenceController(
context,
new AmbientDisplayConfiguration(context),
KEY_AMBIENT_DISPLAY));
controllers.add(new TapToWakePreferenceController(context));
controllers.add(new TimeoutPreferenceController(context, KEY_SCREEN_TIMEOUT));
controllers.add(new VrDisplayPreferenceController(context));
controllers.add(new WallpaperPreferenceController(context));
controllers.add(new ThemePreferenceController(context));
controllers.add(new BrightnessLevelPreferenceController(context, lifecycle));
controllers.add(new ColorModePreferenceController(context));
return controllers;
}
@@ -131,6 +128,8 @@ public class DisplaySettings extends DashboardFragment {
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_DISPLAY_SIZE);
keys.add(WallpaperPreferenceController.KEY_WALLPAPER);
keys.add(KEY_AMBIENT_DISPLAY);
return keys;
}

View File

@@ -1,364 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.Switch;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.DreamInfo;
import java.util.List;
public class DreamSettings extends SettingsPreferenceFragment implements
SwitchBar.OnSwitchChangeListener {
private static final String TAG = DreamSettings.class.getSimpleName();
static final boolean DEBUG = false;
private static final int DIALOG_WHEN_TO_DREAM = 1;
private static final String PACKAGE_SCHEME = "package";
private final PackageReceiver mPackageReceiver = new PackageReceiver();
private Context mContext;
private DreamBackend mBackend;
private SwitchBar mSwitchBar;
private MenuItem[] mMenuItemsWhenEnabled;
private boolean mRefreshing;
@Override
public int getHelpResource() {
return R.string.help_url_dreams;
}
@Override
public void onAttach(Activity activity) {
logd("onAttach(%s)", activity.getClass().getSimpleName());
super.onAttach(activity);
mContext = activity;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.DREAM;
}
@Override
public void onCreate(Bundle icicle) {
logd("onCreate(%s)", icicle);
super.onCreate(icicle);
mBackend = new DreamBackend(getActivity());
setHasOptionsMenu(true);
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (!mRefreshing) {
mBackend.setEnabled(isChecked);
refreshFromBackend();
}
}
@Override
public void onStart() {
logd("onStart()");
super.onStart();
}
@Override
public void onDestroyView() {
logd("onDestroyView()");
super.onDestroyView();
mSwitchBar.removeOnSwitchChangeListener(this);
mSwitchBar.hide();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
logd("onActivityCreated(%s)", savedInstanceState);
super.onActivityCreated(savedInstanceState);
TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);
emptyView.setText(R.string.screensaver_settings_disabled_prompt);
setEmptyView(emptyView);
final SettingsActivity sa = (SettingsActivity) getActivity();
mSwitchBar = sa.getSwitchBar();
mSwitchBar.addOnSwitchChangeListener(this);
mSwitchBar.show();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
logd("onCreateOptionsMenu()");
boolean isEnabled = mBackend.isEnabled();
// create "start" action
MenuItem start = createMenuItem(menu, R.string.screensaver_settings_dream_start,
MenuItem.SHOW_AS_ACTION_NEVER,
isEnabled, new Runnable(){
@Override
public void run() {
mBackend.startDreaming();
}});
// create "when to dream" overflow menu item
MenuItem whenToDream = createMenuItem(menu,
R.string.screensaver_settings_when_to_dream,
MenuItem.SHOW_AS_ACTION_NEVER,
isEnabled,
new Runnable() {
@Override
public void run() {
showDialog(DIALOG_WHEN_TO_DREAM);
}});
// create "help" overflow menu item (make sure it appears last)
super.onCreateOptionsMenu(menu, inflater);
mMenuItemsWhenEnabled = new MenuItem[] { start, whenToDream };
}
private MenuItem createMenuItem(Menu menu,
int titleRes, int actionEnum, boolean isEnabled, final Runnable onClick) {
MenuItem item = menu.add(titleRes);
item.setShowAsAction(actionEnum);
item.setEnabled(isEnabled);
item.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
onClick.run();
return true;
}
});
return item;
}
@Override
public Dialog onCreateDialog(int dialogId) {
logd("onCreateDialog(%s)", dialogId);
if (dialogId == DIALOG_WHEN_TO_DREAM)
return createWhenToDreamDialog();
return super.onCreateDialog(dialogId);
}
@Override
public int getDialogMetricsCategory(int dialogId) {
if (dialogId == DIALOG_WHEN_TO_DREAM) {
return MetricsEvent.DIALOG_DREAM_START_DELAY;
}
return 0;
}
private Dialog createWhenToDreamDialog() {
final CharSequence[] items = {
mContext.getString(R.string.screensaver_settings_summary_dock),
mContext.getString(R.string.screensaver_settings_summary_sleep),
mContext.getString(R.string.screensaver_settings_summary_either_short)
};
int initialSelection = mBackend.isActivatedOnDock() && mBackend.isActivatedOnSleep() ? 2
: mBackend.isActivatedOnDock() ? 0
: mBackend.isActivatedOnSleep() ? 1
: -1;
return new AlertDialog.Builder(mContext)
.setTitle(R.string.screensaver_settings_when_to_dream)
.setSingleChoiceItems(items, initialSelection, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
mBackend.setActivatedOnDock(item == 0 || item == 2);
mBackend.setActivatedOnSleep(item == 1 || item == 2);
dialog.dismiss();
}
})
.create();
}
@Override
public void onPause() {
logd("onPause()");
super.onPause();
mContext.unregisterReceiver(mPackageReceiver);
}
@Override
public void onResume() {
logd("onResume()");
super.onResume();
refreshFromBackend();
// listen for package changes
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme(PACKAGE_SCHEME);
mContext.registerReceiver(mPackageReceiver , filter);
}
public static int getSummaryResource(Context context) {
DreamBackend backend = new DreamBackend(context);
boolean isEnabled = backend.isEnabled();
boolean activatedOnSleep = backend.isActivatedOnSleep();
boolean activatedOnDock = backend.isActivatedOnDock();
boolean activatedOnEither = activatedOnSleep && activatedOnDock;
return !isEnabled ? R.string.screensaver_settings_summary_off
: activatedOnEither ? R.string.screensaver_settings_summary_either_long
: activatedOnSleep ? R.string.screensaver_settings_summary_sleep
: activatedOnDock ? R.string.screensaver_settings_summary_dock
: 0;
}
public static CharSequence getSummaryTextWithDreamName(Context context) {
DreamBackend backend = new DreamBackend(context);
boolean isEnabled = backend.isEnabled();
if (!isEnabled) {
return context.getString(R.string.screensaver_settings_summary_off);
} else {
return backend.getActiveDreamName();
}
}
private void refreshFromBackend() {
logd("refreshFromBackend()");
mRefreshing = true;
boolean dreamsEnabled = mBackend.isEnabled();
if (mSwitchBar.isChecked() != dreamsEnabled) {
mSwitchBar.setChecked(dreamsEnabled);
}
if (getPreferenceScreen() == null) {
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
}
getPreferenceScreen().removeAll();
if (dreamsEnabled) {
List<DreamBackend.DreamInfo> dreamInfos = mBackend.getDreamInfos();
final int N = dreamInfos.size();
for (int i = 0; i < N; i++) {
getPreferenceScreen().addPreference(
new DreamInfoPreference(getPrefContext(), dreamInfos.get(i)));
}
}
if (mMenuItemsWhenEnabled != null) {
for (MenuItem menuItem : mMenuItemsWhenEnabled) {
menuItem.setEnabled(dreamsEnabled);
}
}
mRefreshing = false;
}
private static void logd(String msg, Object... args) {
if (DEBUG) Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
}
private class DreamInfoPreference extends Preference {
private final DreamInfo mInfo;
public DreamInfoPreference(Context context, DreamInfo info) {
super(context);
mInfo = info;
setLayoutResource(R.layout.dream_info_row);
setTitle(mInfo.caption);
setIcon(mInfo.icon);
}
public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
// bind radio button
RadioButton radioButton = (RadioButton) holder.findViewById(android.R.id.button1);
radioButton.setChecked(mInfo.isActive);
radioButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
holder.itemView.onTouchEvent(event);
return false;
}
});
// bind settings button + divider
boolean showSettings = mInfo.settingsComponentName != null;
View settingsDivider = holder.findViewById(R.id.divider);
settingsDivider.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE);
ImageView settingsButton = (ImageView) holder.findViewById(android.R.id.button2);
settingsButton.setVisibility(showSettings ? View.VISIBLE : View.INVISIBLE);
settingsButton.setAlpha(mInfo.isActive ? 1f : Utils.DISABLED_ALPHA);
settingsButton.setEnabled(mInfo.isActive);
settingsButton.setFocusable(mInfo.isActive);
settingsButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
mBackend.launchSettings(mInfo);
}
});
}
@Override
public void performClick() {
if (mInfo.isActive)
return;
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
DreamInfoPreference preference =
(DreamInfoPreference) getPreferenceScreen().getPreference(i);
preference.mInfo.isActive = false;
preference.notifyChanged();
}
mInfo.isActive = true;
mBackend.setActiveDream(mInfo.componentName);
notifyChanged();
}
}
private class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
logd("PackageReceiver.onReceive");
refreshFromBackend();
}
}
}

View File

@@ -23,6 +23,8 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import com.android.settingslib.CustomEditTextPreference;
/**
* TODO: Add a soft dialpad for PIN entry.
*/
@@ -31,9 +33,9 @@ class EditPinPreference extends CustomEditTextPreference {
interface OnPinEnteredListener {
void onPinEntered(EditPinPreference preference, boolean positiveResult);
}
private OnPinEnteredListener mPinListener;
public EditPinPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -41,7 +43,7 @@ class EditPinPreference extends CustomEditTextPreference {
public EditPinPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setOnPinEnteredListener(OnPinEnteredListener listener) {
mPinListener = listener;
}

View File

@@ -20,7 +20,6 @@ import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -34,7 +33,6 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
@@ -106,7 +104,6 @@ public class EncryptionAndCredential extends SettingsPreferenceFragment implemen
}
}
// Credential storage
mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume()
@@ -168,7 +165,7 @@ public class EncryptionAndCredential extends SettingsPreferenceFragment implemen
@Override
protected int getHelpResource() {
return R.string.help_url_security;
return R.string.help_url_encryption;
}
/**
@@ -182,83 +179,57 @@ public class EncryptionAndCredential extends SettingsPreferenceFragment implemen
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final List<SearchIndexableResource> index = new ArrayList<SearchIndexableResource>();
final List<SearchIndexableResource> index = new ArrayList<>();
final DevicePolicyManager dpm = (DevicePolicyManager)
context.getSystemService(Context.DEVICE_POLICY_SERVICE);
final UserManager um = UserManager.get(context);
if (um.isAdminUser()) {
switch (dpm.getStorageEncryptionStatus()) {
case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
// The device is currently encrypted.
index.add(getSearchResource(context, R.xml.security_settings_encrypted));
break;
case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
// This device supports encryption but isn't encrypted.
index.add(getSearchResource(context, R.xml.security_settings_unencrypted));
break;
}
}
// Add everything. We will suppress some of them in getNonIndexableKeys()
index.add(getSearchResource(context, R.xml.encryption_and_credential));
index.add(getSearchResource(context, R.xml.security_settings_encrypted));
index.add(getSearchResource(context, R.xml.security_settings_unencrypted));
return index;
}
@Override
protected boolean isPageSearchEnabled(Context context) {
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
return um.isAdminUser();
}
private SearchIndexableResource getSearchResource(Context context, int xmlResId) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = xmlResId;
return sir;
}
@Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
final Resources res = context.getResources();
final String screenTitle = res.getString(
R.string.encryption_and_credential_settings_title);
SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = screenTitle;
data.screenTitle = screenTitle;
result.add(data);
final UserManager um = UserManager.get(context);
if (!um.isAdminUser()) {
int resId = um.isLinkedUser() ?
R.string.profile_info_settings_title : R.string.user_info_settings_title;
data = new SearchIndexableRaw(context);
data.title = res.getString(resId);
data.screenTitle = screenTitle;
result.add(data);
}
// Credential storage
if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
KeyStore keyStore = KeyStore.getInstance();
final int storageSummaryRes = keyStore.isHardwareBacked() ?
R.string.credential_storage_type_hardware :
R.string.credential_storage_type_software;
data = new SearchIndexableRaw(context);
data.title = res.getString(storageSummaryRes);
data.screenTitle = screenTitle;
result.add(data);
}
return result;
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = new ArrayList<String>();
final UserManager um = UserManager.get(context);
final List<String> keys = super.getNonIndexableKeys(context);
if (!isPageSearchEnabled(context)) {
return keys;
}
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
keys.add(KEY_CREDENTIALS_MANAGER);
keys.add(KEY_RESET_CREDENTIALS);
keys.add(KEY_CREDENTIALS_INSTALL);
keys.add(KEY_CREDENTIAL_STORAGE_TYPE);
keys.add(KEY_USER_CREDENTIALS);
}
final DevicePolicyManager dpm = (DevicePolicyManager)
context.getSystemService(Context.DEVICE_POLICY_SERVICE);
switch (dpm.getStorageEncryptionStatus()) {
case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
// The device is currently encrypted. Disable security_settings_unencrypted
keys.addAll(getNonIndexableKeysFromXml(
context, R.xml.security_settings_unencrypted));
break;
default:
// This device supports encryption but isn't encrypted.
keys.addAll(getNonIndexableKeysFromXml(
context, R.xml.security_settings_encrypted));
break;
}
return keys;

View File

@@ -17,23 +17,27 @@
package com.android.settings;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.setupwizardlib.GlifLayout;
import java.util.List;
@@ -53,6 +57,12 @@ public class EncryptionInterstitial extends SettingsActivity {
return modIntent;
}
@Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
resid = SetupWizardUtils.getTheme(getIntent());
super.onApplyThemeResource(theme, resid, first);
}
@Override
protected boolean isValidFragment(String fragmentName) {
return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
@@ -74,10 +84,8 @@ public class EncryptionInterstitial extends SettingsActivity {
layout.setFitsSystemWindows(false);
}
public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
implements View.OnClickListener, DialogInterface.OnClickListener {
private static final int ACCESSIBILITY_WARNING_DIALOG = 1;
public static class EncryptionInterstitialFragment extends InstrumentedFragment
implements View.OnClickListener {
private View mRequirePasswordToDecrypt;
private View mDontRequirePasswordToDecrypt;
@@ -164,7 +172,10 @@ public class EncryptionInterstitial extends SettingsActivity {
final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
if (accEn && !mPasswordRequired) {
setRequirePasswordState(false); // clear the UI state
showDialog(ACCESSIBILITY_WARNING_DIALOG);
AccessibilityWarningDialogFragment.newInstance(mRequestedPasswordQuality)
.show(
getChildFragmentManager(),
AccessibilityWarningDialogFragment.TAG);
} else {
setRequirePasswordState(true);
startLockIntent();
@@ -175,72 +186,93 @@ public class EncryptionInterstitial extends SettingsActivity {
}
}
@Override
public Dialog onCreateDialog(int dialogId) {
switch(dialogId) {
case ACCESSIBILITY_WARNING_DIALOG: {
final int titleId;
final int messageId;
switch (mRequestedPasswordQuality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
titleId = R.string.encrypt_talkback_dialog_require_pattern;
messageId = R.string.encrypt_talkback_dialog_message_pattern;
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
titleId = R.string.encrypt_talkback_dialog_require_pin;
messageId = R.string.encrypt_talkback_dialog_message_pin;
break;
default:
titleId = R.string.encrypt_talkback_dialog_require_password;
messageId = R.string.encrypt_talkback_dialog_message_password;
break;
}
List<AccessibilityServiceInfo> list =
AccessibilityManager.getInstance(getActivity())
.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
final CharSequence exampleAccessibility;
if (list.isEmpty()) {
// This should never happen. But we shouldn't crash
exampleAccessibility = "";
} else {
exampleAccessibility = list.get(0).getResolveInfo()
.loadLabel(getPackageManager());
}
return new AlertDialog.Builder(getActivity())
.setTitle(titleId)
.setMessage(getString(messageId, exampleAccessibility))
.setCancelable(true)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
}
default: throw new IllegalArgumentException();
}
}
@Override
public int getDialogMetricsCategory(int dialogId) {
if (dialogId == ACCESSIBILITY_WARNING_DIALOG) {
return MetricsEvent.DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY;
}
return 0;
}
private void setRequirePasswordState(boolean required) {
mPasswordRequired = required;
}
public void finish() {
Activity activity = getActivity();
if (activity == null) return;
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
activity.finish();
}
}
}
public static class AccessibilityWarningDialogFragment extends InstrumentedDialogFragment
implements DialogInterface.OnClickListener {
public static final String TAG = "AccessibilityWarningDialog";
public static AccessibilityWarningDialogFragment newInstance(int passwordQuality) {
AccessibilityWarningDialogFragment fragment = new AccessibilityWarningDialogFragment();
Bundle args = new Bundle(1);
args.putInt(EXTRA_PASSWORD_QUALITY, passwordQuality);
fragment.setArguments(args);
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final int titleId;
final int messageId;
switch (getArguments().getInt(EXTRA_PASSWORD_QUALITY)) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
titleId = R.string.encrypt_talkback_dialog_require_pattern;
messageId = R.string.encrypt_talkback_dialog_message_pattern;
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
titleId = R.string.encrypt_talkback_dialog_require_pin;
messageId = R.string.encrypt_talkback_dialog_message_pin;
break;
default:
titleId = R.string.encrypt_talkback_dialog_require_password;
messageId = R.string.encrypt_talkback_dialog_message_password;
break;
}
final Activity activity = getActivity();
List<AccessibilityServiceInfo> list =
AccessibilityManager.getInstance(activity)
.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
final CharSequence exampleAccessibility;
if (list.isEmpty()) {
// This should never happen. But we shouldn't crash
exampleAccessibility = "";
} else {
exampleAccessibility = list.get(0).getResolveInfo()
.loadLabel(activity.getPackageManager());
}
return new AlertDialog.Builder(activity)
.setTitle(titleId)
.setMessage(getString(messageId, exampleAccessibility))
.setCancelable(true)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
}
@Override
public int getMetricsCategory() {
return MetricsEvent.DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY;
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
setRequirePasswordState(true);
startLockIntent();
} else if (which == DialogInterface.BUTTON_NEGATIVE) {
setRequirePasswordState(false);
EncryptionInterstitialFragment fragment =
(EncryptionInterstitialFragment) getParentFragment();
if (fragment != null) {
if (which == DialogInterface.BUTTON_POSITIVE) {
fragment.setRequirePasswordState(true);
fragment.startLockIntent();
} else if (which == DialogInterface.BUTTON_NEGATIVE) {
fragment.setRequirePasswordState(false);
}
}
}
}

View File

@@ -39,7 +39,11 @@ public class HelpTrampoline extends Activity {
final Intent intent = HelpUtils.getHelpIntent(this, value, null);
if (intent != null) {
startActivity(intent);
/*
* TODO: b/38230998.
* Move to startActivity once the HelpUtils.getHelpIntent is refactored
*/
startActivityForResult(intent, 0);
}
} catch (Resources.NotFoundException | ActivityNotFoundException e) {

View File

@@ -289,6 +289,11 @@ public class IccLockSettings extends SettingsPreferenceFragment
getContext().unregisterReceiver(mSimStateReceiver);
}
@Override
protected int getHelpResource() {
return R.string.help_url_icc_lock;
}
@Override
public void onSaveInstanceState(Bundle out) {
// Need to store this state for slider open/close

View File

@@ -16,11 +16,14 @@
package com.android.settings;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -32,7 +35,10 @@ import android.os.Environment;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -47,13 +53,12 @@ import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.widget.CarrierDemoPasswordDialogFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
import java.util.List;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
* Confirm and execute a reset of the device to a clean "just out of the box"
* state. Multiple confirmations are required: first, a general "are you sure
@@ -64,18 +69,18 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
*
* This is the initial screen.
*/
public class MasterClear extends OptionsMenuFragment
implements CarrierDemoPasswordDialogFragment.Callback {
public class MasterClear extends OptionsMenuFragment {
private static final String TAG = "MasterClear";
private static final int KEYGUARD_REQUEST = 55;
static final String ERASE_EXTERNAL_EXTRA = "erase_sd";
static final String ERASE_ESIMS_EXTRA = "erase_esim";
private View mContentView;
private Button mInitiateButton;
private View mExternalStorageContainer;
private CheckBox mExternalStorage;
@VisibleForTesting CheckBox mExternalStorage;
private ScrollView mScrollView;
private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
@@ -115,9 +120,12 @@ public class MasterClear extends OptionsMenuFragment
}
}
private void showFinalConfirmation() {
@VisibleForTesting
void showFinalConfirmation() {
Bundle args = new Bundle();
args.putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());
// TODO: Offer the user a choice to wipe eSIMs when it is technically feasible to do so.
args.putBoolean(ERASE_ESIMS_EXTRA, true);
((SettingsActivity) getActivity()).startPreferencePanel(
this, MasterClearConfirm.class.getName(),
args, R.string.master_clear_confirm_title, null, null, 0);
@@ -127,15 +135,21 @@ public class MasterClear extends OptionsMenuFragment
* If the user clicks to begin the reset sequence, we next require a
* keyguard confirmation if the user has currently enabled one. If there
* is no keyguard available, we simply go to the final confirmation prompt.
*
* If the user is in demo mode, route to the demo mode app for confirmation.
*/
private final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
@VisibleForTesting
protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
public void onClick(View v) {
if ( Utils.isCarrierDemoUser(v.getContext())) {
// Require the carrier password before displaying the final confirmation.
final FragmentManager fm = getChildFragmentManager();
if (fm != null && !fm.isDestroyed()) {
new CarrierDemoPasswordDialogFragment().show(fm, null /* tag */);
public void onClick(View view) {
final Context context = view.getContext();
if (Utils.isDemoUser(context)) {
final ComponentName componentName = Utils.getDeviceOwnerComponent(context);
if (componentName != null) {
final Intent requestFactoryReset = new Intent()
.setPackage(componentName.getPackageName())
.setAction(Intent.ACTION_FACTORY_RESET);
context.startActivity(requestFactoryReset);
}
} else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
showFinalConfirmation();
@@ -143,11 +157,6 @@ public class MasterClear extends OptionsMenuFragment
}
};
@Override
public void onPasswordVerified() {
showFinalConfirmation();
}
/**
* In its initial state, the activity presents a button for the user to
* click in order to initiate a confirmation sequence. This method is
@@ -198,6 +207,14 @@ public class MasterClear extends OptionsMenuFragment
});
}
if (showWipeEuicc()) {
final View esimAlsoErased = mContentView.findViewById(R.id.also_erases_esim);
esimAlsoErased.setVisibility(View.VISIBLE);
final View noCancelMobilePlan = mContentView.findViewById(R.id.no_cancel_mobile_plan);
noCancelMobilePlan.setVisibility(View.VISIBLE);
}
final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
loadAccountList(um);
StringBuffer contentDescription = new StringBuffer();
@@ -220,6 +237,28 @@ public class MasterClear extends OptionsMenuFragment
mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
}
/**
* Whether to show strings indicating that the eUICC will be wiped.
*
* <p>We show the strings on any device which supports eUICC as long as the eUICC was ever
* provisioned (that is, at least one profile was ever downloaded onto it).
*/
@VisibleForTesting
boolean showWipeEuicc() {
Context context = getContext();
if (!isEuiccEnabled(context)) {
return false;
}
ContentResolver cr = context.getContentResolver();
return Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) != 0;
}
@VisibleForTesting
protected boolean isEuiccEnabled(Context context) {
EuiccManager euiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
return euiccManager.isEnabled();
}
@VisibleForTesting
boolean hasReachedBottom(final ScrollView scrollView) {
if (scrollView.getChildCount() < 1) {
@@ -349,7 +388,7 @@ public class MasterClear extends OptionsMenuFragment
final UserManager um = UserManager.get(context);
final boolean disallow = !um.isAdminUser() || RestrictedLockUtils.hasBaseUserRestriction(
context, UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
if (disallow && !Utils.isCarrierDemoUser(context)) {
if (disallow && !Utils.isDemoUser(context)) {
return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);

View File

@@ -24,7 +24,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.view.LayoutInflater;
import android.view.View;
@@ -51,6 +51,7 @@ public class MasterClearConfirm extends OptionsMenuFragment {
private View mContentView;
private boolean mEraseSdCard;
private boolean mEraseEsims;
/**
* The user has gone through the multiple confirmation, so now we go ahead
@@ -66,12 +67,14 @@ public class MasterClearConfirm extends OptionsMenuFragment {
final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
final OemLockManager oemLockManager = (OemLockManager)
getActivity().getSystemService(Context.OEM_LOCK_SERVICE);
if (pdbManager != null && !pdbManager.getOemUnlockEnabled() &&
if (pdbManager != null && !oemLockManager.isOemUnlockAllowed() &&
Utils.isDeviceProvisioned(getActivity())) {
// if OEM unlock is enabled, this will be wiped during FR process. If disabled, it
// will be wiped here, unless the device is still being provisioned, in which case
// the persistent data block will be preserved.
// if OEM unlock is allowed, the persistent data block will be wiped during FR
// process. If disabled, it will be wiped here, unless the device is still being
// provisioned, in which case the persistent data block will be preserved.
new AsyncTask<Void, Void, Void>() {
int mOldOrientation;
ProgressDialog mProgressDialog;
@@ -125,6 +128,7 @@ public class MasterClearConfirm extends OptionsMenuFragment {
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);
intent.putExtra(Intent.EXTRA_WIPE_ESIMS, mEraseEsims);
getActivity().sendBroadcast(intent);
// Intent handling is asynchronous -- assume it will happen soon.
}
@@ -175,6 +179,8 @@ public class MasterClearConfirm extends OptionsMenuFragment {
Bundle args = getArguments();
mEraseSdCard = args != null
&& args.getBoolean(MasterClear.ERASE_EXTERNAL_EXTRA);
mEraseEsims = args != null
&& args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);
}
@Override

View File

@@ -20,6 +20,8 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.QueuedWork;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -31,6 +33,7 @@ import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.CarrierConfigManager;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
@@ -129,6 +132,9 @@ public class RadioInfo extends Activity {
private static final int IMS_WFC_PROVISIONED_CONFIG_ID =
ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED;
private static final int EAB_PROVISIONED_CONFIG_ID =
ImsConfig.ConfigConstants.EAB_SETTING_ENABLED;
//Values in must match mCellInfoRefreshRates
private static final String[] mCellInfoRefreshRateLabels = {
"Disabled",
@@ -195,9 +201,12 @@ public class RadioInfo extends Activity {
private Button updateSmscButton;
private Button refreshSmscButton;
private Button oemInfoButton;
private Button carrierProvisioningButton;
private Button triggercarrierProvisioningButton;
private Switch imsVolteProvisionedSwitch;
private Switch imsVtProvisionedSwitch;
private Switch imsWfcProvisionedSwitch;
private Switch eabProvisionedSwitch;
private Spinner preferredNetworkType;
private Spinner cellInfoRefreshRateSpinner;
@@ -403,6 +412,7 @@ public class RadioInfo extends Activity {
imsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
imsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
eabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
radioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
@@ -414,6 +424,11 @@ public class RadioInfo extends Activity {
refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
carrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning);
carrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler);
triggercarrierProvisioningButton = (Button) findViewById(R.id.trigger_carrier_provisioning);
triggercarrierProvisioningButton.setOnClickListener(
mTriggerCarrierProvisioningButtonHandler);
oemInfoButton = (Button) findViewById(R.id.oem_info);
oemInfoButton.setOnClickListener(mOemInfoButtonHandler);
@@ -470,6 +485,7 @@ public class RadioInfo extends Activity {
imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
mTelephonyManager.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE
@@ -1162,6 +1178,11 @@ public class RadioInfo extends Activity {
setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state);
}
void setEabProvisionedState(boolean state) {
Log.d(TAG, "setEabProvisioned() state: " + ((state)? "on":"off"));
setImsConfigProvisionedState(EAB_PROVISIONED_CONFIG_ID, state);
}
void setImsConfigProvisionedState(int configItem, boolean state) {
if (phone != null && mImsManager != null) {
QueuedWork.queue(new Runnable() {
@@ -1231,6 +1252,48 @@ public class RadioInfo extends Activity {
}
};
private boolean isEabProvisioned() {
return isFeatureProvisioned(EAB_PROVISIONED_CONFIG_ID, false);
}
OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setEabProvisionedState(isChecked);
}
};
private boolean isFeatureProvisioned(int featureId, boolean defaultValue) {
boolean provisioned = defaultValue;
if (mImsManager != null) {
try {
ImsConfig imsConfig = mImsManager.getConfigInterface();
if (imsConfig != null) {
provisioned =
(imsConfig.getProvisionedValue(featureId)
== ImsConfig.FeatureValueConstants.ON);
}
} catch (ImsException ex) {
Log.e(TAG, "isFeatureProvisioned() exception:", ex);
}
}
log("isFeatureProvisioned() featureId=" + featureId + " provisioned=" + provisioned);
return provisioned;
}
private static boolean isEabEnabledByPlatform(Context context) {
if (context != null) {
CarrierConfigManager configManager = (CarrierConfigManager)
context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager != null && configManager.getConfig().getBoolean(
CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)) {
return true;
}
}
return false;
}
private void updateImsProvisionedState() {
log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
//delightful hack to prevent on-checked-changed calls from
@@ -1252,6 +1315,11 @@ public class RadioInfo extends Activity {
imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
imsWfcProvisionedSwitch.setEnabled(
mImsManager.isWfcEnabledByPlatform(phone.getContext()));
eabProvisionedSwitch.setOnCheckedChangeListener(null);
eabProvisionedSwitch.setChecked(isEabProvisioned());
eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
eabProvisionedSwitch.setEnabled(isEabEnabledByPlatform(phone.getContext()));
}
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
@@ -1295,6 +1363,26 @@ public class RadioInfo extends Activity {
}
};
OnClickListener mCarrierProvisioningButtonHandler = new OnClickListener() {
public void onClick(View v) {
final Intent intent = new Intent("com.android.settings.CARRIER_PROVISIONING");
final ComponentName serviceComponent = ComponentName.unflattenFromString(
"com.android.omadm.service/.DMIntentReceiver");
intent.setComponent(serviceComponent);
sendBroadcast(intent);
}
};
OnClickListener mTriggerCarrierProvisioningButtonHandler = new OnClickListener() {
public void onClick(View v) {
final Intent intent = new Intent("com.android.settings.TRIGGER_CARRIER_PROVISIONING");
final ComponentName serviceComponent = ComponentName.unflattenFromString(
"com.android.omadm.service/.DMIntentReceiver");
intent.setComponent(serviceComponent);
sendBroadcast(intent);
}
};
AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
new AdapterView.OnItemSelectedListener() {

View File

@@ -20,15 +20,20 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Locale;
/**
* {@link Activity} that displays regulatory information for the "Regulatory information"
* preference item, and when "*#07#" is dialed on the Phone keypad. To enable this feature,
@@ -41,7 +46,12 @@ import android.widget.TextView;
*/
public class RegulatoryInfoDisplayActivity extends Activity implements
DialogInterface.OnDismissListener {
private final String REGULATORY_INFO_RESOURCE = "regulatory_info";
private static final String DEFAULT_REGULATORY_INFO_FILEPATH =
"/data/misc/elabel/regulatory_info.png";
private static final String REGULATORY_INFO_FILEPATH_TEMPLATE =
"/data/misc/elabel/regulatory_info_%s.png";
/**
* Display the regulatory info graphic in a dialog window.
@@ -60,7 +70,18 @@ public class RegulatoryInfoDisplayActivity extends Activity implements
.setOnDismissListener(this);
boolean regulatoryInfoDrawableExists = false;
int resId = getResourceId();
final String regulatoryInfoFile = getRegulatoryInfoImageFileName();
final Bitmap regulatoryInfoBitmap = BitmapFactory.decodeFile(regulatoryInfoFile);
if (regulatoryInfoBitmap != null) {
regulatoryInfoDrawableExists = true;
}
int resId = 0;
if (!regulatoryInfoDrawableExists) {
resId = getResourceId();
}
if (resId != 0) {
try {
Drawable d = getDrawable(resId);
@@ -77,8 +98,12 @@ public class RegulatoryInfoDisplayActivity extends Activity implements
if (regulatoryInfoDrawableExists) {
View view = getLayoutInflater().inflate(R.layout.regulatory_info, null);
ImageView image = (ImageView) view.findViewById(R.id.regulatoryInfo);
image.setImageResource(resId);
ImageView image = view.findViewById(R.id.regulatoryInfo);
if (regulatoryInfoBitmap != null) {
image.setImageBitmap(regulatoryInfoBitmap);
} else {
image.setImageResource(resId);
}
builder.setView(view);
builder.show();
} else if (regulatoryText.length() > 0) {
@@ -99,7 +124,7 @@ public class RegulatoryInfoDisplayActivity extends Activity implements
REGULATORY_INFO_RESOURCE, "drawable", getPackageName());
// When hardware sku property exists, use regulatory_info_<sku> resource if valid.
String sku = SystemProperties.get("ro.boot.hardware.sku", "");
final String sku = getSku();
if (!TextUtils.isEmpty(sku)) {
String regulatory_info_res = REGULATORY_INFO_RESOURCE + "_" + sku.toLowerCase();
int id = getResources().getIdentifier(
@@ -115,4 +140,20 @@ public class RegulatoryInfoDisplayActivity extends Activity implements
public void onDismiss(DialogInterface dialog) {
finish(); // close the activity
}
@VisibleForTesting
public static String getSku() {
return SystemProperties.get("ro.boot.hardware.sku", "");
}
@VisibleForTesting
public static String getRegulatoryInfoImageFileName() {
final String sku = getSku();
if (TextUtils.isEmpty(sku)) {
return DEFAULT_REGULATORY_INFO_FILEPATH;
} else {
return String.format(Locale.US, REGULATORY_INFO_FILEPATH_TEMPLATE,
sku.toLowerCase());
}
}
}

View File

@@ -34,13 +34,14 @@ import android.widget.Spinner;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import java.util.ArrayList;
import java.util.List;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
/**
* Confirm and execute a reset of the device's network settings to a clean "just out of the box"
* state. Multiple confirmations are required: first, a general "are you sure you want to do this?"

View File

@@ -18,9 +18,11 @@ package com.android.settings;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.ContentResolver;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserHandle;
@@ -104,12 +106,27 @@ public class ResetNetworkConfirm extends OptionsMenuFragment {
}
ImsManager.factoryReset(context);
restoreDefaultApn(context);
Toast.makeText(context, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show();
}
};
/**
* Restore APN settings to default.
*/
private void restoreDefaultApn(Context context) {
Uri uri = Uri.parse(ApnSettings.RESTORE_CARRIERS_URI);
if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
uri = Uri.withAppendedPath(uri, "subId/" + String.valueOf(mSubId));
}
ContentResolver resolver = context.getContentResolver();
resolver.delete(uri, null, null);
}
/**
* Configure the UI for the final confirmation interaction
*/

View File

@@ -17,7 +17,6 @@
package com.android.settings;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -27,10 +26,10 @@ import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settingslib.RestrictedLockUtils;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -46,7 +45,10 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
* If this settings screen should be pin protected whenever
* {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
* {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
*
* @deprecated Use {@link RestrictedDashboardFragment} instead
*/
@Deprecated
public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragment {
protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";

View File

@@ -33,6 +33,7 @@ import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
@@ -73,6 +74,11 @@ public class ScreenPinningSettings extends SettingsPreferenceFragment
mSwitchBar.setChecked(isLockToAppEnabled(getActivity()));
}
@Override
protected int getHelpResource() {
return R.string.help_url_screen_pinning;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

View File

@@ -17,6 +17,7 @@
package com.android.settings;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.Activity;
@@ -65,6 +66,9 @@ import com.android.settings.fingerprint.FingerprintSettings;
import com.android.settings.location.LocationPreferenceController;
import com.android.settings.notification.LockScreenNotificationPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ManagedLockPasswordProvider;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
@@ -104,6 +108,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
static final String KEY_LOCKSCREEN_PREFERENCES = "lockscreen_preferences";
private static final String KEY_ENCRYPTION_AND_CREDENTIALS = "encryption_and_credential";
private static final String KEY_LOCATION_SCANNING = "location_scanning";
private static final String KEY_LOCATION = "location";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
@@ -177,6 +182,12 @@ public class SecuritySettings extends SettingsPreferenceFragment
return MetricsEvent.SECURITY;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mLocationcontroller = new LocationPreferenceController(context, getLifecycle());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -207,7 +218,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
}
mLocationcontroller = new LocationPreferenceController(activity);
mManageDeviceAdminPreferenceController
= new ManageDeviceAdminPreferenceController(activity);
mEnterprisePrivacyPreferenceController
@@ -632,7 +642,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
return false;
}
}
startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
startFragment(this, ChooseLockGenericFragment.class.getName(),
R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
} else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) {
if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm,
@@ -641,7 +651,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
}
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
startFragment(this, ChooseLockGenericFragment.class.getName(),
R.string.lock_settings_picker_title_profile,
SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
} else if (KEY_TRUST_AGENT.equals(key)) {
@@ -741,7 +751,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private void unifyUncompliantLocks() {
mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false,
mCurrentProfilePassword);
startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
startFragment(this, ChooseLockGenericFragment.class.getName(),
R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
}
@@ -749,7 +759,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
startFragment(this,
"com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
ChooseLockGenericFragment.class.getName(),
R.string.lock_settings_picker_title_profile,
SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
}
@@ -957,7 +967,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
// Duplicate in special app access
keys.add(KEY_MANAGE_DEVICE_ADMIN);
// Duplicates between parent-child
keys.add((new LocationPreferenceController(context)).getPreferenceKey());
keys.add(KEY_LOCATION);
keys.add(KEY_ENCRYPTION_AND_CREDENTIALS);
keys.add(KEY_SCREEN_PINNING);
keys.add(KEY_LOCATION_SCANNING);

View File

@@ -23,6 +23,8 @@ import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import com.android.settingslib.CustomDialogPreference;
/**
* Based on frameworks/base/core/java/android/preference/SeekBarDialogPreference.java
* except uses support lib preferences.

View File

@@ -22,6 +22,8 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import com.android.settingslib.CustomEditTextPreference;
public class SelectableEditTextPreference extends CustomEditTextPreference {
private int mSelectionMode;

View File

@@ -22,6 +22,7 @@ import com.android.settings.applications.AppOpsSummary;
import com.android.settings.enterprise.EnterprisePrivacySettings;
import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.fingerprint.FingerprintSettings;
import com.android.settings.password.ChooseLockGeneric;
/**
* Top-level Settings activity
@@ -31,6 +32,7 @@ public class Settings extends SettingsActivity {
/*
* Settings subclasses for launching independently.
*/
public static class AssistGestureSettingsActivity extends SettingsActivity { /* empty */}
public static class BluetoothSettingsActivity extends SettingsActivity { /* empty */ }
public static class SimSettingsActivity extends SettingsActivity { /* empty */ }
public static class TetherSettingsActivity extends SettingsActivity { /* empty */ }
@@ -139,12 +141,17 @@ public class Settings extends SettingsActivity {
public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ }
public static class FingerprintSuggestionActivity extends FingerprintSettings { /* empty */ }
public static class FingerprintEnrollSuggestionActivity extends FingerprintEnrollIntroduction {
/* empty */
}
public static class ScreenLockSuggestionActivity extends ChooseLockGeneric { /* empty */ }
public static class DoubleTapPowerSuggestionActivity extends SettingsActivity { /* empty */ }
public static class DoubleTwistSuggestionActivity extends SettingsActivity { /* empty */ }
public static class AmbientDisplaySuggestionActivity extends SettingsActivity { /* empty */ }
public static class AmbientDisplayPickupSuggestionActivity extends SettingsActivity {
/* empty */ }
public static class SwipeToNotificationSuggestionActivity extends SettingsActivity {
/* empty */ }
public static class WallpaperSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManagedProfileSettingsActivity extends SettingsActivity { /* empty */ }
public static class DeletionHelperActivity extends SettingsActivity { /* empty */ }
@@ -168,6 +175,7 @@ public class Settings extends SettingsActivity {
}
}
public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
public static class LegacySupportActivity extends SettingsActivity{ /* empty */ }
// Top level categories for new IA
public static class NetworkDashboardActivity extends SettingsActivity {}
@@ -176,6 +184,5 @@ public class Settings extends SettingsActivity {
public static class StorageDashboardActivity extends SettingsActivity {}
public static class UserAndAccountDashboardActivity extends SettingsActivity {}
public static class SystemDashboardActivity extends SettingsActivity {}
public static class SupportDashboardActivity extends SettingsActivity {}
}

View File

@@ -50,6 +50,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toolbar;
import com.android.internal.util.ArrayUtils;
import com.android.settings.Settings.WifiSettingsActivity;
@@ -62,7 +63,8 @@ import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.development.DevelopmentSettings;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DynamicIndexableContentMonitor;
import com.android.settings.search2.SearchFeatureProvider;
import com.android.settings.search.SearchActivity;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.drawer.DashboardCategory;
@@ -75,7 +77,7 @@ import java.util.Set;
public class SettingsActivity extends SettingsDrawerActivity
implements PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback,
ButtonBarHandler, FragmentManager.OnBackStackChangedListener {
ButtonBarHandler, FragmentManager.OnBackStackChangedListener, OnClickListener {
private static final String LOG_TAG = "Settings";
@@ -85,8 +87,6 @@ public class SettingsActivity extends SettingsDrawerActivity
private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
@VisibleForTesting
static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
@VisibleForTesting
static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
/**
* When starting this activity, the invoking Intent can contain this extra
@@ -190,22 +190,18 @@ public class SettingsActivity extends SettingsDrawerActivity
private DynamicIndexableContentMonitor mDynamicIndexableContentMonitor;
private ActionBar mActionBar;
private SwitchBar mSwitchBar;
private Button mNextButton;
@VisibleForTesting
boolean mDisplayHomeAsUpEnabled;
@VisibleForTesting
boolean mDisplaySearch;
private boolean mIsShowingDashboard;
private boolean mIsShortcut;
private ViewGroup mContent;
private SearchFeatureProvider mSearchFeatureProvider;
private MetricsFeatureProvider mMetricsFeatureProvider;
// Categories
@@ -230,15 +226,6 @@ public class SettingsActivity extends SettingsDrawerActivity
return false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mDisplaySearch) {
return false;
}
mSearchFeatureProvider.setUpSearchMenu(menu, this);
return true;
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
if (name.equals(getPackageName() + "_preferences")) {
@@ -282,7 +269,6 @@ public class SettingsActivity extends SettingsDrawerActivity
final FeatureFactory factory = FeatureFactory.getFactory(this);
mDashboardFeatureProvider = factory.getDashboardFeatureProvider(this);
mSearchFeatureProvider = factory.getSearchFeatureProvider();
mMetricsFeatureProvider = factory.getMetricsFeatureProvider();
// Should happen before any call to getIntent()
@@ -322,7 +308,7 @@ public class SettingsActivity extends SettingsDrawerActivity
setContentView(mIsShowingDashboard ?
R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
mContent = (ViewGroup) findViewById(R.id.main_content);
mContent = findViewById(R.id.main_content);
getFragmentManager().addOnBackStackChangedListener(this);
@@ -345,12 +331,28 @@ public class SettingsActivity extends SettingsDrawerActivity
launchSettingFragment(initialFragmentName, isSubSettings, intent);
}
mActionBar = getActionBar();
if (mActionBar != null) {
mActionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
mActionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
if (mIsShowingDashboard) {
findViewById(R.id.search_bar).setVisibility(View.VISIBLE);
findViewById(R.id.action_bar).setVisibility(View.GONE);
Toolbar toolbar = findViewById(R.id.search_action_bar);
toolbar.setOnClickListener(this);
setActionBar(toolbar);
// Please forgive me for what I am about to do.
//
// Need to make the navigation icon non-clickable so that the entire card is clickable
// and goes to the search UI. Also set the background to null so there's no ripple.
View navView = toolbar.getNavigationView();
navView.setClickable(false);
navView.setBackground(null);
}
mSwitchBar = (SwitchBar) findViewById(R.id.switch_bar);
ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
actionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
}
mSwitchBar = findViewById(R.id.switch_bar);
if (mSwitchBar != null) {
mSwitchBar.setMetricsTag(getMetricsTag());
}
@@ -417,7 +419,6 @@ public class SettingsActivity extends SettingsDrawerActivity
@VisibleForTesting
void launchSettingFragment(String initialFragmentName, boolean isSubSettings, Intent intent) {
if (!mIsShowingDashboard && initialFragmentName != null) {
mDisplaySearch = false;
// UP will be shown only if it is a sub settings
if (mIsShortcut) {
mDisplayHomeAsUpEnabled = isSubSettings;
@@ -432,10 +433,8 @@ public class SettingsActivity extends SettingsDrawerActivity
switchToFragment(initialFragmentName, initialArguments, true, false,
mInitialTitleResId, mInitialTitle, false);
} else {
// No UP affordance if we are displaying the main Dashboard
mDisplayHomeAsUpEnabled = false;
// Show Search affordance
mDisplaySearch = true;
// Show search icon as up affordance if we are displaying the main Dashboard
mDisplayHomeAsUpEnabled = true;
mInitialTitleResId = R.string.dashboard_title;
switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false,
@@ -443,13 +442,6 @@ public class SettingsActivity extends SettingsDrawerActivity
}
}
public void setDisplaySearchMenu(boolean displaySearch) {
if (displaySearch != mDisplaySearch) {
mDisplaySearch = displaySearch;
invalidateOptionsMenu();
}
}
private void setTitleFromIntent(Intent intent) {
final int initialTitleResId = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
if (initialTitleResId > 0) {
@@ -530,7 +522,6 @@ public class SettingsActivity extends SettingsDrawerActivity
}
outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
}
@Override
@@ -538,19 +529,13 @@ public class SettingsActivity extends SettingsDrawerActivity
super.onRestoreInstanceState(savedInstanceState);
mDisplayHomeAsUpEnabled = savedInstanceState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
mDisplaySearch = savedInstanceState.getBoolean(SAVE_KEY_SHOW_SEARCH);
}
@Override
protected void onResume() {
super.onResume();
mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updateTilesList();
}
};
mDevelopmentPreferencesListener = (sharedPreferences, key) -> updateTilesList();
mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
mDevelopmentPreferencesListener);
@@ -939,4 +924,10 @@ public class SettingsActivity extends SettingsDrawerActivity
return bitmap;
}
}
@Override
public void onClick(View v) {
Intent intent = new Intent(this, SearchActivity.class);
startActivity(intent);
}
}

View File

@@ -49,8 +49,10 @@ import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.CustomDialogPreference;
import com.android.settingslib.CustomEditTextPreference;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.widget.FooterPreferenceMixin;
import java.util.UUID;
@@ -321,12 +323,15 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
}
}
private void updateEmptyView() {
@VisibleForTesting
void updateEmptyView() {
if (mEmptyView == null) return;
if (getPreferenceScreen() != null) {
final View listContainer = getActivity().findViewById(android.R.id.list_container);
boolean show = (getPreferenceScreen().getPreferenceCount()
- (mHeader != null ? 1 : 0)
- (mFooterPreferenceMixin.hasFooter() ? 1 : 0)) <= 0;
- (mFooterPreferenceMixin.hasFooter() ? 1 : 0)) <= 0
|| (listContainer != null && listContainer.getVisibility() != View.VISIBLE);
mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE);
} else {
mEmptyView.setVisibility(View.VISIBLE);

View File

@@ -1,96 +0,0 @@
/*
* 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.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.LinearLayout;
/**
* Setup Wizard's version of ChooseLockPassword screen. It inherits the logic and basic structure
* from ChooseLockPassword class, and should remain similar to that behaviorally. This class should
* only overload base methods for minor theme and behavior differences specific to Setup Wizard.
* Other changes should be done to ChooseLockPassword class instead and let this class inherit
* those changes.
*/
public class SetupChooseLockPassword extends ChooseLockPassword {
public static Intent createIntent(Context context, int quality,
int minLength, final int maxLength, boolean requirePasswordToDecrypt,
boolean confirmCredentials) {
Intent intent = ChooseLockPassword.createIntent(context, quality, minLength,
maxLength, requirePasswordToDecrypt, confirmCredentials);
intent.setClass(context, SetupChooseLockPassword.class);
intent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false);
return intent;
}
public static Intent createIntent(Context context, int quality,
int minLength, final int maxLength, boolean requirePasswordToDecrypt, String password) {
Intent intent = ChooseLockPassword.createIntent(context, quality, minLength, maxLength,
requirePasswordToDecrypt, password);
intent.setClass(context, SetupChooseLockPassword.class);
intent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false);
return intent;
}
public static Intent createIntent(Context context, int quality,
int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge) {
Intent intent = ChooseLockPassword.createIntent(context, quality, minLength, maxLength,
requirePasswordToDecrypt, challenge);
intent.setClass(context, SetupChooseLockPassword.class);
intent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false);
return intent;
}
@Override
protected boolean isValidFragment(String fragmentName) {
return SetupChooseLockPasswordFragment.class.getName().equals(fragmentName);
}
@Override
/* package */ Class<? extends Fragment> getFragmentClass() {
return SetupChooseLockPasswordFragment.class;
}
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
layout.setFitsSystemWindows(false);
}
@Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
resid = SetupWizardUtils.getTheme(getIntent());
super.onApplyThemeResource(theme, resid, first);
}
public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment {
@Override
protected Intent getRedactionInterstitialIntent(Context context) {
// Setup wizard's redaction interstitial is deferred to optional step. Enable that
// optional step if the lock screen was set up.
SetupRedactionInterstitial.setEnabled(context, true);
return null;
}
}
}

View File

@@ -18,7 +18,6 @@ package com.android.settings;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.LinearLayout;
@@ -54,12 +53,6 @@ public class SetupEncryptionInterstitial extends EncryptionInterstitial {
return SetupEncryptionInterstitialFragment.class.getName().equals(fragmentName);
}
@Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
resid = SetupWizardUtils.getTheme(getIntent());
super.onApplyThemeResource(theme, resid, first);
}
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);

View File

@@ -60,12 +60,6 @@ public class SetupRedactionInterstitial extends RedactionInterstitial {
return SetupRedactionInterstitialFragment.class.getName().equals(fragmentName);
}
@Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
resid = SetupWizardUtils.getTheme(getIntent());
super.onApplyThemeResource(theme, resid, first);
}
public static class SetupRedactionInterstitialFragment extends RedactionInterstitialFragment {
// Setup wizard specific UI customizations can be done here

View File

@@ -17,17 +17,34 @@
package com.android.settings;
import android.content.Intent;
import android.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import com.android.setupwizardlib.util.WizardManagerHelper;
public class SetupWizardUtils {
@VisibleForTesting
static final String SYSTEM_PROP_SETUPWIZARD_THEME = "setupwizard.theme";
public static int getTheme(Intent intent) {
if (WizardManagerHelper.isLightTheme(intent, true)) {
return R.style.SetupWizardTheme_Light;
} else {
return R.style.SetupWizardTheme;
String theme = intent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
if (theme == null) {
theme = SystemProperties.get(SYSTEM_PROP_SETUPWIZARD_THEME);
}
if (theme != null) {
switch (theme) {
case WizardManagerHelper.THEME_GLIF_V2_LIGHT:
return R.style.GlifV2Theme_Light;
case WizardManagerHelper.THEME_GLIF_V2:
return R.style.GlifV2Theme;
case WizardManagerHelper.THEME_GLIF_LIGHT:
return R.style.GlifTheme_Light;
case WizardManagerHelper.THEME_GLIF:
return R.style.GlifTheme;
}
}
return R.style.GlifTheme_Light;
}
public static int getTransparentTheme(Intent intent) {

View File

@@ -400,7 +400,7 @@ public class TetherSettings extends RestrictedSettingsFragment
private void updateState(String[] available, String[] tethered,
String[] errored) {
updateUsbState(available, tethered, errored);
updateBluetoothState(available, tethered, errored);
updateBluetoothState();
}
@@ -431,41 +431,18 @@ public class TetherSettings extends RestrictedSettingsFragment
}
if (usbTethered) {
mUsbTether.setSummary(R.string.usb_tethering_active_subtext);
mUsbTether.setEnabled(!mDataSaverEnabled);
mUsbTether.setChecked(true);
} else if (usbAvailable) {
if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
mUsbTether.setSummary(R.string.usb_tethering_available_subtext);
} else {
mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
}
mUsbTether.setEnabled(!mDataSaverEnabled);
mUsbTether.setChecked(false);
} else if (usbErrored) {
mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
mUsbTether.setEnabled(false);
mUsbTether.setChecked(false);
} else if (mMassStorageActive) {
mUsbTether.setSummary(R.string.usb_tethering_storage_active_subtext);
mUsbTether.setEnabled(false);
mUsbTether.setChecked(false);
} else {
mUsbTether.setSummary(R.string.usb_tethering_unavailable_subtext);
mUsbTether.setEnabled(false);
mUsbTether.setChecked(false);
}
}
private void updateBluetoothState(String[] available, String[] tethered,
String[] errored) {
boolean bluetoothErrored = false;
for (String s: errored) {
for (String regex : mBluetoothRegexs) {
if (s.matches(regex)) bluetoothErrored = true;
}
}
private void updateBluetoothState() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
return;
@@ -473,34 +450,17 @@ public class TetherSettings extends RestrictedSettingsFragment
int btState = adapter.getState();
if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
mBluetoothTether.setEnabled(false);
mBluetoothTether.setSummary(R.string.bluetooth_turning_off);
} else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
mBluetoothTether.setEnabled(false);
mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
} else {
BluetoothPan bluetoothPan = mBluetoothPan.get();
if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null
&& bluetoothPan.isTetheringOn()) {
mBluetoothTether.setChecked(true);
mBluetoothTether.setEnabled(!mDataSaverEnabled);
int bluetoothTethered = bluetoothPan.getConnectedDevices().size();
if (bluetoothTethered > 1) {
String summary = getString(
R.string.bluetooth_tethering_devices_connected_subtext,
bluetoothTethered);
mBluetoothTether.setSummary(summary);
} else if (bluetoothTethered == 1) {
mBluetoothTether.setSummary(
R.string.bluetooth_tethering_device_connected_subtext);
} else if (bluetoothErrored) {
mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
} else {
mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
}
} else {
mBluetoothTether.setEnabled(!mDataSaverEnabled);
mBluetoothTether.setChecked(false);
mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
}
}
}

View File

@@ -35,7 +35,6 @@ import android.util.ArraySet;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.security.SecurityFeatureProvider;
import com.android.settings.trustagent.TrustAgentManager;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -78,6 +77,11 @@ public class TrustAgentSettings extends SettingsPreferenceFragment implements
return MetricsEvent.TRUST_AGENT;
}
@Override
protected int getHelpResource() {
return R.string.help_url_trust_agent;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

View File

@@ -943,6 +943,8 @@ public final class Utils extends com.android.settingslib.Utils {
return result;
}
// TODO: move this out of Utils to a mixin or a controller or a helper class.
@Deprecated
public static void handleLoadingContainer(View loading, View doneLoading, boolean done,
boolean animate) {
setViewShown(loading, !done, animate);
@@ -1036,7 +1038,24 @@ public final class Utils extends com.android.settingslib.Utils {
return getCredentialOwnerUserId(context);
}
int userId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
return enforceSameOwner(context, userId);
if (userId == LockPatternUtils.USER_FRP) {
return enforceSystemUser(context, userId);
} else {
return enforceSameOwner(context, userId);
}
}
/**
* Returns the given user id if the current user is the system user.
*
* @throws SecurityException if the current user is not the system user.
*/
public static int enforceSystemUser(Context context, int userId) {
if (UserHandle.myUserId() == UserHandle.USER_SYSTEM) {
return userId;
}
throw new SecurityException("Given user id " + userId + " must only be used from "
+ "USER_SYSTEM, but current user is " + UserHandle.myUserId());
}
/**
@@ -1233,6 +1252,11 @@ public final class Utils extends com.android.settingslib.Utils {
}
}
public static boolean hasFingerprintHardware(Context context) {
FingerprintManager fingerprintManager = getFingerprintManagerOrNull(context);
return fingerprintManager != null && fingerprintManager.isHardwareDetected();
}
/**
* Launches an intent which may optionally have a user id defined.
* @param fragment Fragment to use to launch the activity.
@@ -1252,19 +1276,19 @@ public final class Utils extends com.android.settingslib.Utils {
}
}
public static boolean isCarrierDemoUser(Context context) {
final String carrierDemoModeSetting =
context.getString(com.android.internal.R.string.config_carrierDemoModeSetting);
return UserManager.isDeviceInDemoMode(context)
&& getUserManager(context).isDemoUser()
&& !TextUtils.isEmpty(carrierDemoModeSetting)
&& (Settings.Secure.getInt(context.getContentResolver(),
carrierDemoModeSetting, 0) == 1);
public static boolean isDemoUser(Context context) {
return UserManager.isDeviceInDemoMode(context) && getUserManager(context).isDemoUser();
}
public static ComponentName getDeviceOwnerComponent(Context context) {
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
return dpm.getDeviceOwnerComponentOnAnyUser();
}
/**
* Returns if a given user is a profile of another user.
* @param user The user whose profiles will be checked.
* @param user The user whose profiles wibe checked.
* @param profile The (potential) profile.
* @return if the profile is actually a profile
*/
@@ -1311,8 +1335,6 @@ public final class Utils extends com.android.settingslib.Utils {
}
}
private static boolean isVolumeValid(VolumeInfo volume) {
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
&& volume.isMountedReadable();

View File

@@ -152,7 +152,9 @@ public class WifiCallingSettings extends SettingsPreferenceFragment
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
setEmptyView(mEmptyView);
mEmptyView.setText(R.string.wifi_calling_off_explanation);
String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
+ activity.getString(R.string.wifi_calling_off_explanation_2);
mEmptyView.setText(emptyViewText);
}
@Override

View File

@@ -55,7 +55,7 @@ public class AccessibilityServiceWarning {
final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
// Filter obscured touches by consuming them.
if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
|| ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
|| ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Toast.makeText(v.getContext(), R.string.touch_filtered_warning,
Toast.LENGTH_SHORT).show();

View File

@@ -211,6 +211,18 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
private DevicePolicyManager mDpm;
/**
* Check if the color transforms are color accelerated. Some transforms are experimental only
* on non-accelerated platforms due to the performance implications.
*
* @param context The current context
* @return
*/
public static boolean isColorTransformAccelerated(Context context) {
return context.getResources()
.getBoolean(com.android.internal.R.bool.config_setColorTransformAccelerated);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.ACCESSIBILITY;
@@ -618,11 +630,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
updateAccessibilityShortcut(mAccessibilityShortcutPreferenceScreen);
}
private boolean isColorTransformAccelerated(Context context) {
return context.getResources()
.getBoolean(com.android.internal.R.bool.config_setColorTransformAccelerated);
}
private void updateMagnificationSummary(Preference pref) {
final boolean tripleTapEnabled = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0) == 1;
@@ -767,10 +774,9 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = new ArrayList<>();
List<String> keys = super.getNonIndexableKeys(context);
// Duplicates in Display
keys.add(FONT_SIZE_PREFERENCE_SCREEN);
// TODO (b/37741509) Remove this non-indexble key when bug is resolved.
keys.add(DisplaySettings.KEY_DISPLAY_SIZE);
return keys;

View File

@@ -51,6 +51,11 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
}
@Override
protected int getHelpResource() {
return R.string.help_url_accessibility_shortcut;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View File

@@ -31,7 +31,7 @@ import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import com.android.settings.CustomDialogPreference;
import com.android.settingslib.CustomDialogPreference;
/**
* Abstract dialog preference that displays a set of values and optional titles.

View File

@@ -31,11 +31,9 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.PreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -67,6 +65,11 @@ public final class MagnificationPreferenceFragment extends SettingsPreferenceFra
mMagnificationNavbarPreference = findPreference(MAGNIFICATION_NAVBAR_PREFERENCE_SCREEN_KEY);
}
@Override
protected int getHelpResource() {
return R.string.help_url_magnification;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

View File

@@ -16,7 +16,6 @@
package com.android.settings.accessibility;
import static android.content.DialogInterface.BUTTON_POSITIVE;
import static com.android.settings.Utils.setOverlayAllowed;
import android.accessibilityservice.AccessibilityServiceInfo;

View File

@@ -16,8 +16,6 @@
package com.android.settings.accessibility;
import static com.android.settings.Utils.setOverlayAllowed;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.AlertDialog;
@@ -38,19 +36,20 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.ConfirmDeviceCredentialActivity;
import com.android.settings.R;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.widget.ToggleSwitch;
import com.android.settings.widget.ToggleSwitch.OnBeforeCheckedChangeListener;
import com.android.settingslib.accessibility.AccessibilityUtils;
import java.util.List;
import static com.android.settings.Utils.setOverlayAllowed;
public class ToggleAccessibilityServicePreferenceFragment
extends ToggleFeaturePreferenceFragment implements DialogInterface.OnClickListener {
@@ -85,14 +84,6 @@ public class ToggleAccessibilityServicePreferenceFragment
// Do not call super. We don't want to see the "Help & feedback" option on this page so as
// not to confuse users who think they might be able to send feedback about a specific
// accessibility service from this page.
// We still want to show the "Settings" menu.
if (mSettingsTitle != null && mSettingsIntent != null) {
MenuItem menuItem = menu.add(mSettingsTitle);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menuItem.setIntent(mSettingsIntent);
}
}
@Override

View File

@@ -26,7 +26,7 @@ import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SeekBarPreference;
import com.android.settings.widget.SeekBarPreference;
import com.android.settings.widget.SwitchBar;
@@ -104,6 +104,11 @@ public class ToggleAutoclickPreferenceFragment extends ToggleFeaturePreferenceFr
return MetricsEvent.ACCESSIBILITY_TOGGLE_AUTOCLICK;
}
@Override
protected int getHelpResource() {
return R.string.help_url_autoclick;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

View File

@@ -41,6 +41,11 @@ public class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePreferenceF
return MetricsEvent.ACCESSIBILITY_TOGGLE_DALTONIZER;
}
@Override
protected int getHelpResource() {
return R.string.help_url_color_correction;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -49,6 +54,10 @@ public class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePreferenceF
mType = (ListPreference) findPreference("type");
if (!AccessibilitySettings.isColorTransformAccelerated(getActivity())) {
mFooterPreferenceMixin.createFooterPreference().setTitle(
R.string.accessibility_display_daltonizer_preference_subtitle);
}
initPreferences();
}

View File

@@ -42,7 +42,6 @@ public abstract class ToggleFeaturePreferenceFragment
protected ToggleSwitch mToggleSwitch;
protected String mPreferenceKey;
protected Preference mSummaryPreference;
protected CharSequence mSettingsTitle;
protected Intent mSettingsIntent;
@@ -53,36 +52,6 @@ public abstract class ToggleFeaturePreferenceFragment
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
getActivity());
setPreferenceScreen(preferenceScreen);
mSummaryPreference = new Preference(getPrefContext()) {
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
view.setDividerAllowedAbove(false);
view.setDividerAllowedBelow(false);
final TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
summaryView.setText(getSummary());
sendAccessibilityEvent(summaryView);
}
private void sendAccessibilityEvent(View view) {
// Since the view is still not attached we create, populate,
// and send the event directly since we do not know when it
// will be attached and posting commands is not as clean.
AccessibilityManager accessibilityManager =
AccessibilityManager.getInstance(getActivity());
if (accessibilityManager.isEnabled()) {
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
view.onInitializeAccessibilityEvent(event);
view.dispatchPopulateAccessibilityEvent(event);
accessibilityManager.sendAccessibilityEvent(event);
}
}
};
mSummaryPreference.setSelectable(false);
mSummaryPreference.setPersistent(false);
mSummaryPreference.setLayoutResource(R.layout.text_description_preference);
preferenceScreen.addPreference(mSummaryPreference);
}
@Override
@@ -94,6 +63,16 @@ public abstract class ToggleFeaturePreferenceFragment
mToggleSwitch = mSwitchBar.getSwitch();
onProcessArguments(getArguments());
// Show the "Settings" menu as if it were a preference screen
if (mSettingsTitle != null && mSettingsIntent != null) {
PreferenceScreen preferenceScreen = getPreferenceScreen();
Preference settingsPref = new Preference(preferenceScreen.getContext());
settingsPref.setTitle(mSettingsTitle);
settingsPref.setIconSpaceReserved(true);
settingsPref.setIntent(mSettingsIntent);
preferenceScreen.addPreference(settingsPref);
}
}
@Override
@@ -111,16 +90,6 @@ public abstract class ToggleFeaturePreferenceFragment
protected abstract void onPreferenceToggled(String preferenceKey, boolean enabled);
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
if (mSettingsTitle != null && mSettingsIntent != null) {
MenuItem menuItem = menu.add(mSettingsTitle);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menuItem.setIntent(mSettingsIntent);
}
}
protected void onInstallSwitchBarToggleSwitch() {
// Implement this to set a checked listener.
}
@@ -145,11 +114,6 @@ public abstract class ToggleFeaturePreferenceFragment
}
protected void onProcessArguments(Bundle arguments) {
if (arguments == null) {
getPreferenceScreen().removePreference(mSummaryPreference);
return;
}
// Key.
mPreferenceKey = arguments.getString(AccessibilitySettings.EXTRA_PREFERENCE_KEY);
@@ -168,9 +132,7 @@ public abstract class ToggleFeaturePreferenceFragment
if (arguments.containsKey(AccessibilitySettings.EXTRA_SUMMARY)) {
final CharSequence summary = arguments.getCharSequence(
AccessibilitySettings.EXTRA_SUMMARY);
mSummaryPreference.setSummary(summary);
} else {
getPreferenceScreen().removePreference(mSummaryPreference);
mFooterPreferenceMixin.createFooterPreference().setTitle(summary);
}
}
}

View File

@@ -72,6 +72,11 @@ public class ToggleFontSizePreferenceFragment extends PreviewSeekBarPreferenceFr
Settings.System.putFloat(resolver, Settings.System.FONT_SCALE, mValues[mCurrentIndex]);
}
@Override
public int getHelpResource() {
return R.string.help_url_font_size;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.ACCESSIBILITY_FONT_SIZE;

View File

@@ -146,7 +146,6 @@ public class ToggleScreenMagnificationPreferenceFragment extends
final PreferenceScreen preferenceScreen = getPreferenceManager().getPreferenceScreen();
preferenceScreen.setOrderingAsAdded(false);
mVideoPreference.setOrder(0);
mSummaryPreference.setOrder(1);
mConfigWarningPreference.setOrder(2);
preferenceScreen.addPreference(mVideoPreference);
preferenceScreen.addPreference(mConfigWarningPreference);

View File

@@ -22,9 +22,8 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -45,13 +44,12 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
public static final String KEY_ACCOUNT_TYPE = "account_type";
public static final String KEY_ACCOUNT_LABEL = "account_label";
public static final String KEY_ACCOUNT_TITLE_RES = "account_title_res";
public static final String KEY_ACCOUNT_HEADER = "account_header";
public static final String KEY_USER_HANDLE = "user_handle";
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@VisibleForTesting
Account mAccount;
private String mAccountLabel;
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@VisibleForTesting
String mAccountType;
private AccountSyncPreferenceController mAccountSynController;
private RemoveAccountPreferenceController mRemoveAccountController;
@@ -98,6 +96,11 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
return TAG;
}
@Override
protected int getHelpResource() {
return R.string.help_url_account_detail;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.account_type_settings;
@@ -110,6 +113,8 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
controllers.add(mAccountSynController);
mRemoveAccountController = new RemoveAccountPreferenceController(context, this);
controllers.add(mRemoveAccountController);
controllers.add(new AccountHeaderPreferenceController(
context, getLifecycle(), getActivity(), this /* host */, getArguments()));
return controllers;
}
@@ -127,8 +132,6 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
@VisibleForTesting
void updateUi() {
final Preference headerPreference = findPreference(KEY_ACCOUNT_HEADER);
headerPreference.setTitle(mAccount.name);
final Context context = getContext();
UserHandle userHandle = null;
Bundle args = getArguments();
@@ -136,14 +139,12 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
userHandle = args.getParcelable(KEY_USER_HANDLE);
}
final AuthenticatorHelper helper = new AuthenticatorHelper(context, userHandle, null);
headerPreference.setIcon(helper.getDrawableForType(context, mAccountType));
final AccountTypePreferenceLoader accountTypePreferenceLoader =
new AccountTypePreferenceLoader(this, helper, userHandle);
PreferenceScreen prefs =
accountTypePreferenceLoader.addPreferencesForType(mAccountType, getPreferenceScreen());
new AccountTypePreferenceLoader(this, helper, userHandle);
PreferenceScreen prefs = accountTypePreferenceLoader.addPreferencesForType(
mAccountType, getPreferenceScreen());
if (prefs != null) {
accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
}
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2017 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.accounts;
import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_ACCOUNT;
import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_USER_HANDLE;
import android.accounts.Account;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.accounts.AuthenticatorHelper;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnResume;
public class AccountHeaderPreferenceController extends PreferenceController
implements LifecycleObserver, OnResume {
private static final String KEY_ACCOUNT_HEADER = "account_header";
private final Activity mActivity;
private final PreferenceFragment mHost;
private final Account mAccount;
private final UserHandle mUserHandle;
private LayoutPreference mHeaderPreference;
public AccountHeaderPreferenceController(Context context, Lifecycle lifecycle,
Activity activity, PreferenceFragment host, Bundle args) {
super(context);
mActivity = activity;
mHost = host;
if (args != null && args.containsKey(KEY_ACCOUNT)) {
mAccount = args.getParcelable(KEY_ACCOUNT);
} else {
mAccount = null;
}
if (args != null && args.containsKey(KEY_USER_HANDLE)) {
mUserHandle = args.getParcelable(KEY_USER_HANDLE);
} else {
mUserHandle = null;
}
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public boolean isAvailable() {
return mAccount != null && mUserHandle != null;
}
@Override
public String getPreferenceKey() {
return KEY_ACCOUNT_HEADER;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mHeaderPreference = (LayoutPreference) screen.findPreference(KEY_ACCOUNT_HEADER);
}
@Override
public void onResume() {
final AuthenticatorHelper helper = new AuthenticatorHelper(mContext, mUserHandle, null);
EntityHeaderController
.newInstance(mActivity, mHost, mHeaderPreference.findViewById(R.id.entity_header))
.setLabel(mAccount.name)
.setIcon(helper.getDrawableForType(mContext, mAccount.type))
.done(mActivity, true /* rebindButtons */);
}
}

View File

@@ -47,14 +47,14 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.search2.SearchFeatureProviderImpl;
import com.android.settings.search.SearchFeatureProviderImpl;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.accounts.AuthenticatorHelper;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.ArrayList;
import java.util.Collections;

View File

@@ -19,23 +19,31 @@ package com.android.settings.accounts;
import static android.content.Intent.EXTRA_USER;
import android.accounts.Account;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncAdapterType;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.accounts.AuthenticatorHelper;
public class AccountSyncPreferenceController extends PreferenceController {
public class AccountSyncPreferenceController extends PreferenceController
implements AuthenticatorHelper.OnAccountsUpdateListener {
private static final String TAG = "AccountSyncController";
private static final String KEY_ACCOUNT_SYNC = "account_sync";
private Account mAccount;
private UserHandle mUserHandle;
private AuthenticatorHelper mAuthenticatorHelper;
private Preference mPreference;
public AccountSyncPreferenceController(Context context) {
super(context);
@@ -65,8 +73,61 @@ public class AccountSyncPreferenceController extends PreferenceController {
return KEY_ACCOUNT_SYNC;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void updateState(Preference preference) {
updateSummary(preference);
}
@Override
public void onAccountsUpdate(UserHandle userHandle) {
updateSummary(mPreference);
}
public void init(Account account, UserHandle userHandle) {
mAccount = account;
mUserHandle = userHandle;
mAuthenticatorHelper = new AuthenticatorHelper(mContext, mUserHandle, this);
}
@VisibleForTesting
void updateSummary(Preference preference) {
final int userId = mUserHandle.getIdentifier();
final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
int total = 0;
int enabled = 0;
if (syncAdapters != null) {
for (int i = 0, n = syncAdapters.length; i < n; i++) {
final SyncAdapterType sa = syncAdapters[i];
if (!sa.accountType.equals(mAccount.type) || !sa.isUserVisible()) {
continue;
}
final int syncState =
ContentResolver.getIsSyncableAsUser(mAccount, sa.authority, userId);
if (syncState > 0) {
total++;
final boolean syncEnabled = ContentResolver.getSyncAutomaticallyAsUser(
mAccount, sa.authority, userId);
final boolean oneTimeSyncMode =
!ContentResolver.getMasterSyncAutomaticallyAsUser(userId);
if (oneTimeSyncMode || syncEnabled) {
enabled++;
}
}
}
}
if (enabled == 0) {
preference.setSummary(R.string.account_sync_summary_all_off);
} else if (enabled == total) {
preference.setSummary(R.string.account_sync_summary_all_on);
} else {
preference.setSummary(
mContext.getString(R.string.account_sync_summary_some_on, enabled, total));
}
}
}

View File

@@ -79,7 +79,6 @@ public class AccountTypePreference extends Preference implements OnPreferenceCli
mFragment = fragment;
mFragmentArguments = fragmentArguments;
mMetricsCategory = metricsCategory;
setWidgetLayoutResource(R.layout.account_type_preference);
setKey(buildKey(account));
setTitle(mTitle);

View File

@@ -16,6 +16,8 @@
package com.android.settings.accounts;
import static android.content.Intent.EXTRA_USER;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
@@ -32,14 +34,12 @@ import android.os.UserManager;
import android.util.Log;
import android.widget.Toast;
import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.password.ChooseLockSettingsHelper;
import java.io.IOException;
import static android.content.Intent.EXTRA_USER;
/**
* Entry point Activity for account setup. Works as follows
*

View File

@@ -20,11 +20,11 @@ import android.provider.Settings.Global;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settings.users.UserCapabilities;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
public class AddUserWhenLockedPreferenceController extends PreferenceController
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnPause, OnResume {

View File

@@ -44,10 +44,10 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.FooterPreference;
import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.FooterPreferenceMixin;
import com.google.android.collect.Maps;

View File

@@ -34,7 +34,7 @@ import java.util.List;
public class EmergencyInfoPreferenceController extends PreferenceController {
private static final String KEY_EMERGENCY_INFO = "emergency_info";
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENGY_INFO";
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
private static final String PACKAGE_NAME_EMERGENCY = "com.android.emergency";
public EmergencyInfoPreferenceController(Context context) {

View File

@@ -57,6 +57,11 @@ public class UserAndAccountDashboardFragment extends DashboardFragment {
return R.xml.user_and_accounts_settings;
}
@Override
protected int getHelpResource() {
return R.string.help_url_user_and_account_dashboard;
}
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
final List<PreferenceController> controllers = new ArrayList<>();

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2017 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.view.accessibility.AccessibilityManager;
/**
* This class replicates a subset of the {@link android.view.accessibility.AccessibilityManager}.
* The interface exists so that we can use a thin wrapper around the AccessibilityManager in
* production code and a mock in tests.
*/
public class AccessibilityManagerWrapperImpl {
/**
* Determines if the accessibility button within the system navigation area is supported.
*
* @return {@code true} if the accessibility button is supported on this device,
* {@code false} otherwise
* @hide
*/
public static boolean isAccessibilityButtonSupported() {
return AccessibilityManager.isAccessibilityButtonSupported();
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2017 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.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
/**
* This interface replicates a subset of the
* {@link android.accessibilityservice.AccessibilityServiceInfo}. The interface
* exists so that we can use a thin wrapper around it in production code and a mock in tests.
* We cannot directly mock or shadow it, because some of the methods we rely on are newer than
* the API version supported by Robolectric.
*/
public interface AccessibilityServiceInfoWrapper {
/**
* Returns the real {@code AccessibilityServiceInfo} object.
*/
AccessibilityServiceInfo getAccessibilityServiceInfo();
ComponentName getComponentName();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2017 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.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
public class AccessibilityServiceInfoWrapperImpl implements AccessibilityServiceInfoWrapper {
private final AccessibilityServiceInfo mServiceInfo;
public AccessibilityServiceInfoWrapperImpl(AccessibilityServiceInfo serviceInfo) {
mServiceInfo = serviceInfo;
}
@Override
public AccessibilityServiceInfo getAccessibilityServiceInfo() {
return mServiceInfo;
}
@Override
public ComponentName getComponentName() {
return mServiceInfo.getComponentName();
}
}

View File

@@ -18,8 +18,8 @@ package com.android.settings.applications;
import android.app.Activity;
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
@@ -57,6 +57,15 @@ public class AdvancedAppSettings extends DashboardFragment {
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.APPLICATIONS_ADVANCED;
}
private static List<PreferenceController> buildPreferenceControllers(Context context) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new DefaultBrowserPreferenceController(context));
controllers.add(new DefaultWorkBrowserPreferenceController(context));
@@ -68,11 +77,6 @@ public class AdvancedAppSettings extends DashboardFragment {
return controllers;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.APPLICATIONS_ADVANCED;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
@@ -94,6 +98,11 @@ public class AdvancedAppSettings extends DashboardFragment {
.getPreferenceKey());
return keys;
}
@Override
public List<PreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
};
static class SummaryProvider implements SummaryLoader.SummaryProvider {
@@ -118,10 +127,10 @@ public class AdvancedAppSettings extends DashboardFragment {
return;
}
CharSequence summary = concatSummaryText(
mDefaultSmsPreferenceController.getDefaultAppLabel(),
mDefaultBrowserPreferenceController.getDefaultAppLabel());
mDefaultSmsPreferenceController.getDefaultAppLabel(),
mDefaultBrowserPreferenceController.getDefaultAppLabel());
summary = concatSummaryText(summary,
mDefaultPhonePreferenceController.getDefaultAppLabel());
mDefaultPhonePreferenceController.getDefaultAppLabel());
if (!TextUtils.isEmpty(summary)) {
mSummaryLoader.setSummary(this, summary);
}
@@ -139,11 +148,11 @@ public class AdvancedAppSettings extends DashboardFragment {
}
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
new SummaryLoader.SummaryProviderFactory() {
@Override
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
SummaryLoader summaryLoader) {
return new AdvancedAppSettings.SummaryProvider(activity, summaryLoader);
}
};
new SummaryLoader.SummaryProviderFactory() {
@Override
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
SummaryLoader summaryLoader) {
return new AdvancedAppSettings.SummaryProvider(activity, summaryLoader);
}
};
}

View File

@@ -16,6 +16,9 @@
package com.android.settings.applications;
import android.app.Activity;
import android.app.Application;
import android.app.Fragment;
import android.content.Context;
import android.provider.SearchIndexableResource;
@@ -47,7 +50,12 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
mProgressiveDisclosureMixin.setTileLimit(3);
mProgressiveDisclosureMixin.setTileLimit(4);
}
@Override
protected int getHelpResource() {
return R.string.help_url_apps_and_notifications;
}
@Override
@@ -57,14 +65,24 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
final Activity activity = getActivity();
final Application app;
if (activity != null) {
app = activity.getApplication();
} else {
app = null;
}
return buildPreferenceControllers(context, app, this);
}
private static List<PreferenceController> buildPreferenceControllers(Context context) {
private static List<PreferenceController> buildPreferenceControllers(Context context,
Application app, Fragment host) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new EmergencyBroadcastPreferenceController(context,
"app_and_notif_cell_broadcast_settings"));
controllers.add(new SpecialAppAccessPreferenceController(context));
controllers.add(new AppPermissionsPreferenceController(context));
controllers.add(new RecentAppsPreferenceController(context, app, host));
return controllers;
}
@@ -80,7 +98,7 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
@Override
public List<PreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
return buildPreferenceControllers(context, null, null /* host */);
}
@Override

View File

@@ -14,7 +14,6 @@
package com.android.settings.applications;
import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;

View File

@@ -35,6 +35,7 @@ import android.os.IBinder;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
@@ -293,7 +294,8 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
@Override
public void onReceive(Context context, Intent intent) {
String packageName = intent.getData().getSchemeSpecificPart();
if (!mFinishing && mAppEntry.info.packageName.equals(packageName)) {
if (!mFinishing && (mAppEntry == null || mAppEntry.info == null
|| TextUtils.equals(mAppEntry.info.packageName, packageName))) {
onPackageRemoved();
}
}

View File

@@ -16,17 +16,17 @@
package com.android.settings.applications;
import static com.android.settings.applications.AppHeaderController.ActionType;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.applications.AppUtils;
import static com.android.settings.widget.EntityHeaderController.ActionType;
public abstract class AppInfoWithHeader extends AppInfoBase {
private boolean mCreated;
@@ -41,9 +41,9 @@ public abstract class AppInfoWithHeader extends AppInfoBase {
mCreated = true;
if (mPackageInfo == null) return;
final Activity activity = getActivity();
final Preference pref = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this, null /* appHeader */)
final Preference pref = EntityHeaderController
.newInstance(activity, this, null /* header */)
.setRecyclerView(getListView(), getLifecycle())
.setIcon(IconDrawableFactory.newInstance(activity)
.getBadgedIcon(mPackageInfo.applicationInfo))
.setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))

View File

@@ -28,6 +28,7 @@ import android.content.pm.PermissionInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,6 +44,7 @@ import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.widget.EntityHeaderController;
import java.util.List;
@@ -64,7 +66,7 @@ public class AppOpsDetails extends InstrumentedPreferenceFragment {
final View appSnippet = mRootView.findViewById(R.id.app_snippet);
CharSequence label = mPm.getApplicationLabel(pkgInfo.applicationInfo);
Drawable icon = mPm.getApplicationIcon(pkgInfo.applicationInfo);
InstalledAppDetails.setupAppSnippet(appSnippet, label, icon,
setupAppSnippet(appSnippet, label, icon,
pkgInfo != null ? pkgInfo.versionName : null);
}
@@ -191,4 +193,30 @@ public class AppOpsDetails extends InstrumentedPreferenceFragment {
setIntentAndFinish(true, true);
}
}
/**
* @deprecated app info pages should use {@link EntityHeaderController} to show the app header.
*/
void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
CharSequence versionName) {
LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
appSnippet.findViewById(android.R.id.widget_frame));
ImageView iconView = appSnippet.findViewById(android.R.id.icon);
iconView.setImageDrawable(icon);
// Set application name.
TextView labelView = appSnippet.findViewById(android.R.id.title);
labelView.setText(label);
// Version number of application
TextView appVersion = appSnippet.findViewById(R.id.widget_text1);
if (!TextUtils.isEmpty(versionName)) {
appVersion.setSelected(true);
appVersion.setVisibility(View.VISIBLE);
appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
String.valueOf(versionName)));
} else {
appVersion.setVisibility(View.INVISIBLE);
}
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2017 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.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import java.util.List;
import java.util.Set;
public class AppPermissionsPreferenceController extends PreferenceController {
private static final String TAG = "AppPermissionPrefCtrl";
private static final String KEY_APP_PERMISSION_GROUPS = "manage_perms";
private static final String[] PERMISSION_GROUPS = new String[] {
"android.permission-group.LOCATION",
"android.permission-group.MICROPHONE",
"android.permission-group.CAMERA",
"android.permission-group.SMS",
"android.permission-group.CONTACTS",
"android.permission-group.PHONE"};
private static final int NUM_PERMISSION_TO_USE = 3;
private final PackageManager mPackageManager;
public AppPermissionsPreferenceController(Context context) {
super(context);
mPackageManager = context.getPackageManager();
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY_APP_PERMISSION_GROUPS;
}
@Override
public void updateState(Preference preference) {
final String summary = getSummary();
if (summary != null) {
preference.setSummary(summary);
}
}
/*
Summary text looks like: Apps using Permission1, Permission2, Permission3
The 3 permissions are the first three from the list which any app has granted:
Location, Microphone, Camera, Sms, Contacts, and Phone
*/
private String getSummary() {
final Set<String> permissions = getAllPermissionsInGroups();
Set<String> grantedPermissionGroups = getGrantedPermissionGroups(permissions);
CharSequence summary = null;
int count = 0;
for (String group : PERMISSION_GROUPS) {
if (!grantedPermissionGroups.contains(group)) {
continue;
}
summary = concatSummaryText(summary, group);
if (++count >= NUM_PERMISSION_TO_USE) {
break;
}
}
return count > 0 ? mContext.getString(R.string.app_permissions_summary, summary) : null;
}
private Set<String> getGrantedPermissionGroups(Set<String> permissions) {
ArraySet<String> grantedPermissionGroups = new ArraySet<>();
List<PackageInfo> installedPackages =
mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
for (PackageInfo installedPackage : installedPackages) {
if (installedPackage.permissions == null) {
continue;
}
for (PermissionInfo permissionInfo : installedPackage.permissions) {
if (permissions.contains(permissionInfo.name)
&& !grantedPermissionGroups.contains(permissionInfo.group)) {
grantedPermissionGroups.add(permissionInfo.group);
}
}
}
return grantedPermissionGroups;
}
private CharSequence concatSummaryText(CharSequence currentSummary, String permission) {
final CharSequence label = getPermissionGroupLabel(permission);
if (TextUtils.isEmpty(currentSummary)) {
return label;
}
return mContext.getString(R.string.join_many_items_middle, currentSummary, label);
}
private CharSequence getPermissionGroupLabel(String group) {
try {
final PermissionGroupInfo groupInfo = mPackageManager.getPermissionGroupInfo(group, 0);
return groupInfo.loadLabel(mPackageManager);
} catch (NameNotFoundException e) {
Log.e(TAG, "Error getting permissions label.", e);
}
return group;
}
private Set<String> getAllPermissionsInGroups() {
ArraySet<String> result = new ArraySet<>();
for (String group : PERMISSION_GROUPS) {
try {
final List<PermissionInfo> permissions =
mPackageManager.queryPermissionsByGroup(group, 0);
for (PermissionInfo permissionInfo : permissions) {
result.add(permissionInfo.name);
}
} catch (NameNotFoundException e) {
Log.e(TAG, "Error getting permissions in group "+group, e);
}
}
return result;
}
}

View File

@@ -29,14 +29,8 @@ import java.util.Set;
public interface ApplicationFeatureProvider {
/**
* Returns a new {@link AppHeaderController} instance to customize app header.
*/
AppHeaderController newAppHeaderController(Fragment fragment, View appHeader);
/**
*
* Returns a new {@link InstantAppButtonsController} instance for showing buttons
* only relevant to instant apps.
* Returns a new {@link InstantAppButtonsController} instance for showing buttons
* only relevant to instant apps.
*/
InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate);
@@ -45,7 +39,7 @@ public interface ApplicationFeatureProvider {
* Calculates the total number of apps installed on the device via policy in the current user
* and all its managed profiles.
*
* @param async Whether to count asynchronously in a background thread
* @param async Whether to count asynchronously in a background thread
* @param callback The callback to invoke with the result
*/
void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback);
@@ -62,10 +56,10 @@ public interface ApplicationFeatureProvider {
* Asynchronously calculates the total number of apps installed in the current user and all its
* managed profiles that have been granted one or more of the given permissions by the admin.
*
* @param permissions Only consider apps that have been granted one or more of these permissions
* by the admin, either at run-time or install-time
* @param async Whether to count asynchronously in a background thread
* @param callback The callback to invoke with the result
* @param permissions Only consider apps that have been granted one or more of these
* permissions by the admin, either at run-time or install-time
* @param async Whether to count asynchronously in a background thread
* @param callback The callback to invoke with the result
*/
void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions, boolean async,
NumberOfAppsCallback callback);
@@ -74,9 +68,9 @@ public interface ApplicationFeatureProvider {
* Asynchronously builds the list of apps installed in the current user and all its
* managed profiles that have been granted one or more of the given permissions by the admin.
*
* @param permissions Only consider apps that have been granted one or more of these permissions
* by the admin, either at run-time or install-time
* @param callback The callback to invoke with the result
* @param permissions Only consider apps that have been granted one or more of these
* permissions by the admin, either at run-time or install-time
* @param callback The callback to invoke with the result
*/
void listAppsWithAdminGrantedPermissions(String[] permissions, ListOfAppsCallback callback);
@@ -86,10 +80,9 @@ public interface ApplicationFeatureProvider {
* given intent (e.g. open browser), even if the user has other apps installed that would also
* be able to handle the intent.
*
* @param userId ID of the user for which to find persistent preferred activities
* @param intent The intents for which to find persistent preferred activities
*
* @return the persistent preferred activites for the given intents, ordered first by user id,
* @param userId ID of the user for which to find persistent preferred activities
* @param intents The intents for which to find persistent preferred activities
* @return the persistent preferred activities for the given intents, ordered first by user id,
* then by package name
*/
List<UserAppInfo> findPersistentPreferredActivities(@UserIdInt int userId, Intent[] intents);

View File

@@ -24,7 +24,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.view.View;
@@ -53,11 +52,6 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
mUm = UserManager.get(mContext);
}
@Override
public AppHeaderController newAppHeaderController(Fragment fragment, View appHeader) {
return new AppHeaderController(mContext, fragment, appHeader);
}
@Override
public InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate) {

View File

@@ -24,16 +24,15 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.ChooseLockSettingsHelper;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
/* Class to prompt for conversion of userdata to file based encryption
*/
public class ConvertToFbe extends SettingsPreferenceFragment {
public class ConvertToFbe extends InstrumentedFragment {
static final String TAG = "ConvertToFBE";
static final String CONVERT_FBE_EXTRA = "ConvertFBE";
private static final int KEYGUARD_REQUEST = 55;

View File

@@ -20,8 +20,6 @@ import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
@@ -206,33 +204,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
public static CharSequence getSummary(Context context, OverlayState overlayState) {
return context.getString(overlayState.isPermissible() ?
R.string.system_alert_window_on : R.string.system_alert_window_off);
}
public static CharSequence getSummary(Context context, String pkg) {
// first check if pkg is a system pkg
PackageManager packageManager = context.getPackageManager();
int uid = -1;
try {
ApplicationInfo appInfo = packageManager.getApplicationInfo(pkg, 0);
uid = appInfo.uid;
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return context.getString(R.string.system_alert_window_on);
}
} catch (PackageManager.NameNotFoundException e) {
// pkg doesn't even exist?
Log.w(LOG_TAG, "Package " + pkg + " not found", e);
return context.getString(R.string.system_alert_window_off);
}
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context
.APP_OPS_SERVICE);
if (uid == -1) {
return context.getString(R.string.system_alert_window_off);
}
int mode = appOpsManager.noteOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, pkg);
return context.getString((mode == AppOpsManager.MODE_ALLOWED) ?
R.string.system_alert_window_on : R.string.system_alert_window_off);
R.string.app_permission_summary_allowed : R.string.app_permission_summary_not_allowed);
}
}

View File

@@ -15,11 +15,6 @@
*/
package com.android.settings.applications;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.Context;
@@ -29,12 +24,16 @@ import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
public class ExternalSourcesDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
@@ -90,15 +89,12 @@ public class ExternalSourcesDetails extends AppInfoWithHeader
return context.getString(R.string.disabled);
}
final InstallAppsState appsState;
if (entry.extraInfo instanceof InstallAppsState) {
appsState = (InstallAppsState) entry.extraInfo;
} else {
appsState = new AppStateInstallAppsBridge(context, null, null)
.createInstallAppsStateFor(entry.info.packageName, entry.info.uid);
}
return context.getString(appsState.canInstallApps() ? R.string.external_source_trusted
: R.string.external_source_untrusted);
final InstallAppsState appsState = new AppStateInstallAppsBridge(context, null, null)
.createInstallAppsStateFor(entry.info.packageName, entry.info.uid);
return context.getString(appsState.canInstallApps()
? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed);
}
private void setCanInstallApps(boolean newState) {

View File

@@ -37,7 +37,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.icu.text.ListFormatter;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
@@ -60,16 +59,12 @@ import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.IWebViewUpdateService;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.BatterySipper;
@@ -96,7 +91,7 @@ import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.AppItem;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
@@ -214,7 +209,7 @@ public class InstalledAppDetails extends AppInfoBase
@Override
public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) {
return new BatteryStatsHelperLoader(getContext(), args);
return new BatteryStatsHelperLoader(getContext());
}
@Override
@@ -381,7 +376,7 @@ public class InstalledAppDetails extends AppInfoBase
}
setHasOptionsMenu(true);
addPreferencesFromResource(R.xml.installed_app_details_ia);
addPreferencesFromResource(R.xml.installed_app_details);
addDynamicPrefs();
if (Utils.isBandwidthControlEnabled()) {
INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
@@ -447,14 +442,13 @@ public class InstalledAppDetails extends AppInfoBase
final Activity activity = getActivity();
mHeader = (LayoutPreference) findPreference(KEY_HEADER);
mActionButtons = (LayoutPreference) findPreference(KEY_ACTION_BUTTONS);
FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header))
.setRecyclerView(getListView(), getLifecycle())
.setPackageName(mPackageName)
.setButtonActions(AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
AppHeaderController.ActionType.ACTION_NONE)
.setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
EntityHeaderController.ActionType.ACTION_NONE)
.styleActionBar(activity)
.bindAppHeaderButtons();
.bindHeaderButtons();
prepareUninstallAndStop();
mNotificationPreference = findPreference(KEY_NOTIFICATION);
@@ -620,20 +614,18 @@ public class InstalledAppDetails extends AppInfoBase
// Utility method to set application label and icon.
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
final View appSnippet = mHeader.findViewById(R.id.app_snippet);
final View appSnippet = mHeader.findViewById(R.id.entity_header);
mState.ensureIcon(mAppEntry);
final Activity activity = getActivity();
final boolean isInstantApp = AppUtils.isInstant(mPackageInfo.applicationInfo);
final CharSequence summary =
isInstantApp ? null : getString(Utils.getInstallationStatus(mAppEntry.info));
FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this, appSnippet)
.setLabel(mAppEntry)
.setIcon(mAppEntry)
.setSummary(summary)
.setIsInstantApp(isInstantApp)
.done(activity, false /* rebindActions */);
EntityHeaderController.newInstance(activity, this, appSnippet)
.setLabel(mAppEntry)
.setIcon(mAppEntry)
.setSummary(summary)
.setIsInstantApp(isInstantApp)
.done(activity, false /* rebindActions */);
mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
}
@@ -1058,9 +1050,10 @@ public class InstalledAppDetails extends AppInfoBase
} else if (preference == mBatteryPreference) {
if (isBatteryStatsAvailable()) {
BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper);
entry.defaultPackageName = mPackageName;
AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
this, mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry,
mBatteryPercent);
mBatteryPercent, null /* mAnomalies */);
} else {
AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(),
this, mPackageName);
@@ -1256,7 +1249,8 @@ public class InstalledAppDetails extends AppInfoBase
Preference pref = findPreference("default_home");
if (pref != null) {
pref.setSummary(DefaultHomePreferenceController.isHomeDefault(mPackageName, context)
pref.setSummary(DefaultHomePreferenceController.isHomeDefault(mPackageName,
new PackageManagerWrapperImpl(context.getPackageManager()))
? R.string.yes : R.string.no);
}
pref = findPreference("default_browser");
@@ -1300,32 +1294,6 @@ public class InstalledAppDetails extends AppInfoBase
}
}
/**
* @deprecated app info pages should use {@link AppHeaderController} to show the app header.
*/
public static void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
CharSequence versionName) {
LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
(ViewGroup) appSnippet.findViewById(android.R.id.widget_frame));
ImageView iconView = (ImageView) appSnippet.findViewById(R.id.app_detail_icon);
iconView.setImageDrawable(icon);
// Set application name.
TextView labelView = (TextView) appSnippet.findViewById(R.id.app_detail_title);
labelView.setText(label);
// Version number of application
TextView appVersion = (TextView) appSnippet.findViewById(R.id.widget_text1);
if (!TextUtils.isEmpty(versionName)) {
appVersion.setSelected(true);
appVersion.setVisibility(View.VISIBLE);
appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
String.valueOf(versionName)));
} else {
appVersion.setVisibility(View.INVISIBLE);
}
}
public static NetworkTemplate getTemplate(Context context) {
if (DataUsageList.hasReadyMobileRadio(context)) {
return NetworkTemplate.buildTemplateMobileWildcard();

View File

@@ -19,6 +19,7 @@ package com.android.settings.applications;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.VisibleForTesting;
import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
@@ -33,19 +34,30 @@ import com.android.settings.Utils;
public class LayoutPreference extends Preference {
private final View.OnClickListener mClickListener = v -> performClick(v);
private boolean mAllowDividerAbove;
private boolean mAllowDividerBelow;
@VisibleForTesting
View mRootView;
public LayoutPreference(Context context, AttributeSet attrs) {
super(context, attrs);
final TypedArray a = context.obtainStyledAttributes(
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference);
mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove,
R.styleable.Preference_allowDividerAbove, false);
mAllowDividerBelow = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerBelow,
R.styleable.Preference_allowDividerBelow, false);
a.recycle();
a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.Preference, 0, 0);
int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
0);
if (layoutResource == 0) {
throw new IllegalArgumentException("LayoutPreference requires a layout to be defined");
}
a.recycle();
// Need to create view now so that findViewById can be called immediately.
final View view = LayoutInflater.from(getContext())
.inflate(layoutResource, null, false);
@@ -78,6 +90,8 @@ public class LayoutPreference extends Preference {
final boolean selectable = isSelectable();
holder.itemView.setFocusable(selectable);
holder.itemView.setClickable(selectable);
holder.setDividerAllowedAbove(mAllowDividerAbove);
holder.setDividerAllowedBelow(mAllowDividerBelow);
FrameLayout layout = (FrameLayout) holder.itemView;
layout.removeAllViews();
@@ -88,7 +102,7 @@ public class LayoutPreference extends Preference {
layout.addView(mRootView);
}
public View findViewById(int id) {
public <T extends View> T findViewById(int id) {
return mRootView.findViewById(id);
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import com.android.settings.R;
public class LinearColorPreference extends Preference {
float mRedRatio;
float mYellowRatio;
float mGreenRatio;
int mRedColor = 0xffaa5030;
int mYellowColor = 0xffaaaa30;
int mGreenColor = 0xff30aa50;
int mColoredRegions = LinearColorBar.REGION_ALL;
LinearColorBar.OnRegionTappedListener mOnRegionTappedListener;
public LinearColorPreference(Context context) {
super(context);
setLayoutResource(R.layout.preference_linearcolor);
}
public void setRatios(float red, float yellow, float green) {
mRedRatio = red;
mYellowRatio = yellow;
mGreenRatio = green;
notifyChanged();
}
public void setColors(int red, int yellow, int green) {
mRedColor = red;
mYellowColor = yellow;
mGreenColor = green;
notifyChanged();
}
public void setOnRegionTappedListener(LinearColorBar.OnRegionTappedListener listener) {
mOnRegionTappedListener = listener;
notifyChanged();
}
public void setColoredRegions(int regions) {
mColoredRegions = regions;
notifyChanged();
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
LinearColorBar colors = (LinearColorBar)view.findViewById(
R.id.linear_color_bar);
colors.setShowIndicator(false);
colors.setColors(mRedColor, mYellowColor, mGreenColor);
colors.setRatios(mRedRatio, mYellowRatio, mGreenRatio);
colors.setColoredRegions(mColoredRegions);
colors.setOnRegionTappedListener(mOnRegionTappedListener);
}
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.applications;
import android.annotation.IdRes;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -148,7 +149,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
public static final int FILTER_APPS_COUNT = 13; // This should always be the last entry
// Mapping to string labels for the FILTER_APPS_* constants above.
public static final @IdRes int[] FILTER_LABELS = new int[FILTER_APPS_COUNT];
@IdRes
public static final int[] FILTER_LABELS = new int[FILTER_APPS_COUNT];
// Mapping to filters for the FILTER_APPS_* constants above.
public static final AppFilter[] FILTERS = new AppFilter[FILTER_APPS_COUNT];
@@ -212,8 +214,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
// Storage types. Used to determine what the extra item in the list of preferences is.
public static final int STORAGE_TYPE_DEFAULT = 0;
public static final int STORAGE_TYPE_DEFAULT = 0; // Show all apps that are not categorized.
public static final int STORAGE_TYPE_MUSIC = 1;
public static final int STORAGE_TYPE_LEGACY = 2; // Show apps even if they can be categorized.
// sort order
private int mSortOrder = R.id.sort_order_alpha;
@@ -261,8 +264,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
// List types that should show instant apps.
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
LIST_TYPE_MAIN,
LIST_TYPE_STORAGE));
LIST_TYPE_MAIN,
LIST_TYPE_STORAGE));
private View mRootView;
@@ -338,13 +341,12 @@ public class ManageApplications extends InstrumentedPreferenceFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
// initialize the inflater
mInflater = inflater;
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
mLoadingContainer = mRootView.findViewById(R.id.loading_container);
mLoadingContainer.setVisibility(View.VISIBLE);
mListContainer = mRootView.findViewById(R.id.list_container);
if (mListContainer != null) {
// Create adapter and list view here
@@ -393,7 +395,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
return mRootView;
}
private void createHeader() {
@VisibleForTesting
void createHeader() {
Activity activity = getActivity();
FrameLayout pinnedHeader = (FrameLayout) mRootView.findViewById(R.id.pinned_header);
mSpinnerHeader = activity.getLayoutInflater()
@@ -425,12 +428,13 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
@VisibleForTesting
static @Nullable AppFilter getCompositeFilter(int listType, int storageType, String volumeUuid) {
@Nullable
static AppFilter getCompositeFilter(int listType, int storageType, String volumeUuid) {
AppFilter filter = new VolumeFilter(volumeUuid);
if (listType == LIST_TYPE_STORAGE) {
if (storageType == STORAGE_TYPE_MUSIC) {
filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter);
} else {
} else if (storageType == STORAGE_TYPE_DEFAULT) {
filter = new CompoundFilter(ApplicationsState.FILTER_OTHER_APPS, filter);
}
return filter;
@@ -506,10 +510,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
@Override
public void onResume() {
super.onResume();
public void onStart() {
super.onStart();
updateView();
updateOptionsMenu();
if (mApplications != null) {
mApplications.resume(mSortOrder);
mApplications.updateLoading();
@@ -527,16 +530,11 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
@Override
public void onPause() {
super.onPause();
public void onStop() {
super.onStop();
if (mApplications != null) {
mApplications.pause();
}
}
@Override
public void onStop() {
super.onStop();
mResetAppsHelper.stop();
}
@@ -572,8 +570,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
private void startApplicationDetailsActivity() {
switch (mListType) {
case LIST_TYPE_NOTIFICATION:
startAppInfoFragment(AppNotificationSettings.class,
R.string.app_notifications_title);
startAppInfoFragment(AppNotificationSettings.class, R.string.notifications_title);
break;
case LIST_TYPE_USAGE_ACCESS:
startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
@@ -601,8 +598,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
startAppInfoFragment(AppStorageSettings.class, R.string.storage_movies_tv);
break;
// 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.
// 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.
default:
startAppInfoFragment(InstalledAppDetails.class, R.string.application_info_label);
break;
@@ -616,8 +613,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
HelpUtils.prepareHelpMenuItem(getActivity(), menu, mListType == LIST_TYPE_MAIN
? R.string.help_uri_apps : R.string.help_uri_notifications, getClass().getName());
HelpUtils.prepareHelpMenuItem(getActivity(), menu, getHelpResource(), getClass().getName());
mOptionsMenu = menu;
inflater.inflate(R.menu.manage_apps, menu);
updateOptionsMenu();
@@ -633,11 +629,21 @@ public class ManageApplications extends InstrumentedPreferenceFragment
mOptionsMenu = null;
}
@StringRes
int getHelpResource() {
if (mListType == LIST_TYPE_MAIN) {
return R.string.help_uri_apps;
} else if (mListType == LIST_TYPE_USAGE_ACCESS) {
return R.string.help_url_usage_access;
} else {
return R.string.help_uri_notifications;
}
}
void updateOptionsMenu() {
if (mOptionsMenu == null) {
return;
}
final Context context = getActivity();
mOptionsMenu.findItem(R.id.advanced).setVisible(false);
mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
@@ -649,6 +655,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
&& mListType != LIST_TYPE_HIGH_POWER);
mOptionsMenu.findItem(R.id.hide_system).setVisible(mShowSystem
&& mListType != LIST_TYPE_HIGH_POWER);
mOptionsMenu.findItem(R.id.reset_app_preferences).setVisible(mListType == LIST_TYPE_MAIN);
}
@Override
@@ -675,7 +683,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
if (mListType == LIST_TYPE_NOTIFICATION) {
((SettingsActivity) getActivity()).startPreferencePanel(this,
ConfigureNotificationSettings.class.getName(), null,
R.string.configure_notification_settings, null, this, ADVANCED_SETTINGS);
R.string.configure_notification_settings, null, this,
ADVANCED_SETTINGS);
} else {
((SettingsActivity) getActivity()).startPreferencePanel(this,
AdvancedAppSettings.class.getName(), null, R.string.configure_apps,
@@ -826,6 +835,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
static class ApplicationsAdapter extends BaseAdapter implements Filterable,
ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
AbsListView.RecyclerListener, SectionIndexer {
// how long to wait for app list to populate without showing the loading container
private static final long DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS = 100L;
private static final SectionInfo[] EMPTY_SECTIONS = new SectionInfo[0];
private final ApplicationsState mState;
@@ -881,8 +894,15 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
};
private Runnable mShowLoadingContainerRunnable = new Runnable() {
public void run() {
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
mManageApplications.mListContainer, false /* done */, false /* animate */);
}
};
public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
int filterMode) {
int filterMode) {
mState = state;
mFgHandler = new Handler();
mBgHandler = new Handler(mState.getBackgroundLooper());
@@ -955,7 +975,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
// Record the current scroll position before pausing.
mLastIndex = mManageApplications.mListView.getFirstVisiblePosition();
View v = mManageApplications.mListView.getChildAt(0);
mLastTop = (v == null) ? 0 : (v.getTop() - mManageApplications.mListView.getPaddingTop());
mLastTop =
(v == null) ? 0 : (v.getTop() - mManageApplications.mListView.getPaddingTop());
}
public void release() {
@@ -1042,8 +1063,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
private ArrayList<ApplicationsState.AppEntry> removeDuplicateIgnoringUser(
ArrayList<ApplicationsState.AppEntry> entries)
{
ArrayList<ApplicationsState.AppEntry> entries) {
int size = entries.size();
// returnList will not have more entries than entries
ArrayList<ApplicationsState.AppEntry> returnEntries = new
@@ -1089,6 +1109,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
if (mSession.getAllApps().size() != 0
&& mManageApplications.mListContainer.getVisibility() != View.VISIBLE) {
// Cancel any pending task to show the loading animation and show the list of
// apps directly.
mFgHandler.removeCallbacks(mShowLoadingContainerRunnable);
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
mManageApplications.mListContainer, true, true);
}
@@ -1102,7 +1125,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
private void rebuildSections() {
if (mEntries!= null && mManageApplications.mListView.isFastScrollEnabled()) {
if (mEntries != null && mManageApplications.mListView.isFastScrollEnabled()) {
// Rebuild sections
if (mIndex == null) {
LocaleList locales = mContext.getResources().getConfiguration().getLocales();
@@ -1140,14 +1163,20 @@ public class ManageApplications extends InstrumentedPreferenceFragment
}
}
private void updateLoading() {
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
mManageApplications.mListContainer,
mHasReceivedLoadEntries && mSession.getAllApps().size() != 0, false);
@VisibleForTesting
void updateLoading() {
final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
if (appLoaded) {
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
mManageApplications.mListContainer, true /* done */, false /* animate */);
} else {
mFgHandler.postDelayed(
mShowLoadingContainerRunnable, DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS);
}
}
ArrayList<ApplicationsState.AppEntry> applyPrefixFilter(CharSequence prefix,
ArrayList<ApplicationsState.AppEntry> origEntries) {
ArrayList<ApplicationsState.AppEntry> origEntries) {
if (prefix == null || prefix.length() == 0) {
return origEntries;
} else {
@@ -1366,8 +1395,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
case LIST_TYPE_USAGE_ACCESS:
if (holder.entry.extraInfo != null) {
holder.summary.setText((new UsageState((PermissionState) holder.entry
.extraInfo)).isPermissible() ? R.string.switch_on_text :
R.string.switch_off_text);
.extraInfo)).isPermissible()
? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed);
} else {
holder.summary.setText(null);
}
@@ -1468,7 +1498,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
= new SummaryLoader.SummaryProviderFactory() {
@Override
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
SummaryLoader summaryLoader) {
SummaryLoader summaryLoader) {
return new SummaryProvider(activity, summaryLoader);
}
};

View File

@@ -19,6 +19,7 @@ package com.android.settings.applications;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.InsetDrawable;
import android.os.UserHandle;
import android.provider.DocumentsContract;
import android.support.annotation.WorkerThread;
@@ -38,6 +39,7 @@ public class MusicViewHolderController implements FileViewHolderController {
private static final String TAG = "MusicViewHolderController";
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
private static final int INSET_SIZE = 24; // dp
private Context mContext;
private StorageStatsSource mSource;
@@ -71,7 +73,8 @@ public class MusicViewHolderController implements FileViewHolderController {
@Override
public void setupView(AppViewHolder holder) {
holder.appIcon.setImageDrawable(mContext.getDrawable(R.drawable.ic_headset_24dp));
holder.appIcon.setImageDrawable(
new InsetDrawable(mContext.getDrawable(R.drawable.ic_headset_24dp), INSET_SIZE));
holder.appName.setText(mContext.getText(R.string.audio_files_title));
holder.summary.setText(Formatter.formatFileSize(mContext, mMusicSize));
}

View File

@@ -17,7 +17,6 @@ package com.android.settings.applications;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import com.android.settings.R;
import com.android.settings.dashboard.SummaryLoader;
@@ -29,23 +28,24 @@ import com.android.settings.notification.NotificationBackend;
*/
public class NotificationApps extends ManageApplications {
private static class SummaryProvider implements SummaryLoader.SummaryProvider {
public static class SummaryProvider implements SummaryLoader.SummaryProvider {
private final Context mContext;
private final SummaryLoader mLoader;
private final NotificationBackend mNotificationBackend;
private final PackageManagerWrapper mPackageManager;
private SummaryProvider(Context context, SummaryLoader loader) {
public SummaryProvider(Context context, SummaryLoader loader) {
mContext = context;
mLoader = loader;
mNotificationBackend = new NotificationBackend();
mPackageManager = new PackageManagerWrapperImpl(mContext.getPackageManager());
}
@Override
public void setListening(boolean listening) {
if (listening) {
new AppCounter(mContext,
new PackageManagerWrapperImpl(mContext.getPackageManager())) {
new AppCounter(mContext, mPackageManager) {
@Override
protected void onCountComplete(int num) {
updateSummary(num);

View File

@@ -101,13 +101,16 @@ public interface PackageManagerWrapper {
void replacePreferredActivity(IntentFilter homeFilter, int matchCategoryEmpty,
ComponentName[] componentNames, ComponentName component);
/**
* Calls {@code PackageManager.getPrimaryStorageCurrentVolume}
*/
VolumeInfo getPrimaryStorageCurrentVolume();
/**
* Calls {@code PackageManager.deletePackageAsUser}
*/
void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
int userId);
/**
* Calls {@code PackageManager.getPrimaryStorageCurrentVolume}
*/
VolumeInfo getPrimaryStorageCurrentVolume();
int getPackageUidAsUser(String pkg, int userId) throws PackageManager.NameNotFoundException;
}

View File

@@ -93,6 +93,11 @@ public class PackageManagerWrapperImpl implements PackageManagerWrapper {
mPm.replacePreferredActivity(homeFilter, matchCategoryEmpty, componentNames, component);
}
@Override
public VolumeInfo getPrimaryStorageCurrentVolume() {
return mPm.getPrimaryStorageCurrentVolume();
}
@Override
public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
int userId) {
@@ -100,7 +105,8 @@ public class PackageManagerWrapperImpl implements PackageManagerWrapper {
}
@Override
public VolumeInfo getPrimaryStorageCurrentVolume() {
return mPm.getPrimaryStorageCurrentVolume();
public int getPackageUidAsUser(String pkg, int userId)
throws PackageManager.NameNotFoundException {
return mPm.getPackageUidAsUser(pkg, userId);
}
}

View File

@@ -15,10 +15,6 @@
*/
package com.android.settings.applications;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.Context;
@@ -34,6 +30,10 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
public class PictureInPictureDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
@@ -124,7 +124,8 @@ public class PictureInPictureDetails extends AppInfoWithHeader
static int getPreferenceSummary(Context context, int uid, String packageName) {
final boolean enabled = PictureInPictureDetails.getEnterPipStateForPackage(context, uid,
packageName);
return enabled ? R.string.picture_in_picture_on : R.string.picture_in_picture_off;
return enabled ? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed;
}
@VisibleForTesting

View File

@@ -16,8 +16,6 @@
package com.android.settings.applications;
import static com.android.settings.applications.AppHeaderController.ActionType;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
@@ -53,7 +51,7 @@ import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.SummaryPreference;
import com.android.settings.applications.ProcStatsEntry.Service;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
import java.util.ArrayList;
import java.util.Collections;
@@ -61,6 +59,8 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import static com.android.settings.widget.EntityHeaderController.ActionType;
public class ProcessStatsDetail extends SettingsPreferenceFragment {
private static final String TAG = "ProcessStatsDetail";
@@ -126,19 +126,19 @@ public class ProcessStatsDetail extends SettingsPreferenceFragment {
return;
}
final Activity activity = getActivity();
final Preference pref = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this, null /* appHeader */)
.setIcon(mApp.mUiTargetApp != null
? IconDrawableFactory.newInstance(activity).getBadgedIcon(mApp.mUiTargetApp)
: new ColorDrawable(0))
.setLabel(mApp.mUiLabel)
.setPackageName(mApp.mPackage)
.setUid(mApp.mUiTargetApp != null
? mApp.mUiTargetApp.uid
: UserHandle.USER_NULL)
.setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
.done(activity, getPrefContext());
final Preference pref = EntityHeaderController
.newInstance(activity, this, null /* appHeader */)
.setRecyclerView(getListView(), getLifecycle())
.setIcon(mApp.mUiTargetApp != null
? IconDrawableFactory.newInstance(activity).getBadgedIcon(mApp.mUiTargetApp)
: new ColorDrawable(0))
.setLabel(mApp.mUiLabel)
.setPackageName(mApp.mPackage)
.setUid(mApp.mUiTargetApp != null
? mApp.mUiTargetApp.uid
: UserHandle.USER_NULL)
.setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
.done(activity, getPrefContext());
getPreferenceScreen().addPreference(pref);
}

View File

@@ -102,6 +102,11 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
return MetricsEvent.PROCESS_STATS_SUMMARY;
}
@Override
protected int getHelpResource() {
return R.string.help_uri_process_stats_summary;
}
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == mAppListPreference) {

View File

@@ -95,6 +95,11 @@ public class ProcessStatsUi extends ProcessStatsBase {
return MetricsEvent.APPLICATIONS_PROCESS_STATS_UI;
}
@Override
protected int getHelpResource() {
return R.string.help_uri_process_stats_apps;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);

View File

@@ -0,0 +1,320 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.Application;
import android.app.Fragment;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.applications.ApplicationsState;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.SETTINGS_APP_NOTIF_CATEGORY;
/**
* This controller displays a list of recently used apps and a "See all" button. If there is
* no recently used app, "See all" will be displayed as "App info".
*/
public class RecentAppsPreferenceController extends PreferenceController
implements Comparator<UsageStats> {
private static final String TAG = "RecentAppsCtrl";
private static final String KEY_PREF_CATEGORY = "recent_apps_category";
@VisibleForTesting
static final String KEY_DIVIDER = "all_app_info_divider";
@VisibleForTesting
static final String KEY_SEE_ALL = "all_app_info";
private static final int SHOW_RECENT_APP_COUNT = 5;
private static final Set<String> SKIP_SYSTEM_PACKAGES = new ArraySet<>();
private final Fragment mHost;
private final PackageManager mPm;
private final UsageStatsManager mUsageStatsManager;
private final ApplicationsState mApplicationsState;
private final int mUserId;
private final IconDrawableFactory mIconDrawableFactory;
private Calendar mCal;
private List<UsageStats> mStats;
private PreferenceCategory mCategory;
private Preference mSeeAllPref;
private Preference mDivider;
private boolean mHasRecentApps;
static {
SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList(
"android",
"com.android.phone",
"com.android.settings",
"com.android.systemui",
"com.android.providers.calendar",
"com.android.providers.media"
));
}
public RecentAppsPreferenceController(Context context, Application app, Fragment host) {
this(context, app == null ? null : ApplicationsState.getInstance(app), host);
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
RecentAppsPreferenceController(Context context, ApplicationsState appState, Fragment host) {
super(context);
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
mUserId = UserHandle.myUserId();
mPm = context.getPackageManager();
mHost = host;
mUsageStatsManager =
(UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
mApplicationsState = appState;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY_PREF_CATEGORY;
}
@Override
public void updateNonIndexableKeys(List<String> keys) {
super.updateNonIndexableKeys(keys);
// Don't index category name into search. It's not actionable.
keys.add(KEY_PREF_CATEGORY);
keys.add(KEY_DIVIDER);
}
@Override
public void displayPreference(PreferenceScreen screen) {
mCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
mSeeAllPref = screen.findPreference(KEY_SEE_ALL);
mDivider = screen.findPreference(KEY_DIVIDER);
super.displayPreference(screen);
refreshUi(mCategory.getContext());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
refreshUi(mCategory.getContext());
// Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
new PackageManagerWrapperImpl(mContext.getPackageManager())) {
@Override
protected void onCountComplete(int num) {
if (mHasRecentApps) {
mSeeAllPref.setTitle(mContext.getString(R.string.see_all_apps_title, num));
} else {
mSeeAllPref.setSummary(mContext.getString(R.string.apps_summary, num));
}
}
}.execute();
}
@Override
public final int compare(UsageStats a, UsageStats b) {
// return by descending order
return Long.compare(b.getLastTimeUsed(), a.getLastTimeUsed());
}
@VisibleForTesting
void refreshUi(Context prefContext) {
reloadData();
final List<UsageStats> recentApps = getDisplayableRecentAppList();
if (recentApps != null && !recentApps.isEmpty()) {
mHasRecentApps = true;
displayRecentApps(prefContext, recentApps);
} else {
mHasRecentApps = false;
displayOnlyAppInfo();
}
}
@VisibleForTesting
void reloadData() {
mCal = Calendar.getInstance();
mCal.add(Calendar.DAY_OF_YEAR, -1);
mStats = mUsageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST, mCal.getTimeInMillis(),
System.currentTimeMillis());
}
private void displayOnlyAppInfo() {
mCategory.setTitle(null);
mDivider.setVisible(false);
mSeeAllPref.setTitle(R.string.applications_settings);
mSeeAllPref.setIcon(null);
int prefCount = mCategory.getPreferenceCount();
for (int i = prefCount - 1; i >= 0; i--) {
final Preference pref = mCategory.getPreference(i);
if (!TextUtils.equals(pref.getKey(), KEY_SEE_ALL)) {
mCategory.removePreference(pref);
}
}
}
private void displayRecentApps(Context prefContext, List<UsageStats> recentApps) {
mCategory.setTitle(R.string.recent_app_category_title);
mDivider.setVisible(true);
mSeeAllPref.setSummary(null);
mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
// Rebind prefs/avoid adding new prefs if possible. Adding/removing prefs causes jank.
// Build a cached preference pool
final Map<String, Preference> appPreferences = new ArrayMap<>();
int prefCount = mCategory.getPreferenceCount();
for (int i = 0; i < prefCount; i++) {
final Preference pref = mCategory.getPreference(i);
final String key = pref.getKey();
if (!TextUtils.equals(key, KEY_SEE_ALL)) {
appPreferences.put(key, pref);
}
}
final int recentAppsCount = recentApps.size();
for (int i = 0; i < recentAppsCount; i++) {
final UsageStats stat = recentApps.get(i);
// Bind recent apps to existing prefs if possible, or create a new pref.
final String pkgName = stat.getPackageName();
final ApplicationsState.AppEntry appEntry =
mApplicationsState.getEntry(pkgName, mUserId);
if (appEntry == null) {
continue;
}
boolean rebindPref = true;
Preference pref = appPreferences.remove(pkgName);
if (pref == null) {
pref = new Preference(prefContext);
rebindPref = false;
}
pref.setKey(pkgName);
pref.setTitle(appEntry.label);
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
pref.setSummary(TextUtils.expandTemplate(
mContext.getResources().getText(R.string.recent_app_summary),
Utils.formatElapsedTime(mContext,
System.currentTimeMillis() - stat.getLastTimeUsed(), false)));
pref.setOrder(i);
pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
R.string.application_info_label, pkgName, appEntry.info.uid, mHost,
1001 /*RequestCode*/, SETTINGS_APP_NOTIF_CATEGORY);
return true;
});
if (!rebindPref) {
mCategory.addPreference(pref);
}
}
// Remove unused prefs from pref cache pool
for (Preference unusedPrefs : appPreferences.values()) {
mCategory.removePreference(unusedPrefs);
}
}
private List<UsageStats> getDisplayableRecentAppList() {
final List<UsageStats> recentApps = new ArrayList<>();
final Map<String, UsageStats> map = new ArrayMap<>();
final int statCount = mStats.size();
for (int i = 0; i < statCount; i++) {
final UsageStats pkgStats = mStats.get(i);
if (!shouldIncludePkgInRecents(pkgStats)) {
continue;
}
final String pkgName = pkgStats.getPackageName();
final UsageStats existingStats = map.get(pkgName);
if (existingStats == null) {
map.put(pkgName, pkgStats);
} else {
existingStats.add(pkgStats);
}
}
final List<UsageStats> packageStats = new ArrayList<>();
packageStats.addAll(map.values());
Collections.sort(packageStats, this /* comparator */);
int count = 0;
for (UsageStats stat : packageStats) {
final ApplicationsState.AppEntry appEntry = mApplicationsState.getEntry(
stat.getPackageName(), mUserId);
if (appEntry == null) {
continue;
}
recentApps.add(stat);
count++;
if (count >= SHOW_RECENT_APP_COUNT) {
break;
}
}
return recentApps;
}
/**
* Whether or not the app should be included in recent list.
*/
private boolean shouldIncludePkgInRecents(UsageStats stat) {
final String pkgName = stat.getPackageName();
if (stat.getLastTimeUsed() < mCal.getTimeInMillis()) {
Log.d(TAG, "Invalid timestamp, skipping " + pkgName);
return false;
}
if (SKIP_SYSTEM_PACKAGES.contains(pkgName)) {
Log.d(TAG, "System package, skipping " + pkgName);
return false;
}
final Intent launchIntent = new Intent().addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(pkgName);
if (mPm.resolveActivity(launchIntent, 0) == null) {
// Not visible on launcher -> likely not a user visible app, skip
Log.d(TAG, "Not a user visible app, skipping " + pkgName);
return false;
}
return true;
}
}

View File

@@ -22,10 +22,10 @@ import android.support.v7.preference.Preference;
import android.text.TextUtils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnCreate;
import com.android.settings.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
public class ResetAppPrefPreferenceController extends PreferenceController
implements LifecycleObserver, OnCreate, OnSaveInstanceState {

View File

@@ -17,6 +17,7 @@ package com.android.settings.applications;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
@@ -33,7 +34,9 @@ public class SpacePreference extends Preference {
private int mHeight;
public SpacePreference(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.preferenceStyle);
this(context, attrs, TypedArrayUtils.getAttr(context,
android.support.v7.preference.R.attr.preferenceStyle,
android.R.attr.preferenceStyle));
}
public SpacePreference(Context context, AttributeSet attrs, int defStyleAttr) {

View File

@@ -14,20 +14,54 @@
package com.android.settings.applications;
import android.os.Bundle;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
public class SpecialAccessSettings extends SettingsPreferenceFragment {
import java.util.ArrayList;
import java.util.List;
public class SpecialAccessSettings extends DashboardFragment {
private static final String TAG = "SpecialAccessSettings";
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.special_access);
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.special_access;
}
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
return null;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SPECIAL_ACCESS;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.special_access;
result.add(sir);
return result;
}
};
}

View File

@@ -20,8 +20,6 @@ import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
@@ -38,8 +36,6 @@ import com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettin
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import java.util.List;
public class WriteSettingsDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
OnPreferenceClickListener {
@@ -182,47 +178,8 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
}
public static CharSequence getSummary(Context context, WriteSettingsState writeSettingsState) {
return context.getString(writeSettingsState.isPermissible() ? R.string.write_settings_on :
R.string.write_settings_off);
}
public static CharSequence getSummary(Context context, String pkg) {
// first check if pkg is a system pkg
boolean isSystem = false;
PackageManager packageManager = context.getPackageManager();
try {
ApplicationInfo appInfo = packageManager.getApplicationInfo(pkg, 0);
if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
isSystem = true;
}
} catch (PackageManager.NameNotFoundException e) {
// pkg doesn't even exist?
Log.w(LOG_TAG, "Package " + pkg + " not found", e);
return context.getString(R.string.write_settings_off);
}
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context
.APP_OPS_SERVICE);
List<AppOpsManager.PackageOps> packageOps = appOpsManager.getPackagesForOps(
APP_OPS_OP_CODE);
if (packageOps == null) {
return context.getString(R.string.write_settings_off);
}
int uid = isSystem ? 0 : -1;
for (AppOpsManager.PackageOps packageOp : packageOps) {
if (pkg.equals(packageOp.getPackageName())) {
uid = packageOp.getUid();
break;
}
}
if (uid == -1) {
return context.getString(R.string.write_settings_off);
}
int mode = appOpsManager.noteOpNoThrow(AppOpsManager.OP_WRITE_SETTINGS, uid, pkg);
return context.getString((mode == AppOpsManager.MODE_ALLOWED) ?
R.string.write_settings_on : R.string.write_settings_off);
return context.getString(writeSettingsState.isPermissible()
? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed);
}
}

View File

@@ -26,10 +26,10 @@ import android.support.v7.preference.TwoStatePreference;
import com.android.internal.app.AssistUtils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.Arrays;
import java.util.List;

View File

@@ -28,10 +28,10 @@ import android.support.v7.preference.TwoStatePreference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.Arrays;
import java.util.List;

View File

@@ -26,10 +26,10 @@ import android.support.v7.preference.TwoStatePreference;
import com.android.internal.app.AssistUtils;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.Arrays;
import java.util.List;

View File

@@ -27,10 +27,10 @@ import android.text.TextUtils;
import com.android.internal.app.AssistUtils;
import com.android.settings.applications.defaultapps.DefaultAppInfo;
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.List;

View File

@@ -22,11 +22,11 @@ import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.gestures.AssistGesturePreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.Arrays;
@@ -72,7 +72,8 @@ public class ManageAssist extends DashboardFragment {
Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
controllers.add(new DefaultAssistPreferenceController(context));
controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
true /* assistOnly */));
controllers.add(new AssistContextPreferenceController(context, lifecycle));
controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
@@ -102,6 +103,5 @@ public class ManageAssist extends DashboardFragment {
keys.add(KEY_ASSIST);
return keys;
}
};
}

View File

@@ -23,11 +23,11 @@ import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.applications.PackageManagerWrapperImpl;
@@ -62,6 +62,16 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment
}
}
@Override
protected void onRadioButtonConfirmed(String selectedKey) {
mMetricsFeatureProvider.action(getContext(),
MetricsEvent.ACTION_SETTINGS_UPDATE_DEFAULT_APP,
selectedKey,
Pair.create(MetricsEvent.FIELD_CONTEXT, getMetricsCategory()));
super.onRadioButtonConfirmed(selectedKey);
}
@Override
public void bindPreferenceExtra(RadioButtonPreference pref,
String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
@@ -97,7 +107,7 @@ public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_APP_PICKER_CONFIRMATION_DIALOG;
return MetricsEvent.DEFAULT_APP_PICKER_CONFIRMATION_DIALOG;
}
/**

View File

@@ -18,16 +18,20 @@ package com.android.settings.applications.defaultapps;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.Log;
import java.util.List;
public class DefaultBrowserPreferenceController extends DefaultAppPreferenceController {
private static final String TAG = "BrowserPrefCtrl";
static final Intent BROWSE_PROBE = new Intent()
.setAction(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
@@ -60,9 +64,10 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
final String packageName = mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId);
Log.d(TAG, "Get default browser package: " + packageName);
return new DefaultAppInfo(mPackageManager,
mPackageManager.getPackageManager().getApplicationInfo(
mPackageManager.getDefaultBrowserPackageNameAsUser(mUserId), 0));
mPackageManager.getPackageManager().getApplicationInfo(packageName, 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
@@ -90,7 +95,12 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = getCandidates();
if (list != null && list.size() == 1) {
return list.get(0).loadLabel(mPackageManager.getPackageManager()).toString();
final ResolveInfo info = list.get(0);
final String label = info.loadLabel(mPackageManager.getPackageManager()).toString();
final ComponentInfo cn = info.getComponentInfo();
final String packageName = cn == null ? null : cn.packageName;
Log.d(TAG, "Getting label for the only browser app: " + packageName + label);
return label;
}
return null;
}

View File

@@ -26,6 +26,8 @@ import android.content.pm.ResolveInfo;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import com.android.settings.applications.PackageManagerWrapper;
import java.util.ArrayList;
import java.util.List;
@@ -106,11 +108,10 @@ public class DefaultHomePreferenceController extends DefaultAppPreferenceControl
return false;
}
public static boolean isHomeDefault(String pkg, Context context) {
ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
PackageManager pm = context.getPackageManager();
public static boolean isHomeDefault(String pkg, PackageManagerWrapper pm) {
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
ComponentName def = pm.getHomeActivities(homeActivities);
return def != null && def.getPackageName().equals(pkg);
return def == null || def.getPackageName().equals(pkg);
}
}

Some files were not shown because too many files have changed in this diff Show More