Merge commit '937ede14d84c2093f831ff8adab96dca207ad742' from
oc-mr1-dev-plus-aosp-without-vendor into stage-aosp-master Change-Id: I91ee596e3800726445cfff5dd784bae9dfdad3ee Merged-In: I91c48c73287a271bd6c99e60e216dead22e68764
This commit is contained in:
@@ -78,6 +78,10 @@ public class ActivityPicker extends AlertActivity implements
|
||||
Parcelable parcel = intent.getParcelableExtra(Intent.EXTRA_INTENT);
|
||||
if (parcel instanceof Intent) {
|
||||
mBaseIntent = (Intent) parcel;
|
||||
mBaseIntent.setFlags(mBaseIntent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_PREFIX_URI_PERMISSION));
|
||||
} else {
|
||||
mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
|
||||
@@ -297,6 +297,11 @@ public class ApnEditor extends SettingsPreferenceFragment
|
||||
getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
fillUi();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +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.Fragment;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class AppHeader {
|
||||
|
||||
public static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
|
||||
// constant value that can be used to check return code from sub activity.
|
||||
private static final int INSTALLED_APP_DETAILS = 1;
|
||||
|
||||
public static boolean includeAppInfo(final Fragment fragment) {
|
||||
Bundle args = fragment.getArguments();
|
||||
boolean showInfo = true;
|
||||
if (args != null && args.getBoolean(EXTRA_HIDE_INFO_BUTTON, false)) {
|
||||
showInfo = false;
|
||||
}
|
||||
Intent intent = fragment.getActivity().getIntent();
|
||||
if (intent != null && intent.getBooleanExtra(EXTRA_HIDE_INFO_BUTTON, false)) {
|
||||
showInfo = false;
|
||||
}
|
||||
return showInfo;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.datetime.AutoTimePreferenceController;
|
||||
@@ -36,6 +35,7 @@ import com.android.settings.datetime.TimePreferenceController;
|
||||
import com.android.settings.datetime.TimeZonePreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.datetime.ZoneGetter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -72,8 +72,8 @@ public class DateTimeSettings extends DashboardFragment implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
final Activity activity = getActivity();
|
||||
final Intent intent = activity.getIntent();
|
||||
final boolean isFromSUW = intent.getBooleanExtra(EXTRA_IS_FROM_SUW, false);
|
||||
|
||||
@@ -36,7 +36,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -60,12 +59,11 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.users.UserDialogs;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -353,23 +351,13 @@ public class DeviceAdminAdd extends Activity {
|
||||
restrictedAction.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (!mActionButton.isEnabled()) {
|
||||
showPolicyTransparencyDialogIfRequired();
|
||||
return;
|
||||
}
|
||||
if (mAdding) {
|
||||
addAndFinish();
|
||||
} else if (isManagedProfile(mDeviceAdmin)
|
||||
&& mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
|
||||
if (hasBaseCantRemoveProfileRestriction()) {
|
||||
// If DISALLOW_REMOVE_MANAGED_PROFILE is set by the system, there's no
|
||||
// point showing a dialog saying it's disabled by an admin.
|
||||
return;
|
||||
}
|
||||
EnforcedAdmin enforcedAdmin = getAdminEnforcingCantRemoveProfile();
|
||||
if (enforcedAdmin != null) {
|
||||
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(DeviceAdminAdd.this,
|
||||
enforcedAdmin);
|
||||
return;
|
||||
}
|
||||
final int userId = UserHandle.myUserId();
|
||||
UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@@ -380,7 +368,7 @@ public class DeviceAdminAdd extends Activity {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
).show();
|
||||
).show();
|
||||
} else if (mUninstalling) {
|
||||
mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
|
||||
finish();
|
||||
@@ -414,6 +402,26 @@ public class DeviceAdminAdd extends Activity {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a dialog to explain why the button is disabled if required.
|
||||
*/
|
||||
private void showPolicyTransparencyDialogIfRequired() {
|
||||
if (isManagedProfile(mDeviceAdmin)
|
||||
&& mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
|
||||
if (hasBaseCantRemoveProfileRestriction()) {
|
||||
// If DISALLOW_REMOVE_MANAGED_PROFILE is set by the system, there's no
|
||||
// point showing a dialog saying it's disabled by an admin.
|
||||
return;
|
||||
}
|
||||
EnforcedAdmin enforcedAdmin = getAdminEnforcingCantRemoveProfile();
|
||||
if (enforcedAdmin != null) {
|
||||
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
|
||||
DeviceAdminAdd.this,
|
||||
enforcedAdmin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addAndFinish() {
|
||||
try {
|
||||
logSpecialPermissionChange(true, mDeviceAdmin.getComponent().getPackageName());
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.content.Intent;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.deviceinfo.AdditionalSystemUpdatePreferenceController;
|
||||
@@ -41,6 +40,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.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -84,7 +84,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getActivity(), this /* fragment */,
|
||||
getLifecycle());
|
||||
}
|
||||
@@ -114,9 +114,9 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
||||
}
|
||||
};
|
||||
|
||||
private static List<PreferenceController> buildPreferenceControllers(Context context,
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Activity activity, Fragment fragment, Lifecycle lifecycle) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(
|
||||
new BuildNumberPreferenceController(context, activity, fragment, lifecycle));
|
||||
controllers.add(new AdditionalSystemUpdatePreferenceController(context));
|
||||
@@ -149,7 +149,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, null /*activity */,
|
||||
null /* fragment */, null /* lifecycle */);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ 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.dashboard.DashboardFragment;
|
||||
import com.android.settings.display.AmbientDisplayPreferenceController;
|
||||
import com.android.settings.display.AutoBrightnessPreferenceController;
|
||||
@@ -41,6 +40,7 @@ import com.android.settings.display.VrDisplayPreferenceController;
|
||||
import com.android.settings.display.WallpaperPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -77,7 +77,7 @@ public class DisplaySettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getLifecycle());
|
||||
}
|
||||
|
||||
@@ -86,9 +86,9 @@ public class DisplaySettings extends DashboardFragment {
|
||||
return R.string.help_uri_display;
|
||||
}
|
||||
|
||||
private static List<PreferenceController> buildPreferenceControllers(
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(
|
||||
Context context, Lifecycle lifecycle) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new AutoBrightnessPreferenceController(context, KEY_AUTO_BRIGHTNESS));
|
||||
controllers.add(new AutoRotatePreferenceController(context, lifecycle));
|
||||
controllers.add(new CameraGesturePreferenceController(context));
|
||||
@@ -134,7 +134,7 @@ public class DisplaySettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,8 +19,8 @@ import android.content.res.TypedArray;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
@Deprecated
|
||||
public class DividerPreference extends Preference {
|
||||
|
||||
private Boolean mAllowAbove;
|
||||
@@ -35,10 +35,11 @@ public class DividerPreference extends Preference {
|
||||
if (a.hasValue(R.styleable.DividerPreference_allowDividerBelow)) {
|
||||
mAllowBelow = a.getBoolean(R.styleable.DividerPreference_allowDividerBelow, false);
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public DividerPreference(Context context) {
|
||||
this(context, null);
|
||||
this(context, null /* attrs */);
|
||||
}
|
||||
|
||||
public void setDividerAllowedAbove(boolean allowed) {
|
||||
|
||||
@@ -33,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);
|
||||
}
|
||||
@@ -43,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;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.HelpUtils;
|
||||
@@ -34,6 +35,11 @@ public class HelpTrampoline extends Activity {
|
||||
|
||||
try {
|
||||
final String name = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
finishAndRemoveTask();
|
||||
return;
|
||||
}
|
||||
|
||||
final int id = getResources().getIdentifier(name, "string", getPackageName());
|
||||
final String value = getResources().getString(id);
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class IconPreferenceScreen extends Preference {
|
||||
|
||||
private Drawable mIcon;
|
||||
|
||||
// Whether or not the text and icon should be highlighted (as selected)
|
||||
private boolean mHighlight;
|
||||
|
||||
public IconPreferenceScreen(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public IconPreferenceScreen(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setLayoutResource(R.layout.preference_icon);
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.IconPreferenceScreen, defStyle, 0);
|
||||
mIcon = a.getDrawable(R.styleable.IconPreferenceScreen_icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
ImageView imageView = (ImageView) view.findViewById(R.id.icon);
|
||||
if (imageView != null && mIcon != null) {
|
||||
imageView.setImageDrawable(mIcon);
|
||||
}
|
||||
TextView textView = (TextView) view.findViewById(android.R.id.title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the icon for this Preference with a Drawable.
|
||||
*
|
||||
* @param icon The icon for this Preference
|
||||
*/
|
||||
public void setIcon(Drawable icon) {
|
||||
if ((icon == null && mIcon != null) || (icon != null && !icon.equals(mIcon))) {
|
||||
mIcon = icon;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon of this Preference.
|
||||
*
|
||||
* @return The icon.
|
||||
* @see #setIcon(Drawable)
|
||||
*/
|
||||
public Drawable getIcon() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
public void setHighlighted(boolean highlight) {
|
||||
mHighlight = highlight;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MultiLinePreference extends Preference {
|
||||
|
||||
public MultiLinePreference(Context ctx, AttributeSet attrs, int defStyle) {
|
||||
super(ctx, attrs, defStyle);
|
||||
}
|
||||
|
||||
public MultiLinePreference(Context ctx, AttributeSet attrs) {
|
||||
super(ctx, attrs);
|
||||
}
|
||||
|
||||
public MultiLinePreference(Context ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
TextView textView = (TextView) view.findViewById(android.R.id.title);
|
||||
if (textView != null) {
|
||||
textView.setSingleLine(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,6 +173,7 @@ public class RadioInfo extends Activity {
|
||||
|
||||
private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
|
||||
private TextView number;
|
||||
private TextView mSubscriberId;
|
||||
private TextView callState;
|
||||
private TextView operatorName;
|
||||
private TextView roamingState;
|
||||
@@ -371,8 +372,9 @@ public class RadioInfo extends Activity {
|
||||
mImsManager = ImsManager.getInstance(getApplicationContext(),
|
||||
SubscriptionManager.getDefaultVoicePhoneId());
|
||||
|
||||
mDeviceId= (TextView) findViewById(R.id.imei);
|
||||
mDeviceId = (TextView) findViewById(R.id.imei);
|
||||
number = (TextView) findViewById(R.id.number);
|
||||
mSubscriberId = (TextView) findViewById(R.id.imsi);
|
||||
callState = (TextView) findViewById(R.id.call);
|
||||
operatorName = (TextView) findViewById(R.id.operator);
|
||||
roamingState = (TextView) findViewById(R.id.roaming);
|
||||
@@ -896,6 +898,10 @@ public class RadioInfo extends Activity {
|
||||
if (s == null) s = r.getString(R.string.radioInfo_unknown);
|
||||
mDeviceId.setText(s);
|
||||
|
||||
s = phone.getSubscriberId();
|
||||
if (s == null) s = r.getString(R.string.radioInfo_unknown);
|
||||
mSubscriberId.setText(s);
|
||||
|
||||
//FIXME: Replace with a TelephonyManager call
|
||||
s = phone.getLine1Number();
|
||||
if (s == null) s = r.getString(R.string.radioInfo_unknown);
|
||||
|
||||
@@ -359,6 +359,15 @@ public class SecuritySettings extends SettingsPreferenceFragment
|
||||
getResources().getString(R.string.switch_on_text));
|
||||
}
|
||||
|
||||
// Encryption status of device
|
||||
if (LockPatternUtils.isDeviceEncryptionEnabled()) {
|
||||
root.findPreference(KEY_ENCRYPTION_AND_CREDENTIALS).setSummary(
|
||||
R.string.encryption_and_credential_settings_summary);
|
||||
} else {
|
||||
root.findPreference(KEY_ENCRYPTION_AND_CREDENTIALS).setSummary(
|
||||
R.string.summary_placeholder);
|
||||
}
|
||||
|
||||
// Show password
|
||||
mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD);
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.os.Bundle;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -53,6 +52,7 @@ public class Settings extends SettingsActivity {
|
||||
public static class UserDictionarySettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DisplaySettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NightDisplaySuggestionActivity extends NightDisplaySettingsActivity { /* empty */ }
|
||||
public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
|
||||
@@ -66,7 +66,7 @@ public class Settings extends SettingsActivity {
|
||||
return true;
|
||||
}
|
||||
return super.isValidFragment(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
|
||||
public static class StorageUseActivity extends SettingsActivity { /* empty */ }
|
||||
@@ -88,7 +88,9 @@ public class Settings extends SettingsActivity {
|
||||
public static class AccountSyncSettingsInAddAccountActivity extends SettingsActivity { /* empty */ }
|
||||
public static class CryptKeeperSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DeviceAdminSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DataPlanUsageSummaryActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DataUsageSummaryActivity extends SettingsActivity { /* empty */ }
|
||||
public static class MobileDataUsageListActivity extends SettingsActivity { /* empty */ }
|
||||
public static class ConfigureWifiSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class SavedAccessPointsSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class TextToSpeechSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
@@ -97,6 +99,7 @@ public class Settings extends SettingsActivity {
|
||||
public static class DreamSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NotificationStationActivity extends SettingsActivity { /* empty */ }
|
||||
public static class UserSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class SpecialAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class NotificationAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class VrListenersSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
@@ -124,6 +127,9 @@ public class Settings extends SettingsActivity {
|
||||
public static class AutomaticStorageManagerSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class GamesStorageActivity extends SettingsActivity { /* empty */ }
|
||||
public static class MoviesStorageActivity extends SettingsActivity { /* empty */ }
|
||||
public static class PhotosStorageActivity extends SettingsActivity {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
|
||||
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
@@ -45,13 +44,11 @@ import android.support.v7.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.transition.TransitionManager;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
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;
|
||||
import com.android.settings.backup.BackupSettingsActivity;
|
||||
@@ -62,14 +59,11 @@ import com.android.settings.dashboard.DashboardFeatureProvider;
|
||||
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.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;
|
||||
import com.android.settingslib.drawer.SettingsDrawerActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -81,8 +75,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
|
||||
private static final String LOG_TAG = "Settings";
|
||||
|
||||
public static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
|
||||
|
||||
// Constants for state save/restore
|
||||
private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
|
||||
@VisibleForTesting
|
||||
@@ -188,8 +180,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
}
|
||||
};
|
||||
|
||||
private DynamicIndexableContentMonitor mDynamicIndexableContentMonitor;
|
||||
|
||||
private SwitchBar mSwitchBar;
|
||||
|
||||
private Button mNextButton;
|
||||
@@ -540,10 +530,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
mDevelopmentPreferencesListener);
|
||||
|
||||
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (mDynamicIndexableContentMonitor == null) {
|
||||
mDynamicIndexableContentMonitor = new DynamicIndexableContentMonitor();
|
||||
}
|
||||
mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
|
||||
|
||||
updateTilesList();
|
||||
}
|
||||
@@ -555,9 +541,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
mDevelopmentPreferencesListener);
|
||||
mDevelopmentPreferencesListener = null;
|
||||
unregisterReceiver(mBatteryInfoReceiver);
|
||||
if (mDynamicIndexableContentMonitor != null) {
|
||||
mDynamicIndexableContentMonitor.unregister(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -770,68 +753,97 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
PackageManager pm = getPackageManager();
|
||||
final UserManager um = UserManager.get(this);
|
||||
final boolean isAdmin = um.isAdminUser();
|
||||
|
||||
boolean somethingChanged = false;
|
||||
String packageName = getPackageName();
|
||||
setTileEnabled(new ComponentName(packageName, WifiSettingsActivity.class.getName()),
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin);
|
||||
somethingChanged = setTileEnabled(
|
||||
new ComponentName(packageName, WifiSettingsActivity.class.getName()),
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin) || somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.BluetoothSettingsActivity.class.getName()),
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin);
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
Settings.DataUsageSummaryActivity.class.getName()),
|
||||
Utils.isBandwidthControlEnabled(), isAdmin);
|
||||
boolean isDataPlanFeatureEnabled = FeatureFactory.getFactory(this)
|
||||
.getDataPlanFeatureProvider()
|
||||
.isEnabled();
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
// When the data plan feature flag is turned on we disable DataUsageSummaryActivity
|
||||
// and enable DataPlanUsageSummaryActivity. When the feature flag is turned off we do the
|
||||
// reverse.
|
||||
|
||||
// Disable DataUsageSummaryActivity if the data plan feature flag is turned on otherwise
|
||||
// disable DataPlanUsageSummaryActivity.
|
||||
somethingChanged = setTileEnabled(
|
||||
new ComponentName(packageName,
|
||||
isDataPlanFeatureEnabled
|
||||
? Settings.DataUsageSummaryActivity.class.getName()
|
||||
: Settings.DataPlanUsageSummaryActivity.class.getName()),
|
||||
false /* enabled */,
|
||||
isAdmin) || somethingChanged;
|
||||
|
||||
// Enable DataUsageSummaryActivity if the data plan feature flag is turned on otherwise
|
||||
// enable DataPlanUsageSummaryActivity.
|
||||
somethingChanged = setTileEnabled(
|
||||
new ComponentName(packageName,
|
||||
isDataPlanFeatureEnabled
|
||||
? Settings.DataPlanUsageSummaryActivity.class.getName()
|
||||
: Settings.DataUsageSummaryActivity.class.getName()),
|
||||
Utils.isBandwidthControlEnabled() /* enabled */,
|
||||
isAdmin) || somethingChanged;
|
||||
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.SimSettingsActivity.class.getName()),
|
||||
Utils.showSimCardTile(this), isAdmin);
|
||||
Utils.showSimCardTile(this), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.PowerUsageSummaryActivity.class.getName()),
|
||||
mBatteryPresent, isAdmin);
|
||||
mBatteryPresent, isAdmin) || somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.UserSettingsActivity.class.getName()),
|
||||
UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
|
||||
&& !Utils.isMonkeyRunning(), isAdmin);
|
||||
&& !Utils.isMonkeyRunning(), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.NetworkDashboardActivity.class.getName()),
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin);
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.ConnectedDeviceDashboardActivity.class.getName()),
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin);
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.DateTimeSettingsActivity.class.getName()),
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin);
|
||||
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
Settings.PaymentSettingsActivity.class.getName()),
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_NFC)
|
||||
&& pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
|
||||
&& adapter != null && adapter.isEnabled(), isAdmin);
|
||||
!UserManager.isDeviceInDemoMode(this), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.PrintSettingsActivity.class.getName()),
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin);
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
final boolean showDev = mDevelopmentPreferences.getBoolean(
|
||||
DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng"))
|
||||
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.DevelopmentSettingsActivity.class.getName()),
|
||||
showDev, isAdmin);
|
||||
showDev, isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
// Enable/disable backup settings depending on whether the user is admin.
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
BackupSettingsActivity.class.getName()), true, isAdmin);
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
BackupSettingsActivity.class.getName()), true, isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
setTileEnabled(new ComponentName(packageName,
|
||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||
Settings.WifiDisplaySettingsActivity.class.getName()),
|
||||
WifiDisplaySettings.isAvailable(this), isAdmin);
|
||||
WifiDisplaySettings.isAvailable(this), isAdmin)
|
||||
|| somethingChanged;
|
||||
|
||||
if (UserHandle.MU_ENABLED && !isAdmin) {
|
||||
|
||||
@@ -848,7 +860,8 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
SettingsGateway.SETTINGS_FOR_RESTRICTED, name);
|
||||
if (packageName.equals(component.getPackageName())
|
||||
&& !isEnabledForRestricted) {
|
||||
setTileEnabled(component, false, isAdmin);
|
||||
somethingChanged = setTileEnabled(component, false, isAdmin)
|
||||
|| somethingChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -856,16 +869,24 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
}
|
||||
|
||||
// Final step, refresh categories.
|
||||
updateCategories();
|
||||
if (somethingChanged) {
|
||||
Log.d(LOG_TAG, "Enabled state changed for some tiles, reloading all categories");
|
||||
updateCategories();
|
||||
} else {
|
||||
Log.d(LOG_TAG, "No enabled state changed, skipping updateCategory call");
|
||||
}
|
||||
}
|
||||
|
||||
private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin) {
|
||||
/**
|
||||
* @return whether or not the enabled state actually changed.
|
||||
*/
|
||||
private boolean setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin) {
|
||||
if (UserHandle.MU_ENABLED && !isAdmin && getPackageName().equals(component.getPackageName())
|
||||
&& !ArrayUtils.contains(SettingsGateway.SETTINGS_FOR_RESTRICTED,
|
||||
component.getClassName())) {
|
||||
enabled = false;
|
||||
}
|
||||
setTileEnabled(component, enabled);
|
||||
return setTileEnabled(component, enabled);
|
||||
}
|
||||
|
||||
private void getMetaData() {
|
||||
|
||||
@@ -49,6 +49,7 @@ 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.LoadingViewController;
|
||||
import com.android.settingslib.CustomDialogPreference;
|
||||
import com.android.settingslib.CustomEditTextPreference;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
@@ -240,14 +241,11 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
|
||||
unregisterObserverIfNeeded();
|
||||
}
|
||||
|
||||
public void showLoadingWhenEmpty() {
|
||||
View loading = getView().findViewById(R.id.loading_container);
|
||||
setEmptyView(loading);
|
||||
}
|
||||
|
||||
public void setLoading(boolean loading, boolean animate) {
|
||||
View loading_container = getView().findViewById(R.id.loading_container);
|
||||
Utils.handleLoadingContainer(loading_container, getListView(), !loading, animate);
|
||||
View loadingContainer = getView().findViewById(R.id.loading_container);
|
||||
LoadingViewController.handleLoadingContainer(loadingContainer, getListView(),
|
||||
!loading /* done */,
|
||||
animate);
|
||||
}
|
||||
|
||||
public void registerObserverIfNeeded() {
|
||||
|
||||
@@ -43,6 +43,8 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.datausage.DataSaverBackend;
|
||||
import com.android.settings.wifi.WifiApDialog;
|
||||
import com.android.settings.wifi.WifiApEnabler;
|
||||
import com.android.settings.wifi.tether.WifiTetherPreferenceController;
|
||||
import com.android.settings.wifi.tether.WifiTetherSettings;
|
||||
import com.android.settingslib.TetherUtil;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -63,7 +65,6 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
private static final String USB_TETHER_SETTINGS = "usb_tether_settings";
|
||||
private static final String ENABLE_WIFI_AP = "enable_wifi_ap";
|
||||
private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering";
|
||||
private static final String TETHER_CHOICE = "TETHER_TYPE";
|
||||
private static final String DATA_SAVER_FOOTER = "disabled_on_data_saver";
|
||||
|
||||
private static final int DIALOG_AP_SETTINGS = 1;
|
||||
@@ -100,17 +101,14 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
private WifiConfiguration mWifiConfig = null;
|
||||
private ConnectivityManager mCm;
|
||||
|
||||
private WifiTetherPreferenceController mWifiTetherPreferenceController;
|
||||
|
||||
private boolean mRestartWifiApAfterConfigChange;
|
||||
|
||||
private boolean mUsbConnected;
|
||||
private boolean mMassStorageActive;
|
||||
|
||||
private boolean mBluetoothEnableForTether;
|
||||
|
||||
/* Stores the package name and the class name of the provisioning app */
|
||||
private String[] mProvisionApp;
|
||||
private static final int PROVISION_REQUEST = 0;
|
||||
|
||||
private boolean mUnavailable;
|
||||
|
||||
private DataSaverBackend mDataSaverBackend;
|
||||
@@ -126,6 +124,13 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
super(UserManager.DISALLOW_CONFIG_TETHERING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mWifiTetherPreferenceController =
|
||||
new WifiTetherPreferenceController(context, getLifecycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
@@ -154,6 +159,7 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
|
||||
mEnableWifiAp =
|
||||
(SwitchPreference) findPreference(ENABLE_WIFI_AP);
|
||||
|
||||
Preference wifiApSettings = findPreference(WIFI_AP_SSID_AND_SECURITY);
|
||||
mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS);
|
||||
mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
|
||||
@@ -175,12 +181,18 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
getPreferenceScreen().removePreference(mUsbTether);
|
||||
}
|
||||
|
||||
if (wifiAvailable && !Utils.isMonkeyRunning()) {
|
||||
mWifiApEnabler = new WifiApEnabler(activity, mDataSaverBackend, mEnableWifiAp);
|
||||
initWifiTethering();
|
||||
mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
|
||||
if (WifiTetherSettings.isTetherSettingPageEnabled()) {
|
||||
removePreference(ENABLE_WIFI_AP);
|
||||
removePreference(WIFI_AP_SSID_AND_SECURITY);
|
||||
} else {
|
||||
getPreferenceScreen().removePreference(mEnableWifiAp);
|
||||
getPreferenceScreen().removePreference(wifiApSettings);
|
||||
if (wifiAvailable && !Utils.isMonkeyRunning()) {
|
||||
mWifiApEnabler = new WifiApEnabler(activity, mDataSaverBackend, mEnableWifiAp);
|
||||
initWifiTethering();
|
||||
} else {
|
||||
getPreferenceScreen().removePreference(mEnableWifiAp);
|
||||
getPreferenceScreen().removePreference(wifiApSettings);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bluetoothAvailable) {
|
||||
|
||||
@@ -51,6 +51,9 @@ import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.icu.text.MeasureFormat;
|
||||
import android.icu.util.Measure;
|
||||
import android.icu.util.MeasureUnit;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
@@ -104,6 +107,7 @@ import com.android.internal.app.UnlaunchableAppActivity;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.UserIcons;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
|
||||
import com.android.settings.password.FingerprintManagerWrapper;
|
||||
import com.android.settings.password.IFingerprintManager;
|
||||
|
||||
@@ -821,33 +825,36 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
minutes = seconds / SECONDS_PER_MINUTE;
|
||||
seconds -= minutes * SECONDS_PER_MINUTE;
|
||||
}
|
||||
if (withSeconds) {
|
||||
if (days > 0) {
|
||||
sb.append(context.getString(R.string.battery_history_days,
|
||||
days, hours, minutes, seconds));
|
||||
} else if (hours > 0) {
|
||||
sb.append(context.getString(R.string.battery_history_hours,
|
||||
hours, minutes, seconds));
|
||||
} else if (minutes > 0) {
|
||||
sb.append(context.getString(R.string.battery_history_minutes, minutes, seconds));
|
||||
} else {
|
||||
sb.append(context.getString(R.string.battery_history_seconds, seconds));
|
||||
}
|
||||
} else {
|
||||
if (days > 0) {
|
||||
sb.append(context.getString(R.string.battery_history_days_no_seconds,
|
||||
days, hours, minutes));
|
||||
} else if (hours > 0) {
|
||||
sb.append(context.getString(R.string.battery_history_hours_no_seconds,
|
||||
hours, minutes));
|
||||
} else {
|
||||
sb.append(context.getString(R.string.battery_history_minutes_no_seconds, minutes));
|
||||
|
||||
// Add ttsSpan if it only have minute value, because it will be read as "meters"
|
||||
TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
|
||||
.setUnit("minute").build();
|
||||
sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
final ArrayList<Measure> measureList = new ArrayList(4);
|
||||
if (days > 0) {
|
||||
measureList.add(new Measure(days, MeasureUnit.DAY));
|
||||
}
|
||||
if (hours > 0) {
|
||||
measureList.add(new Measure(hours, MeasureUnit.HOUR));
|
||||
}
|
||||
if (minutes > 0) {
|
||||
measureList.add(new Measure(minutes, MeasureUnit.MINUTE));
|
||||
}
|
||||
if (withSeconds && seconds > 0) {
|
||||
measureList.add(new Measure(seconds, MeasureUnit.SECOND));
|
||||
}
|
||||
if (measureList.size() == 0) {
|
||||
// Everything addable was zero, so nothing was added. We add a zero.
|
||||
measureList.add(new Measure(0, withSeconds ? MeasureUnit.SECOND : MeasureUnit.MINUTE));
|
||||
}
|
||||
final Measure[] measureArray = measureList.toArray(new Measure[measureList.size()]);
|
||||
|
||||
final Locale locale = context.getResources().getConfiguration().locale;
|
||||
final MeasureFormat measureFormat = MeasureFormat.getInstance(
|
||||
locale, MeasureFormat.FormatWidth.NARROW);
|
||||
sb.append(measureFormat.formatMeasures(measureArray));
|
||||
|
||||
if (measureArray.length == 1 && MeasureUnit.MINUTE.equals(measureArray[0].getUnit())) {
|
||||
// Add ttsSpan if it only have minute value, because it will be read as "meters"
|
||||
final TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
|
||||
.setUnit("minute").build();
|
||||
sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
return sb;
|
||||
@@ -943,43 +950,6 @@ 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);
|
||||
setViewShown(doneLoading, done, animate);
|
||||
}
|
||||
|
||||
private static void setViewShown(final View view, boolean shown, boolean animate) {
|
||||
if (animate) {
|
||||
Animation animation = AnimationUtils.loadAnimation(view.getContext(),
|
||||
shown ? android.R.anim.fade_in : android.R.anim.fade_out);
|
||||
if (shown) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
animation.setAnimationListener(new AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
view.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
view.startAnimation(animation);
|
||||
} else {
|
||||
view.clearAnimation();
|
||||
view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application info of the currently installed MDM package.
|
||||
*/
|
||||
@@ -1310,6 +1280,28 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
return isVolumeValid(volume) ? volume : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the supplied package is device owner or profile owner of at
|
||||
* least one user.
|
||||
* @param userManager used to get profile owner app for each user
|
||||
* @param devicePolicyManager used to check whether it is device owner app
|
||||
* @param packageName package to check about
|
||||
*/
|
||||
public static boolean isProfileOrDeviceOwner(UserManager userManager,
|
||||
DevicePolicyManagerWrapper devicePolicyManager, String packageName) {
|
||||
List<UserInfo> userInfos = userManager.getUsers();
|
||||
if (devicePolicyManager.isDeviceOwnerAppOnAnyUser(packageName)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0, size = userInfos.size(); i < size; i++) {
|
||||
ComponentName cn = devicePolicyManager.getProfileOwnerAsUser(userInfos.get(i).id);
|
||||
if (cn != null && cn.getPackageName().equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resource id to represent the install status for an app
|
||||
*/
|
||||
@@ -1321,20 +1313,6 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
return info.enabled ? R.string.installed : R.string.disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control if other apps can display overlays. By default this is allowed. Be sure to
|
||||
* re-enable overlays, as the effect is system-wide.
|
||||
*/
|
||||
public static void setOverlayAllowed(Context context, IBinder token, boolean allowed) {
|
||||
AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
|
||||
if (appOpsManager != null) {
|
||||
appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
||||
!allowed, token);
|
||||
appOpsManager.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW,
|
||||
!allowed, token);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isVolumeValid(VolumeInfo volume) {
|
||||
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
|
||||
&& volume.isMountedReadable();
|
||||
|
||||
@@ -27,6 +27,8 @@ import android.text.BidiFormatter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -37,6 +39,8 @@ import com.android.settings.R;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
||||
|
||||
/**
|
||||
* Utility class for creating the dialog that asks users for explicit permission to grant
|
||||
* all of the requested capabilities to an accessibility service before the service is enabled
|
||||
@@ -65,6 +69,10 @@ public class AccessibilityServiceWarning {
|
||||
return false;
|
||||
};
|
||||
|
||||
Window window = ad.getWindow();
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.privateFlags |= PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
||||
window.setAttributes(params);
|
||||
ad.create();
|
||||
ad.getButton(AlertDialog.BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);
|
||||
ad.setCanceledOnTouchOutside(true);
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -52,7 +51,6 @@ import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
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.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
@@ -493,7 +491,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
getString(R.string.accessibility_summary_state_disabled);
|
||||
final CharSequence serviceSummary = info.loadSummary(getPackageManager());
|
||||
final String stateSummaryCombo = getString(
|
||||
R.string.accessibility_summary_default_combination,
|
||||
R.string.preference_summary_default_combination,
|
||||
serviceState, serviceSummary);
|
||||
preference.setSummary((TextUtils.isEmpty(serviceSummary)) ? serviceState
|
||||
: stateSummaryCombo);
|
||||
@@ -727,40 +725,6 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
|
||||
List<SearchIndexableRaw> indexables = new ArrayList<>();
|
||||
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
AccessibilityManager accessibilityManager =
|
||||
context.getSystemService(AccessibilityManager.class);
|
||||
|
||||
String screenTitle = context.getResources().getString(
|
||||
R.string.accessibility_settings);
|
||||
|
||||
// Indexing all services, regardless if enabled.
|
||||
List<AccessibilityServiceInfo> services = accessibilityManager
|
||||
.getInstalledAccessibilityServiceList();
|
||||
final int serviceCount = services.size();
|
||||
for (int i = 0; i < serviceCount; i++) {
|
||||
AccessibilityServiceInfo service = services.get(i);
|
||||
if (service == null || service.getResolveInfo() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
|
||||
ComponentName componentName = new ComponentName(serviceInfo.packageName,
|
||||
serviceInfo.name);
|
||||
|
||||
SearchIndexableRaw indexable = new SearchIndexableRaw(context);
|
||||
indexable.key = componentName.flattenToString();
|
||||
indexable.title = service.getResolveInfo().loadLabel(packageManager).toString();
|
||||
indexable.screenTitle = screenTitle;
|
||||
indexables.add(indexable);
|
||||
}
|
||||
|
||||
return indexables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
|
||||
@@ -83,34 +83,43 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
|
||||
protected void onInstallSwitchBarToggleSwitch() {
|
||||
super.onInstallSwitchBarToggleSwitch();
|
||||
mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> {
|
||||
onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled);
|
||||
Context context = getContext();
|
||||
if (enabled && (getServiceInfo(context) == null)) {
|
||||
// If no service is configured, we'll disable the shortcut shortly. Give the
|
||||
// user a chance to select a service. We'll update the preferences when we resume.
|
||||
Settings.Secure.putInt(
|
||||
getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1);
|
||||
mServicePreference.setEnabled(true);
|
||||
mServicePreference.performClick();
|
||||
} else {
|
||||
onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
|
||||
Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
|
||||
updatePreferences();
|
||||
}
|
||||
|
||||
private void updatePreferences() {
|
||||
ContentResolver cr = getContentResolver();
|
||||
Context context = getContext();
|
||||
mServicePreference.setSummary(getServiceName(context));
|
||||
if (getServiceInfo(context) == null) {
|
||||
// If no service is configured, make sure the overall shortcut is turned off
|
||||
Settings.Secure.putInt(
|
||||
getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0);
|
||||
}
|
||||
boolean isEnabled = Settings.Secure
|
||||
.getInt(cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1) == 1;
|
||||
mToggleSwitch.setChecked(isEnabled);
|
||||
CharSequence serviceName = getServiceName(getContext());
|
||||
mServicePreference.setSummary(serviceName);
|
||||
mSwitchBar.setChecked(isEnabled);
|
||||
mOnLockScreenSwitchPreference.setChecked(Settings.Secure.getInt(
|
||||
cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 0) == 1);
|
||||
if (TextUtils.equals(serviceName, getString(R.string.accessibility_no_service_selected))) {
|
||||
// If there's no service configured, enabling the shortcut will have no effect
|
||||
// It should already be disabled, but force the switch to off just in case
|
||||
mToggleSwitch.setChecked(false);
|
||||
mToggleSwitch.setEnabled(false);
|
||||
mSwitchBar.setEnabled(false);
|
||||
} else {
|
||||
mToggleSwitch.setEnabled(true);
|
||||
mSwitchBar.setEnabled(true);
|
||||
}
|
||||
// Only enable changing the service and lock screen behavior if the shortcut is on
|
||||
mServicePreference.setEnabled(mToggleSwitch.isChecked());
|
||||
mOnLockScreenSwitchPreference.setEnabled(mToggleSwitch.isChecked());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,17 +129,21 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
|
||||
* @return The name of the service or a string saying that none is selected.
|
||||
*/
|
||||
public static CharSequence getServiceName(Context context) {
|
||||
ComponentName shortcutServiceName = ComponentName.unflattenFromString(
|
||||
AccessibilityUtils.getShortcutTargetServiceComponentNameString(
|
||||
context, UserHandle.myUserId()));
|
||||
AccessibilityServiceInfo shortcutServiceInfo = AccessibilityManager.getInstance(context)
|
||||
.getInstalledServiceInfoWithComponentName(shortcutServiceName);
|
||||
AccessibilityServiceInfo shortcutServiceInfo = getServiceInfo(context);
|
||||
if (shortcutServiceInfo != null) {
|
||||
return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager());
|
||||
}
|
||||
return context.getString(R.string.accessibility_no_service_selected);
|
||||
}
|
||||
|
||||
private static AccessibilityServiceInfo getServiceInfo(Context context) {
|
||||
ComponentName shortcutServiceName = ComponentName.unflattenFromString(
|
||||
AccessibilityUtils.getShortcutTargetServiceComponentNameString(
|
||||
context, UserHandle.myUserId()));
|
||||
return AccessibilityManager.getInstance(context)
|
||||
.getInstalledServiceInfoWithComponentName(shortcutServiceName);
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
// This fragment is for details of the shortcut. Only the shortcut itself needs
|
||||
|
||||
@@ -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;
|
||||
import android.app.Activity;
|
||||
@@ -146,22 +145,6 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
|
||||
return AccessibilityServiceWarning.createCapabilitiesDialog(getActivity(), info, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mToken != null) {
|
||||
setOverlayAllowed(getActivity(), mToken, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (mToken != null) {
|
||||
setOverlayAllowed(getActivity(), mToken, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
final Fragment fragment = getTargetFragment();
|
||||
|
||||
@@ -48,8 +48,6 @@ 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 {
|
||||
|
||||
@@ -72,8 +70,6 @@ public class ToggleAccessibilityServicePreferenceFragment
|
||||
|
||||
private int mShownDialogId;
|
||||
|
||||
private final IBinder mToken = new Binder();
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY_SERVICE;
|
||||
@@ -96,18 +92,12 @@ public class ToggleAccessibilityServicePreferenceFragment
|
||||
public void onResume() {
|
||||
mSettingsContentObserver.register(getContentResolver());
|
||||
updateSwitchBarToggleSwitch();
|
||||
if (mToken != null) {
|
||||
setOverlayAllowed(getActivity(), mToken, false);
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingsContentObserver.unregister(getContentResolver());
|
||||
if (mToken != null) {
|
||||
setOverlayAllowed(getActivity(), mToken, true);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import android.support.v7.preference.PreferenceScreen;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -39,6 +39,7 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "AccountDetailDashboard";
|
||||
private static final String METADATA_IA_ACCOUNT = "com.android.settings.ia.account";
|
||||
private static final String EXTRA_ACCOUNT_NAME = "extra.accountName";
|
||||
|
||||
public static final String KEY_ACCOUNT = "account";
|
||||
public static final String KEY_ACCOUNT_TYPE = "account_type";
|
||||
@@ -57,6 +58,7 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
getPreferenceManager().setPreferenceComparisonCallback(null);
|
||||
Bundle args = getArguments();
|
||||
final Activity activity = getActivity();
|
||||
UserHandle userHandle = Utils.getSecureTargetUser(activity.getActivityToken(),
|
||||
@@ -107,8 +109,8 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mAccountSynController = new AccountSyncPreferenceController(context);
|
||||
controllers.add(mAccountSynController);
|
||||
mRemoveAccountController = new RemoveAccountPreferenceController(context, this);
|
||||
@@ -127,7 +129,11 @@ public class AccountDetailDashboardFragment extends DashboardFragment {
|
||||
if (metadata == null) {
|
||||
return false;
|
||||
}
|
||||
return mAccountType.equals(metadata.getString(METADATA_IA_ACCOUNT));
|
||||
final boolean display = mAccountType.equals(metadata.getString(METADATA_IA_ACCOUNT));
|
||||
if (display && tile.intent != null) {
|
||||
tile.intent.putExtra(EXTRA_ACCOUNT_NAME, mAccount.name);
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -29,15 +29,16 @@ 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.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
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 {
|
||||
public class AccountHeaderPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnResume {
|
||||
|
||||
private static final String KEY_ACCOUNT_HEADER = "account_header";
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import static android.content.Intent.EXTRA_USER;
|
||||
import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
|
||||
import static android.os.UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
|
||||
import static android.provider.Settings.ACTION_ADD_ACCOUNT;
|
||||
import static android.provider.Settings.EXTRA_AUTHORITIES;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -45,13 +51,14 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settings.search.SearchFeatureProviderImpl;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
@@ -61,17 +68,11 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static android.content.Intent.EXTRA_USER;
|
||||
import static android.os.UserManager.DISALLOW_MODIFY_ACCOUNTS;
|
||||
import static android.os.UserManager.DISALLOW_REMOVE_MANAGED_PROFILE;
|
||||
import static android.provider.Settings.EXTRA_AUTHORITIES;
|
||||
|
||||
public class AccountPreferenceController extends PreferenceController
|
||||
implements AuthenticatorHelper.OnAccountsUpdateListener,
|
||||
public class AccountPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener,
|
||||
OnPreferenceClickListener, LifecycleObserver, OnPause, OnResume {
|
||||
|
||||
private static final String TAG = "AccountPrefController";
|
||||
private static final String ADD_ACCOUNT_ACTION = "android.settings.ADD_ACCOUNT_SETTINGS";
|
||||
|
||||
private static final int ORDER_ACCOUNT_PROFILES = 1;
|
||||
private static final int ORDER_LAST = 1002;
|
||||
@@ -232,7 +233,7 @@ public class AccountPreferenceController extends PreferenceController
|
||||
for (int i = 0; i < count; i++) {
|
||||
ProfileData profileData = mProfiles.valueAt(i);
|
||||
if (preference == profileData.addAccountPreference) {
|
||||
Intent intent = new Intent(ADD_ACCOUNT_ACTION);
|
||||
Intent intent = new Intent(ACTION_ADD_ACCOUNT);
|
||||
intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
|
||||
intent.putExtra(EXTRA_AUTHORITIES, mAuthorities);
|
||||
mContext.startActivity(intent);
|
||||
|
||||
@@ -31,11 +31,12 @@ 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.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class AccountSyncPreferenceController extends PreferenceController
|
||||
implements AuthenticatorHelper.OnAccountsUpdateListener {
|
||||
public class AccountSyncPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener {
|
||||
|
||||
private static final String TAG = "AccountSyncController";
|
||||
private static final String KEY_ACCOUNT_SYNC = "account_sync";
|
||||
@@ -97,6 +98,9 @@ public class AccountSyncPreferenceController extends PreferenceController
|
||||
|
||||
@VisibleForTesting
|
||||
void updateSummary(Preference preference) {
|
||||
if (mAccount == null) {
|
||||
return;
|
||||
}
|
||||
final int userId = mUserHandle.getIdentifier();
|
||||
final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
|
||||
int total = 0;
|
||||
|
||||
@@ -19,15 +19,17 @@ import android.content.Context;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.users.UserCapabilities;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
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 {
|
||||
public class AddUserWhenLockedPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnPause, OnResume {
|
||||
|
||||
private static final String KEY_ADD_USER_WHEN_LOCKED = "add_users_when_locked";
|
||||
|
||||
|
||||
@@ -32,10 +32,12 @@ import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class AutoSyncDataPreferenceController extends PreferenceController {
|
||||
public class AutoSyncDataPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "AutoSyncDataController";
|
||||
private static final String TAG_CONFIRM_AUTO_SYNC_CHANGE = "confirmAutoSyncChange";
|
||||
|
||||
@@ -23,15 +23,16 @@ import android.content.res.Resources;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EmergencyInfoPreferenceController extends PreferenceController {
|
||||
public class EmergencyInfoPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_EMERGENCY_INFO = "emergency_info";
|
||||
private static final String ACTION_EDIT_EMERGENCY_INFO = "android.settings.EDIT_EMERGENCY_INFO";
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.accounts.AccountManagerCallback;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
@@ -29,33 +30,46 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RemoveAccountPreferenceController extends PreferenceController
|
||||
implements OnClickListener {
|
||||
public class RemoveAccountPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, OnClickListener {
|
||||
|
||||
private static final String KEY_REMOVE_ACCOUNT = "remove_account";
|
||||
|
||||
private Account mAccount;
|
||||
private Fragment mParentFragment;
|
||||
private UserHandle mUserHandle;
|
||||
private DevicePolicyManagerWrapper mDpm;
|
||||
|
||||
public RemoveAccountPreferenceController(Context context, Fragment parent) {
|
||||
this(context, parent, new DevicePolicyManagerWrapperImpl(
|
||||
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE)));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
RemoveAccountPreferenceController(Context context, Fragment parent,
|
||||
DevicePolicyManagerWrapper dpm) {
|
||||
super(context);
|
||||
mParentFragment = parent;
|
||||
mDpm = dpm;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,6 +93,12 @@ public class RemoveAccountPreferenceController extends PreferenceController
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Intent intent = mDpm.createAdminSupportIntent(UserManager.DISALLOW_MODIFY_ACCOUNTS);
|
||||
if (intent != null) {
|
||||
// DISALLOW_MODIFY_ACCOUNTS is active, show admin support dialog
|
||||
mContext.startActivity(intent);
|
||||
return;
|
||||
}
|
||||
ConfirmRemoveAccountDialog.show(mParentFragment, mAccount, mUserHandle);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import static android.provider.Settings.EXTRA_AUTHORITIES;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
@@ -25,18 +27,16 @@ 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.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static android.provider.Settings.EXTRA_AUTHORITIES;
|
||||
|
||||
public class UserAndAccountDashboardFragment extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "UserAndAccountDashboard";
|
||||
@@ -63,8 +63,8 @@ public class UserAndAccountDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new EmergencyInfoPreferenceController(context));
|
||||
AddUserWhenLockedPreferenceController addUserWhenLockedPrefController =
|
||||
new AddUserWhenLockedPreferenceController(context);
|
||||
@@ -81,15 +81,6 @@ public class UserAndAccountDashboardFragment extends DashboardFragment {
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayTile(Tile tile) {
|
||||
final Bundle metadata = tile.metaData;
|
||||
if (metadata != null) {
|
||||
return metadata.getString(METADATA_IA_ACCOUNT) == null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class SummaryProvider implements SummaryLoader.SummaryProvider {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
@@ -24,10 +24,10 @@ import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.notification.EmergencyBroadcastPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -64,7 +64,7 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final Activity activity = getActivity();
|
||||
final Application app;
|
||||
if (activity != null) {
|
||||
@@ -75,9 +75,9 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
|
||||
return buildPreferenceControllers(context, app, this);
|
||||
}
|
||||
|
||||
private static List<PreferenceController> buildPreferenceControllers(Context context,
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Application app, Fragment host) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new EmergencyBroadcastPreferenceController(context,
|
||||
"app_and_notif_cell_broadcast_settings"));
|
||||
controllers.add(new SpecialAppAccessPreferenceController(context));
|
||||
@@ -97,7 +97,8 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null, null /* host */);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
|
||||
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
@@ -73,7 +75,7 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
|
||||
protected String mPackageName;
|
||||
|
||||
protected IUsbManager mUsbManager;
|
||||
protected DevicePolicyManager mDpm;
|
||||
protected DevicePolicyManagerWrapper mDpm;
|
||||
protected UserManager mUserManager;
|
||||
protected PackageManager mPm;
|
||||
|
||||
@@ -92,7 +94,8 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
|
||||
.getApplicationFeatureProvider(activity);
|
||||
mState = ApplicationsState.getInstance(activity.getApplication());
|
||||
mSession = mState.newSession(this);
|
||||
mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
mDpm = new DevicePolicyManagerWrapperImpl(
|
||||
(DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
|
||||
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
|
||||
mPm = activity.getPackageManager();
|
||||
IBinder b = ServiceManager.getService(Context.USB_SERVICE);
|
||||
|
||||
@@ -51,7 +51,8 @@ public abstract class AppInfoWithHeader extends AppInfoBase {
|
||||
.setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
|
||||
.setPackageName(mPackageName)
|
||||
.setUid(mPackageInfo.applicationInfo.uid)
|
||||
.setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
|
||||
.setHasAppInfoLink(true)
|
||||
.setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
|
||||
.done(activity, getPrefContext());
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AppPermissionsPreferenceController extends PreferenceController {
|
||||
public class AppPermissionsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "AppPermissionPrefCtrl";
|
||||
private static final String KEY_APP_PERMISSION_GROUPS = "manage_perms";
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.assist.DefaultAssistPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
|
||||
@@ -29,19 +30,20 @@ import com.android.settings.applications.defaultapps.DefaultPhonePreferenceContr
|
||||
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultWorkBrowserPreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultWorkPhonePreferenceController;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultPaymentSettingsPreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AdvancedAppSettings extends DashboardFragment {
|
||||
public class DefaultAppSettings extends DashboardFragment {
|
||||
|
||||
static final String TAG = "AdvancedAppSettings";
|
||||
static final String TAG = "DefaultAppSettings";
|
||||
|
||||
private static final String KEY_ASSIST_VOICE_INPUT = "assist_and_voice_input";
|
||||
|
||||
@@ -56,7 +58,7 @@ public class AdvancedAppSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
|
||||
@@ -65,8 +67,10 @@ public class AdvancedAppSettings extends DashboardFragment {
|
||||
return MetricsEvent.APPLICATIONS_ADVANCED;
|
||||
}
|
||||
|
||||
private static List<PreferenceController> buildPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new DefaultAssistPreferenceController(context, KEY_ASSIST_VOICE_INPUT,
|
||||
false /* showSetting */));
|
||||
controllers.add(new DefaultBrowserPreferenceController(context));
|
||||
controllers.add(new DefaultWorkBrowserPreferenceController(context));
|
||||
controllers.add(new DefaultPhonePreferenceController(context));
|
||||
@@ -74,6 +78,7 @@ public class AdvancedAppSettings extends DashboardFragment {
|
||||
controllers.add(new DefaultSmsPreferenceController(context));
|
||||
controllers.add(new DefaultEmergencyPreferenceController(context));
|
||||
controllers.add(new DefaultHomePreferenceController(context));
|
||||
controllers.add(new DefaultPaymentSettingsPreferenceController(context));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -100,7 +105,8 @@ public class AdvancedAppSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
}
|
||||
};
|
||||
@@ -152,7 +158,7 @@ public class AdvancedAppSettings extends DashboardFragment {
|
||||
@Override
|
||||
public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
|
||||
SummaryLoader summaryLoader) {
|
||||
return new AdvancedAppSettings.SummaryProvider(activity, summaryLoader);
|
||||
return new DefaultAppSettings.SummaryProvider(activity, summaryLoader);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -29,12 +29,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.util.Log;
|
||||
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
|
||||
import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
|
||||
import com.android.settings.core.TouchOverlayManager;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
|
||||
@@ -60,8 +61,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
|
||||
private Intent mSettingsIntent;
|
||||
private OverlayState mOverlayState;
|
||||
|
||||
private TouchOverlayManager mTouchOverlayManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -69,7 +68,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
|
||||
Context context = getActivity();
|
||||
mOverlayBridge = new AppStateOverlayBridge(context, mState, null);
|
||||
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
mTouchOverlayManager = new TouchOverlayManager(context);
|
||||
|
||||
// find preferences
|
||||
addPreferencesFromResource(R.xml.app_ops_permissions_details);
|
||||
@@ -92,17 +90,17 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
mTouchOverlayManager.setOverlayAllowed(false);
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getActivity().getWindow().addFlags(
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
mTouchOverlayManager.setOverlayAllowed(true);
|
||||
public void onPause() {
|
||||
getActivity().getWindow().clearFlags(
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,16 +151,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
|
||||
.getMetricsFeatureProvider().action(getContext(), logCategory, packageName);
|
||||
}
|
||||
|
||||
private boolean canDrawOverlay(String pkgName) {
|
||||
int result = mAppOpsManager.noteOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
|
||||
mPackageInfo.applicationInfo.uid, pkgName);
|
||||
if (result == AppOpsManager.MODE_ALLOWED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean refreshUi() {
|
||||
mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
|
||||
import android.Manifest.permission;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
@@ -55,6 +57,7 @@ import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.format.Formatter;
|
||||
@@ -69,7 +72,6 @@ import android.widget.Button;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.AppHeader;
|
||||
import com.android.settings.DeviceAdminAdd;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
@@ -83,7 +85,8 @@ import com.android.settings.applications.defaultapps.DefaultSmsPreferenceControl
|
||||
import com.android.settings.applications.instantapps.InstantAppButtonsController;
|
||||
import com.android.settings.datausage.AppDataUsage;
|
||||
import com.android.settings.datausage.DataUsageList;
|
||||
import com.android.settings.datausage.DataUsageSummary;
|
||||
import com.android.settings.datausage.DataUsageUtils;
|
||||
import com.android.settings.development.DevelopmentSettingsEnabler;
|
||||
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
|
||||
import com.android.settings.fuelgauge.BatteryEntry;
|
||||
import com.android.settings.fuelgauge.BatteryStatsHelperLoader;
|
||||
@@ -110,8 +113,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
|
||||
/**
|
||||
* Activity to display application information from Settings. This activity presents
|
||||
* extended information associated with a package like code, data, total size, permissions
|
||||
@@ -145,7 +146,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
private static final int DLG_FORCE_STOP = DLG_BASE + 1;
|
||||
private static final int DLG_DISABLE = DLG_BASE + 2;
|
||||
private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
|
||||
|
||||
private static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
|
||||
private static final String KEY_HEADER = "header_view";
|
||||
private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons";
|
||||
private static final String KEY_ACTION_BUTTONS = "action_buttons";
|
||||
@@ -177,7 +178,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
private Preference mMemoryPreference;
|
||||
private Preference mVersionPreference;
|
||||
private AppDomainsPreference mInstantAppDomainsPreference;
|
||||
|
||||
private DevelopmentSettingsEnabler mDevelopmentSettingsEnabler;
|
||||
private boolean mDisableAfterUninstall;
|
||||
|
||||
// Used for updating notification preference.
|
||||
@@ -273,7 +274,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
// We don't allow uninstalling DO/PO on *any* users, because if it's a system app,
|
||||
// "uninstall" is actually "downgrade to the system version + disable", and "downgrade"
|
||||
// will clear data on all users.
|
||||
if (isProfileOrDeviceOwner(mPackageInfo.packageName)) {
|
||||
if (Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mPackageInfo.packageName)) {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
@@ -348,23 +349,6 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/** Returns if the supplied package is device owner or profile owner of at least one user */
|
||||
private boolean isProfileOrDeviceOwner(String packageName) {
|
||||
List<UserInfo> userInfos = mUserManager.getUsers();
|
||||
DevicePolicyManager dpm = (DevicePolicyManager)
|
||||
getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
if (dpm.isDeviceOwnerAppOnAnyUser(packageName)) {
|
||||
return true;
|
||||
}
|
||||
for (UserInfo userInfo : userInfos) {
|
||||
ComponentName cn = dpm.getProfileOwnerAsUser(userInfo.id);
|
||||
if (cn != null && cn.getPackageName().equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
@@ -377,6 +361,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
addPreferencesFromResource(R.xml.installed_app_details);
|
||||
|
||||
addDynamicPrefs();
|
||||
if (Utils.isBandwidthControlEnabled()) {
|
||||
INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
||||
@@ -390,6 +375,8 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
removePreference(KEY_DATA);
|
||||
}
|
||||
mBatteryUtils = BatteryUtils.getInstance(getContext());
|
||||
mDevelopmentSettingsEnabler = new DevelopmentSettingsEnabler(
|
||||
activity, null /* lifecycle */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -413,7 +400,9 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
loaderManager.restartLoader(LOADER_STORAGE, Bundle.EMPTY, this);
|
||||
}
|
||||
restartBatteryStatsLoader();
|
||||
new MemoryUpdater().execute();
|
||||
if (mDevelopmentSettingsEnabler.getLastEnabledState()) {
|
||||
new MemoryUpdater().execute();
|
||||
}
|
||||
updateDynamicPrefs();
|
||||
}
|
||||
|
||||
@@ -445,6 +434,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header))
|
||||
.setRecyclerView(getListView(), getLifecycle())
|
||||
.setPackageName(mPackageName)
|
||||
.setHasAppInfoLink(false)
|
||||
.setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
|
||||
EntityHeaderController.ActionType.ACTION_NONE)
|
||||
.styleActionBar(activity)
|
||||
@@ -466,6 +456,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
mBatteryPreference.setOnPreferenceClickListener(this);
|
||||
mMemoryPreference = findPreference(KEY_MEMORY);
|
||||
mMemoryPreference.setOnPreferenceClickListener(this);
|
||||
mMemoryPreference.setVisible(mDevelopmentSettingsEnabler.getLastEnabledState());
|
||||
mVersionPreference = findPreference(KEY_VERSION);
|
||||
mInstantAppDomainsPreference =
|
||||
(AppDomainsPreference) findPreference(KEY_INSTANT_APP_SUPPORTED_LINKS);
|
||||
@@ -626,7 +617,8 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
.setSummary(summary)
|
||||
.setIsInstantApp(isInstantApp)
|
||||
.done(activity, false /* rebindActions */);
|
||||
mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
|
||||
mVersionPreference.setSummary(getString(R.string.version_text,
|
||||
BidiFormatter.getInstance().unicodeWrap(pkgInfo.versionName)));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -935,7 +927,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
// start new activity to manage app permissions
|
||||
Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
|
||||
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
|
||||
intent.putExtra(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
|
||||
intent.putExtra(EXTRA_HIDE_INFO_BUTTON, true);
|
||||
try {
|
||||
getActivity().startActivityForResult(intent, SUB_INFO_FRAGMENT);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
@@ -953,7 +945,6 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_PACKAGE_NAME, appEntry.info.packageName);
|
||||
args.putInt(ARG_PACKAGE_UID, appEntry.info.uid);
|
||||
args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
|
||||
|
||||
SettingsActivity sa = (SettingsActivity) caller.getActivity();
|
||||
sa.startPreferencePanel(caller, fragment.getName(), args, -1, title, caller,
|
||||
@@ -1072,27 +1063,27 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
final Context context = getContext();
|
||||
if (DefaultHomePreferenceController.hasHomePreference(mPackageName, context)) {
|
||||
screen.addPreference(new ShortcutPreference(getPrefContext(),
|
||||
AdvancedAppSettings.class, "default_home", R.string.home_app,
|
||||
DefaultAppSettings.class, "default_home", R.string.home_app,
|
||||
R.string.configure_apps));
|
||||
}
|
||||
if (DefaultBrowserPreferenceController.hasBrowserPreference(mPackageName, context)) {
|
||||
screen.addPreference(new ShortcutPreference(getPrefContext(),
|
||||
AdvancedAppSettings.class, "default_browser", R.string.default_browser_title,
|
||||
DefaultAppSettings.class, "default_browser", R.string.default_browser_title,
|
||||
R.string.configure_apps));
|
||||
}
|
||||
if (DefaultPhonePreferenceController.hasPhonePreference(mPackageName, context)) {
|
||||
screen.addPreference(new ShortcutPreference(getPrefContext(),
|
||||
AdvancedAppSettings.class, "default_phone_app", R.string.default_phone_title,
|
||||
DefaultAppSettings.class, "default_phone_app", R.string.default_phone_title,
|
||||
R.string.configure_apps));
|
||||
}
|
||||
if (DefaultEmergencyPreferenceController.hasEmergencyPreference(mPackageName, context)) {
|
||||
screen.addPreference(new ShortcutPreference(getPrefContext(),
|
||||
AdvancedAppSettings.class, "default_emergency_app",
|
||||
DefaultAppSettings.class, "default_emergency_app",
|
||||
R.string.default_emergency_app, R.string.configure_apps));
|
||||
}
|
||||
if (DefaultSmsPreferenceController.hasSmsPreference(mPackageName, context)) {
|
||||
screen.addPreference(new ShortcutPreference(getPrefContext(),
|
||||
AdvancedAppSettings.class, "default_sms_app", R.string.sms_application_title,
|
||||
DefaultAppSettings.class, "default_sms_app", R.string.sms_application_title,
|
||||
R.string.configure_apps));
|
||||
}
|
||||
|
||||
@@ -1298,7 +1289,7 @@ public class InstalledAppDetails extends AppInfoBase
|
||||
if (DataUsageList.hasReadyMobileRadio(context)) {
|
||||
return NetworkTemplate.buildTemplateMobileWildcard();
|
||||
}
|
||||
if (DataUsageSummary.hasWifiRadio(context)) {
|
||||
if (DataUsageUtils.hasWifiRadio(context)) {
|
||||
return NetworkTemplate.buildTemplateWifiWildcard();
|
||||
}
|
||||
return NetworkTemplate.buildTemplateEthernet();
|
||||
|
||||
@@ -59,6 +59,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Settings;
|
||||
import com.android.settings.Settings.AllApplicationsActivity;
|
||||
import com.android.settings.Settings.GamesStorageActivity;
|
||||
import com.android.settings.Settings.HighPowerApplicationsActivity;
|
||||
@@ -81,6 +82,7 @@ import com.android.settings.notification.AppNotificationSettings;
|
||||
import com.android.settings.notification.ConfigureNotificationSettings;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
import com.android.settings.widget.LoadingViewController;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
@@ -114,6 +116,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
public static final String EXTRA_VOLUME_UUID = "volumeUuid";
|
||||
public static final String EXTRA_VOLUME_NAME = "volumeName";
|
||||
public static final String EXTRA_STORAGE_TYPE = "storageType";
|
||||
public static final String EXTRA_WORK_ONLY = "workProfileOnly";
|
||||
public static final String EXTRA_WORK_ID = "workId";
|
||||
|
||||
private static final String EXTRA_SORT_ORDER = "sortOrder";
|
||||
private static final String EXTRA_SHOW_SYSTEM = "showSystem";
|
||||
@@ -217,6 +221,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
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.
|
||||
public static final int STORAGE_TYPE_PHOTOS_VIDEOS = 3;
|
||||
|
||||
private static final int NO_USER_SPECIFIED = -1;
|
||||
|
||||
// sort order
|
||||
private int mSortOrder = R.id.sort_order_alpha;
|
||||
@@ -260,6 +267,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
public static final int LIST_TYPE_MANAGE_SOURCES = 8;
|
||||
public static final int LIST_TYPE_GAMES = 9;
|
||||
public static final int LIST_TYPE_MOVIES = 10;
|
||||
public static final int LIST_TYPE_PHOTOGRAPHY = 11;
|
||||
|
||||
|
||||
// List types that should show instant apps.
|
||||
@@ -276,6 +284,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
private ResetAppsHelper mResetAppsHelper;
|
||||
private String mVolumeUuid;
|
||||
private int mStorageType;
|
||||
private boolean mIsWorkOnly;
|
||||
private int mWorkUserId;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -323,10 +333,16 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
} else if (className.equals(MoviesStorageActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_MOVIES;
|
||||
mSortOrder = R.id.sort_order_size;
|
||||
} else if (className.equals(Settings.PhotosStorageActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_PHOTOGRAPHY;
|
||||
mSortOrder = R.id.sort_order_size;
|
||||
mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
|
||||
} else {
|
||||
mListType = LIST_TYPE_MAIN;
|
||||
}
|
||||
mFilter = getDefaultFilter();
|
||||
mIsWorkOnly = args != null ? args.getBoolean(EXTRA_WORK_ONLY) : false;
|
||||
mWorkUserId = args != null ? args.getInt(EXTRA_WORK_ID) : NO_USER_SPECIFIED;
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
|
||||
@@ -367,13 +383,23 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
mApplications.mHasReceivedBridgeCallback =
|
||||
savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
|
||||
}
|
||||
int userId = mIsWorkOnly ? mWorkUserId : UserHandle.getUserId(mCurrentUid);
|
||||
if (mStorageType == STORAGE_TYPE_MUSIC) {
|
||||
Context context = getContext();
|
||||
mApplications.setExtraViewController(new MusicViewHolderController(
|
||||
context,
|
||||
new StorageStatsSource(context),
|
||||
mVolumeUuid,
|
||||
UserHandle.of(UserHandle.getUserId(mCurrentUid))));
|
||||
mApplications.setExtraViewController(
|
||||
new MusicViewHolderController(
|
||||
context,
|
||||
new StorageStatsSource(context),
|
||||
mVolumeUuid,
|
||||
UserHandle.of(userId)));
|
||||
} else if (mStorageType == STORAGE_TYPE_PHOTOS_VIDEOS) {
|
||||
Context context = getContext();
|
||||
mApplications.setExtraViewController(
|
||||
new PhotosViewHolderController(
|
||||
context,
|
||||
new StorageStatsSource(context),
|
||||
mVolumeUuid,
|
||||
UserHandle.of(userId)));
|
||||
}
|
||||
mListView.setAdapter(mApplications);
|
||||
mListView.setRecyclerListener(mApplications);
|
||||
@@ -422,6 +448,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
}
|
||||
|
||||
AppFilter compositeFilter = getCompositeFilter(mListType, mStorageType, mVolumeUuid);
|
||||
if (mIsWorkOnly) {
|
||||
compositeFilter = new CompoundFilter(compositeFilter, FILTERS[FILTER_APPS_WORK]);
|
||||
}
|
||||
if (compositeFilter != null) {
|
||||
mApplications.setCompositeFilter(compositeFilter);
|
||||
}
|
||||
@@ -443,6 +472,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
return new CompoundFilter(ApplicationsState.FILTER_GAMES, filter);
|
||||
} else if (listType == LIST_TYPE_MOVIES) {
|
||||
return new CompoundFilter(ApplicationsState.FILTER_MOVIES, filter);
|
||||
} else if (listType == LIST_TYPE_PHOTOGRAPHY) {
|
||||
return new CompoundFilter(ApplicationsState.FILTER_PHOTOS, filter);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -472,6 +503,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
case LIST_TYPE_STORAGE:
|
||||
case LIST_TYPE_GAMES:
|
||||
case LIST_TYPE_MOVIES:
|
||||
case LIST_TYPE_PHOTOGRAPHY:
|
||||
return mSortOrder == R.id.sort_order_alpha;
|
||||
default:
|
||||
return false;
|
||||
@@ -494,6 +526,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
return MetricsEvent.APPLICATIONS_STORAGE_GAMES;
|
||||
case LIST_TYPE_MOVIES:
|
||||
return MetricsEvent.APPLICATIONS_STORAGE_MOVIES;
|
||||
case LIST_TYPE_PHOTOGRAPHY:
|
||||
return MetricsEvent.APPLICATIONS_STORAGE_PHOTOS;
|
||||
case LIST_TYPE_USAGE_ACCESS:
|
||||
return MetricsEvent.USAGE_ACCESS;
|
||||
case LIST_TYPE_HIGH_POWER:
|
||||
@@ -597,6 +631,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
case LIST_TYPE_MOVIES:
|
||||
startAppInfoFragment(AppStorageSettings.class, R.string.storage_movies_tv);
|
||||
break;
|
||||
case LIST_TYPE_PHOTOGRAPHY:
|
||||
startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos);
|
||||
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.
|
||||
@@ -687,7 +724,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
ADVANCED_SETTINGS);
|
||||
} else {
|
||||
((SettingsActivity) getActivity()).startPreferencePanel(this,
|
||||
AdvancedAppSettings.class.getName(), null, R.string.configure_apps,
|
||||
DefaultAppSettings.class.getName(), null, R.string.configure_apps,
|
||||
null, this, ADVANCED_SETTINGS);
|
||||
}
|
||||
return true;
|
||||
@@ -849,6 +886,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
private final AppStateBaseBridge mExtraInfoBridge;
|
||||
private final Handler mBgHandler;
|
||||
private final Handler mFgHandler;
|
||||
private final LoadingViewController mLoadingViewController;
|
||||
|
||||
private int mFilterMode;
|
||||
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
|
||||
@@ -894,12 +932,6 @@ 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) {
|
||||
@@ -908,6 +940,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
mBgHandler = new Handler(mState.getBackgroundLooper());
|
||||
mSession = state.newSession(this);
|
||||
mManageApplications = manageApplications;
|
||||
mLoadingViewController = new LoadingViewController(
|
||||
mManageApplications.mLoadingContainer,
|
||||
mManageApplications.mListContainer
|
||||
);
|
||||
mContext = manageApplications.getActivity();
|
||||
mPm = mContext.getPackageManager();
|
||||
mFilterMode = filterMode;
|
||||
@@ -1109,11 +1145,7 @@ 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);
|
||||
mLoadingViewController.showContent(true /* animate */);
|
||||
}
|
||||
if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
|
||||
// No enabled or disabled filters for usage access.
|
||||
@@ -1167,11 +1199,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
void updateLoading() {
|
||||
final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
|
||||
if (appLoaded) {
|
||||
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
|
||||
mManageApplications.mListContainer, true /* done */, false /* animate */);
|
||||
mLoadingViewController.showContent(false /* animate */);
|
||||
} else {
|
||||
mFgHandler.postDelayed(
|
||||
mShowLoadingContainerRunnable, DELAY_SHOW_LOADING_CONTAINER_THRESHOLD_MS);
|
||||
mLoadingViewController.showLoadingViewDelayed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ public class ManageDomainUrls extends SettingsPreferenceFragment
|
||||
final Intent launchIntent = instantAppSettingsIntent;
|
||||
// TODO: Make this button actually launch the account chooser.
|
||||
mInstantAppAccountPreference = new Preference(getPrefContext());
|
||||
mInstantAppAccountPreference.setTitle(R.string.instant_apps_account);
|
||||
mInstantAppAccountPreference.setTitle(R.string.instant_apps_settings);
|
||||
mInstantAppAccountPreference.setOnPreferenceClickListener(pref -> {
|
||||
startActivity(launchIntent);
|
||||
return true;
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDeleteObserver;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
@@ -48,6 +49,11 @@ public interface PackageManagerWrapper {
|
||||
*/
|
||||
List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId);
|
||||
|
||||
/**
|
||||
* Calls {@code PackageManager.getInstalledPackagesAsUser}
|
||||
*/
|
||||
List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId);
|
||||
|
||||
/**
|
||||
* Calls {@code PackageManager.hasSystemFeature()}.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDeleteObserver;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
@@ -46,6 +47,11 @@ public class PackageManagerWrapperImpl implements PackageManagerWrapper {
|
||||
return mPm.getInstalledApplicationsAsUser(flags, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
|
||||
return mPm.getInstalledPackagesAsUser(flags, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSystemFeature(String name) {
|
||||
return mPm.hasSystemFeature(name);
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.text.format.Formatter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** PhotosViewHolderController controls an Audio/Music file view in the ManageApplications view. */
|
||||
public class PhotosViewHolderController implements FileViewHolderController {
|
||||
private static final String TAG = "PhotosViewHolderController";
|
||||
|
||||
private static final String IMAGE_MIME_TYPE = "image/*";
|
||||
private static final int INSET_SIZE = 24; // dp
|
||||
|
||||
private Context mContext;
|
||||
private StorageStatsSource mSource;
|
||||
private String mVolumeUuid;
|
||||
private long mFilesSize;
|
||||
private UserHandle mUser;
|
||||
|
||||
public PhotosViewHolderController(
|
||||
Context context, StorageStatsSource source, String volumeUuid, UserHandle user) {
|
||||
mContext = context;
|
||||
mSource = source;
|
||||
mVolumeUuid = volumeUuid;
|
||||
mUser = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
@WorkerThread
|
||||
public void queryStats() {
|
||||
try {
|
||||
StorageStatsSource.ExternalStorageStats stats =
|
||||
mSource.getExternalStorageStats(mVolumeUuid, mUser);
|
||||
mFilesSize = stats.imageBytes + stats.videoBytes;
|
||||
} catch (IOException e) {
|
||||
mFilesSize = 0;
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupView(AppViewHolder holder) {
|
||||
holder.appIcon.setImageDrawable(
|
||||
new InsetDrawable(mContext.getDrawable(R.drawable.ic_photo_library), INSET_SIZE));
|
||||
holder.appName.setText(mContext.getText(R.string.storage_detail_images));
|
||||
holder.summary.setText(Formatter.formatFileSize(mContext, mFilesSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Fragment fragment) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
|
||||
intent.setType(IMAGE_MIME_TYPE);
|
||||
intent.putExtra(Intent.EXTRA_FROM_STORAGE, true);
|
||||
Utils.launchIntent(fragment, intent);
|
||||
}
|
||||
}
|
||||
@@ -22,14 +22,16 @@ import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -37,8 +39,10 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.notification.EmptyTextSettings;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
@@ -50,8 +54,38 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
IGNORE_PACKAGE_LIST.add("com.android.systemui");
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator by name, then user id.
|
||||
* {@see PackageItemInfo#DisplayNameComparator}
|
||||
*/
|
||||
static class AppComparator implements Comparator<Pair<ApplicationInfo, Integer>> {
|
||||
|
||||
private final Collator mCollator = Collator.getInstance();
|
||||
private final PackageManager mPm;
|
||||
|
||||
public AppComparator(PackageManager pm) {
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
public final int compare(Pair<ApplicationInfo, Integer> a,
|
||||
Pair<ApplicationInfo, Integer> b) {
|
||||
CharSequence sa = a.first.loadLabel(mPm);
|
||||
if (sa == null) sa = a.first.name;
|
||||
CharSequence sb = b.first.loadLabel(mPm);
|
||||
if (sb == null) sb = b.first.name;
|
||||
int nameCmp = mCollator.compare(sa.toString(), sb.toString());
|
||||
if (nameCmp != 0) {
|
||||
return nameCmp;
|
||||
} else {
|
||||
return a.second - b.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private PackageManager mPackageManager;
|
||||
private PackageManagerWrapper mPackageManager;
|
||||
private UserManagerWrapper mUserManager;
|
||||
private IconDrawableFactory mIconDrawableFactory;
|
||||
|
||||
/**
|
||||
* @return true if the package has any activities that declare that they support
|
||||
@@ -93,12 +127,23 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
return false;
|
||||
}
|
||||
|
||||
public PictureInPictureSettings() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public PictureInPictureSettings(PackageManagerWrapper pm, UserManagerWrapper um) {
|
||||
mPackageManager = pm;
|
||||
mUserManager = um;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mContext = getActivity();
|
||||
mPackageManager = mContext.getPackageManager();
|
||||
mPackageManager = new PackageManagerWrapperImpl(mContext.getPackageManager());
|
||||
mUserManager = new UserManagerWrapperImpl(mContext.getSystemService(UserManager.class));
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext));
|
||||
}
|
||||
|
||||
@@ -110,33 +155,25 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removeAll();
|
||||
|
||||
// Fetch the set of applications which have at least one activity that declare that they
|
||||
// support picture-in-picture
|
||||
final ArrayMap<String, Boolean> packageToState = new ArrayMap<>();
|
||||
final ArrayList<ApplicationInfo> pipApps = new ArrayList<>();
|
||||
final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, UserHandle.myUserId());
|
||||
for (PackageInfo packageInfo : installedPackages) {
|
||||
if (checkPackageHasPictureInPictureActivities(packageInfo.packageName,
|
||||
packageInfo.activities)) {
|
||||
final String packageName = packageInfo.applicationInfo.packageName;
|
||||
final boolean state = PictureInPictureDetails.getEnterPipStateForPackage(
|
||||
mContext, packageInfo.applicationInfo.uid, packageName);
|
||||
pipApps.add(packageInfo.applicationInfo);
|
||||
packageToState.put(packageName, state);
|
||||
}
|
||||
}
|
||||
Collections.sort(pipApps, new PackageItemInfo.DisplayNameComparator(mPackageManager));
|
||||
// Fetch the set of applications for each profile which have at least one activity that
|
||||
// declare that they support picture-in-picture
|
||||
final PackageManager pm = mPackageManager.getPackageManager();
|
||||
final ArrayList<Pair<ApplicationInfo, Integer>> pipApps =
|
||||
collectPipApps(UserHandle.myUserId());
|
||||
Collections.sort(pipApps, new AppComparator(pm));
|
||||
|
||||
// Rebuild the list of prefs
|
||||
final Context prefContext = getPrefContext();
|
||||
for (final ApplicationInfo appInfo : pipApps) {
|
||||
for (final Pair<ApplicationInfo, Integer> appData : pipApps) {
|
||||
final ApplicationInfo appInfo = appData.first;
|
||||
final int userId = appData.second;
|
||||
final UserHandle user = UserHandle.of(userId);
|
||||
final String packageName = appInfo.packageName;
|
||||
final CharSequence label = appInfo.loadLabel(mPackageManager);
|
||||
final CharSequence label = appInfo.loadLabel(pm);
|
||||
|
||||
final Preference pref = new Preference(prefContext);
|
||||
pref.setIcon(appInfo.loadIcon(mPackageManager));
|
||||
pref.setTitle(label);
|
||||
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appInfo, userId));
|
||||
pref.setTitle(pm.getUserBadgedLabel(label, user));
|
||||
pref.setSummary(PictureInPictureDetails.getPreferenceSummary(prefContext,
|
||||
appInfo.uid, packageName));
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@@ -162,4 +199,28 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.SETTINGS_MANAGE_PICTURE_IN_PICTURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of applications for the given user and all their profiles that have
|
||||
* activities which support PiP.
|
||||
*/
|
||||
ArrayList<Pair<ApplicationInfo, Integer>> collectPipApps(int userId) {
|
||||
final ArrayList<Pair<ApplicationInfo, Integer>> pipApps = new ArrayList<>();
|
||||
final ArrayList<Integer> userIds = new ArrayList<>();
|
||||
for (UserInfo user : mUserManager.getProfiles(userId)) {
|
||||
userIds.add(user.id);
|
||||
}
|
||||
|
||||
for (int id : userIds) {
|
||||
final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, id);
|
||||
for (PackageInfo packageInfo : installedPackages) {
|
||||
if (checkPackageHasPictureInPictureActivities(packageInfo.packageName,
|
||||
packageInfo.activities)) {
|
||||
pipApps.add(new Pair<>(packageInfo.applicationInfo, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pipApps;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,13 @@ public class PremiumSmsAccess extends EmptyTextSettings implements Callback, Cal
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mSmsBackend.release();
|
||||
mSession.release();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.PREMIUM_SMS_ACCESS;
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.android.internal.app.procstats.ProcessStats;
|
||||
import com.android.settings.AppHeader;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
@@ -138,7 +137,6 @@ public abstract class ProcessStatsBase extends SettingsPreferenceFragment
|
||||
args.putDouble(ProcessStatsDetail.EXTRA_MAX_MEMORY_USAGE,
|
||||
memInfo.usedWeight * memInfo.weightToRam);
|
||||
args.putDouble(ProcessStatsDetail.EXTRA_TOTAL_SCALE, memInfo.totalScale);
|
||||
args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, !includeAppInfo);
|
||||
activity.startPreferencePanel(null, ProcessStatsDetail.class.getName(), args,
|
||||
R.string.memory_usage, null, null, 0);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,8 @@ public class ProcessStatsDetail extends SettingsPreferenceFragment {
|
||||
.setUid(mApp.mUiTargetApp != null
|
||||
? mApp.mUiTargetApp.uid
|
||||
: UserHandle.USER_NULL)
|
||||
.setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
|
||||
.setHasAppInfoLink(true)
|
||||
.setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
|
||||
.done(activity, getPrefContext());
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
|
||||
.SETTINGS_APP_NOTIF_CATEGORY;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.Fragment;
|
||||
import android.app.usage.UsageStats;
|
||||
@@ -29,7 +32,6 @@ 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;
|
||||
@@ -37,8 +39,9 @@ import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -49,15 +52,12 @@ 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> {
|
||||
public class RecentAppsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Comparator<UsageStats> {
|
||||
|
||||
private static final String TAG = "RecentAppsCtrl";
|
||||
private static final String KEY_PREF_CATEGORY = "recent_apps_category";
|
||||
@@ -122,7 +122,7 @@ public class RecentAppsPreferenceController extends PreferenceController
|
||||
|
||||
@Override
|
||||
public void updateNonIndexableKeys(List<String> keys) {
|
||||
super.updateNonIndexableKeys(keys);
|
||||
PreferenceControllerMixin.super.updateNonIndexableKeys(keys);
|
||||
// Don't index category name into search. It's not actionable.
|
||||
keys.add(KEY_PREF_CATEGORY);
|
||||
keys.add(KEY_DIVIDER);
|
||||
|
||||
@@ -21,14 +21,15 @@ import android.os.Bundle;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
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 {
|
||||
public class ResetAppPrefPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnSaveInstanceState {
|
||||
|
||||
private ResetAppsHelper mResetAppsHelper;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.settings.applications;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -27,7 +26,7 @@ import android.view.ViewGroup;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.widget.LoadingViewController;
|
||||
|
||||
public class RunningServices extends SettingsPreferenceFragment {
|
||||
|
||||
@@ -37,6 +36,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
||||
private RunningProcessesView mRunningProcessesView;
|
||||
private Menu mOptionsMenu;
|
||||
private View mLoadingContainer;
|
||||
private LoadingViewController mLoadingViewController;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -47,12 +47,13 @@ public class RunningServices extends SettingsPreferenceFragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.manage_applications_running, null);
|
||||
mRunningProcessesView = (RunningProcessesView) rootView.findViewById(
|
||||
R.id.running_processes);
|
||||
mRunningProcessesView = rootView.findViewById(R.id.running_processes);
|
||||
mRunningProcessesView.doCreate();
|
||||
mLoadingContainer = rootView.findViewById(R.id.loading_container);
|
||||
mLoadingViewController = new LoadingViewController(
|
||||
mLoadingContainer, mRunningProcessesView);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
@@ -71,7 +72,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
boolean haveData = mRunningProcessesView.doResume(this, mRunningProcessesAvail);
|
||||
Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, haveData, false);
|
||||
mLoadingViewController.handleLoadingContainer(haveData /* done */, false /* animate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,7 +116,7 @@ public class RunningServices extends SettingsPreferenceFragment {
|
||||
private final Runnable mRunningProcessesAvail = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Utils.handleLoadingContainer(mLoadingContainer, mRunningProcessesView, true, true);
|
||||
mLoadingViewController.showContent(true /* animate */);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
@@ -50,6 +49,7 @@ public class SpacePreference extends Preference {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
new int[] { com.android.internal.R.attr.layout_height }, defStyleAttr, defStyleRes);
|
||||
mHeight = a.getDimensionPixelSize(0, 0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
|
||||
@@ -14,16 +14,17 @@
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import android.support.v7.preference.Preference;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,6 +32,10 @@ public class SpecialAccessSettings extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "SpecialAccessSettings";
|
||||
|
||||
private static final String[] DISABLED_FEATURES_LOW_RAM =
|
||||
new String[]{"notification_access", "zen_access", "enabled_vr_listeners",
|
||||
"picture_in_picture"};
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
@@ -42,7 +47,21 @@ public class SpecialAccessSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
if (ActivityManager.isLowRamDeviceStatic()) {
|
||||
for (String disabledFeature : DISABLED_FEATURES_LOW_RAM) {
|
||||
Preference pref = findPreference(disabledFeature);
|
||||
if (pref != null) {
|
||||
removePreference(disabledFeature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,12 @@ package com.android.settings.applications;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.datausage.DataSaverBackend;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class SpecialAppAccessPreferenceController extends PreferenceController {
|
||||
public class SpecialAppAccessPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_SPECIAL_ACCESS = "special_access";
|
||||
|
||||
|
||||
@@ -29,4 +29,5 @@ import java.util.List;
|
||||
public interface UserManagerWrapper {
|
||||
UserInfo getPrimaryUser();
|
||||
List<UserInfo> getUsers();
|
||||
List<UserInfo> getProfiles(int userHandle);
|
||||
}
|
||||
|
||||
@@ -37,4 +37,9 @@ public class UserManagerWrapperImpl implements UserManagerWrapper {
|
||||
public List<UserInfo> getUsers() {
|
||||
return mUserManager.getUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserInfo> getProfiles(int userHandle) {
|
||||
return mUserManager.getProfiles(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -34,8 +35,9 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistContextPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
public class AssistContextPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_CONTEXT = "context";
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ 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.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -36,8 +37,9 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistFlashScreenPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
public class AssistFlashScreenPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_FLASH = "flash";
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -34,8 +35,9 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AssistScreenshotPreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
|
||||
public class AssistScreenshotPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_SCREENSHOT = "screenshot";
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.service.voice.VoiceInteractionService;
|
||||
import android.service.voice.VoiceInteractionServiceInfo;
|
||||
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
|
||||
@@ -33,17 +33,23 @@ import java.util.List;
|
||||
|
||||
public class DefaultAssistPreferenceController extends DefaultAppPreferenceController {
|
||||
|
||||
private static final String KEY_DEFAULT_ASSIST = "default_assist";
|
||||
private final AssistUtils mAssistUtils;
|
||||
private final boolean mShowSetting;
|
||||
private final String mPrefKey;
|
||||
|
||||
private AssistUtils mAssistUtils;
|
||||
|
||||
public DefaultAssistPreferenceController(Context context) {
|
||||
public DefaultAssistPreferenceController(Context context, String prefKey,
|
||||
boolean showSetting) {
|
||||
super(context);
|
||||
mPrefKey = prefKey;
|
||||
mShowSetting = showSetting;
|
||||
mAssistUtils = new AssistUtils(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getSettingIntent(DefaultAppInfo info) {
|
||||
if (!mShowSetting) {
|
||||
return null;
|
||||
}
|
||||
final ComponentName cn = mAssistUtils.getAssistComponentForUser(mUserId);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
@@ -72,7 +78,7 @@ public class DefaultAssistPreferenceController extends DefaultAppPreferenceContr
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_DEFAULT_ASSIST;
|
||||
return mPrefKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,11 +21,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.dashboard.DashboardFragment;
|
||||
import com.android.settings.gestures.AssistGesturePreferenceController;
|
||||
import com.android.settings.gestures.AssistGestureSettingsPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -51,7 +51,7 @@ public class ManageAssist extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getLifecycle());
|
||||
}
|
||||
|
||||
@@ -68,12 +68,13 @@ public class ManageAssist extends DashboardFragment {
|
||||
.setTitle(R.string.assist_footer);
|
||||
}
|
||||
|
||||
private static List<PreferenceController> buildPreferenceControllers(Context context,
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Lifecycle lifecycle) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new DefaultAssistPreferenceController(context));
|
||||
controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
|
||||
true /* assistOnly */));
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new DefaultAssistPreferenceController(context, "default_assist",
|
||||
true /* showSetting */));
|
||||
controllers.add(new AssistGestureSettingsPreferenceController(context, lifecycle,
|
||||
KEY_ASSIST, true /* assistOnly */));
|
||||
controllers.add(new AssistContextPreferenceController(context, lifecycle));
|
||||
controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
|
||||
controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
|
||||
@@ -81,7 +82,6 @@ public class ManageAssist extends DashboardFragment {
|
||||
return controllers;
|
||||
}
|
||||
|
||||
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
@@ -93,7 +93,8 @@ public class ManageAssist extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null /* lifecycle */);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.settings.applications.defaultapps;
|
||||
|
||||
import android.app.AppGlobals;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ComponentInfo;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.applications.defaultapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
@@ -27,10 +28,12 @@ import android.util.Log;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.PackageManagerWrapper;
|
||||
import com.android.settings.applications.PackageManagerWrapperImpl;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.GearPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public abstract class DefaultAppPreferenceController extends PreferenceController {
|
||||
public abstract class DefaultAppPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "DefaultAppPrefControl";
|
||||
|
||||
@@ -52,9 +55,11 @@ public abstract class DefaultAppPreferenceController extends PreferenceControlle
|
||||
CharSequence defaultAppLabel = getDefaultAppLabel();
|
||||
if (!TextUtils.isEmpty(defaultAppLabel)) {
|
||||
preference.setSummary(defaultAppLabel);
|
||||
preference.setIcon(getDefaultAppIcon());
|
||||
} else {
|
||||
Log.d(TAG, "No default app");
|
||||
preference.setSummary(R.string.app_list_preference_none);
|
||||
preference.setIcon(null);
|
||||
}
|
||||
mayUpdateGearIcon(app, preference);
|
||||
}
|
||||
@@ -82,6 +87,17 @@ public abstract class DefaultAppPreferenceController extends PreferenceControlle
|
||||
return null;
|
||||
}
|
||||
|
||||
public Drawable getDefaultAppIcon() {
|
||||
if (!isAvailable()) {
|
||||
return null;
|
||||
}
|
||||
final DefaultAppInfo app = getDefaultAppInfo();
|
||||
if (app != null) {
|
||||
return app.loadIcon();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CharSequence getDefaultAppLabel() {
|
||||
if (!isAvailable()) {
|
||||
return null;
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
||||
import android.content.pm.ComponentInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
@@ -86,6 +87,18 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
|
||||
return getOnlyAppLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDefaultAppIcon() {
|
||||
if (!isAvailable()) {
|
||||
return null;
|
||||
}
|
||||
final DefaultAppInfo defaultApp = getDefaultAppInfo();
|
||||
if (defaultApp != null) {
|
||||
return defaultApp.loadIcon();
|
||||
}
|
||||
return getOnlyAppIcon();
|
||||
}
|
||||
|
||||
private List<ResolveInfo> getCandidates() {
|
||||
return mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE, PackageManager.MATCH_ALL,
|
||||
mUserId);
|
||||
@@ -105,6 +118,18 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
|
||||
return null;
|
||||
}
|
||||
|
||||
private Drawable getOnlyAppIcon() {
|
||||
final List<ResolveInfo> list = getCandidates();
|
||||
if (list != null && list.size() == 1) {
|
||||
final ResolveInfo info = list.get(0);
|
||||
final ComponentInfo cn = info.getComponentInfo();
|
||||
final String packageName = cn == null ? null : cn.packageName;
|
||||
Log.d(TAG, "Getting icon for the only browser app: " + packageName);
|
||||
return info.loadIcon(mPackageManager.getPackageManager());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the pkg contains browser capability
|
||||
*/
|
||||
|
||||
@@ -23,8 +23,6 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.applications.PackageManagerWrapper;
|
||||
|
||||
@@ -58,28 +56,21 @@ public class DefaultHomePreferenceController extends DefaultAppPreferenceControl
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
final DefaultAppInfo defaultApp = getDefaultAppInfo();
|
||||
final CharSequence defaultAppLabel = defaultApp != null ? defaultApp.loadLabel() : null;
|
||||
if (TextUtils.isEmpty(defaultAppLabel)) {
|
||||
final String onlyAppLabel = getOnlyAppLabel();
|
||||
if (!TextUtils.isEmpty(onlyAppLabel)) {
|
||||
preference.setSummary(onlyAppLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultAppInfo getDefaultAppInfo() {
|
||||
final ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
|
||||
final ComponentName currentDefaultHome = mPackageManager.getHomeActivities(homeActivities);
|
||||
|
||||
return new DefaultAppInfo(mPackageManager, mUserId, currentDefaultHome);
|
||||
if (currentDefaultHome != null) {
|
||||
return new DefaultAppInfo(mPackageManager, mUserId, currentDefaultHome);
|
||||
}
|
||||
final ActivityInfo onlyAppInfo = getOnlyAppInfo();
|
||||
if (onlyAppInfo != null) {
|
||||
return new DefaultAppInfo(mPackageManager, mUserId, onlyAppInfo.getComponentName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getOnlyAppLabel() {
|
||||
private ActivityInfo getOnlyAppInfo() {
|
||||
final List<ResolveInfo> homeActivities = new ArrayList<>();
|
||||
final List<ActivityInfo> appLabels = new ArrayList<>();
|
||||
|
||||
@@ -92,7 +83,7 @@ public class DefaultHomePreferenceController extends DefaultAppPreferenceControl
|
||||
appLabels.add(info);
|
||||
}
|
||||
return appLabels.size() == 1
|
||||
? appLabels.get(0).loadLabel(mPackageManager.getPackageManager()).toString()
|
||||
? appLabels.get(0)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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.defaultapps;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationAssistantService;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.utils.ManagedServiceSettings;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultNotificationAssistantPicker extends DefaultAppPickerFragment {
|
||||
private static final String TAG = "DefaultNotiAssist";
|
||||
|
||||
private final ManagedServiceSettings.Config mConfig = getConfig();
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultKey() {
|
||||
return Settings.Secure.getString(getContext().getContentResolver(), mConfig.setting);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultKey(String value) {
|
||||
Settings.Secure.putString(getContext().getContentResolver(), mConfig.setting, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<DefaultAppInfo> getCandidates() {
|
||||
List<DefaultAppInfo> candidates = new ArrayList<>();
|
||||
final int user = ActivityManager.getCurrentUser();
|
||||
|
||||
List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
|
||||
new Intent(mConfig.intentAction),
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
|
||||
user);
|
||||
|
||||
for (int i = 0, count = installedServices.size(); i < count; i++) {
|
||||
ResolveInfo resolveInfo = installedServices.get(i);
|
||||
ServiceInfo info = resolveInfo.serviceInfo;
|
||||
|
||||
if (!mConfig.permission.equals(info.permission)) {
|
||||
Slog.w(mConfig.tag, "Skipping " + mConfig.noun + " service "
|
||||
+ info.packageName + "/" + info.name
|
||||
+ ": it does not require the permission "
|
||||
+ mConfig.permission);
|
||||
continue;
|
||||
}
|
||||
|
||||
candidates.add(new DefaultAppInfo(mPm,
|
||||
mUserId, new ComponentName(info.packageName, info.name)));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldShowItemNone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private ManagedServiceSettings.Config getConfig() {
|
||||
final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config();
|
||||
c.tag = TAG;
|
||||
c.setting = Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT;
|
||||
c.intentAction = NotificationAssistantService.SERVICE_INTERFACE;
|
||||
c.permission = android.Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE;
|
||||
c.noun = "notification assistant";
|
||||
c.warningDialogTitle = R.string.notification_listener_security_warning_title;
|
||||
c.warningDialogSummary = R.string.notification_listener_security_warning_summary;
|
||||
c.emptyText = R.string.no_notification_listeners;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.defaultapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.nfc.PaymentBackend;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class DefaultPaymentSettingsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private final NfcAdapter mNfcAdapter;
|
||||
private final PackageManager mPackageManager;
|
||||
private final UserManager mUserManager;
|
||||
private PaymentBackend mPaymentBackend;
|
||||
|
||||
public DefaultPaymentSettingsPreferenceController(Context context) {
|
||||
super(context);
|
||||
mPackageManager = context.getPackageManager();
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
|
||||
&& mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
|
||||
&& mUserManager.isAdminUser()
|
||||
&& mNfcAdapter != null
|
||||
&& mNfcAdapter.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mPaymentBackend == null) {
|
||||
if (mNfcAdapter != null) {
|
||||
mPaymentBackend = new PaymentBackend(mContext);
|
||||
} else {
|
||||
mPaymentBackend = null;
|
||||
}
|
||||
}
|
||||
if (mPaymentBackend == null) {
|
||||
return;
|
||||
}
|
||||
mPaymentBackend.refresh();
|
||||
final PaymentBackend.PaymentAppInfo app = mPaymentBackend.getDefaultApp();
|
||||
if (app != null) {
|
||||
preference.setSummary(app.label);
|
||||
} else {
|
||||
preference.setSummary(R.string.app_list_preference_none);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return "default_payment_app";
|
||||
}
|
||||
}
|
||||
@@ -18,19 +18,15 @@ package com.android.settings.backup;
|
||||
|
||||
import android.app.backup.BackupManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class BackupSettingsActivityPreferenceController extends PreferenceController {
|
||||
public class BackupSettingsActivityPreferenceController extends
|
||||
AbstractPreferenceController implements PreferenceControllerMixin {
|
||||
private static final String KEY_BACKUP_SETTINGS = "backup_settings";
|
||||
private static final String TAG = "BackupSettingActivityPC" ;
|
||||
|
||||
|
||||
@@ -21,10 +21,11 @@ import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -57,11 +58,11 @@ public class BackupSettingsFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of {@link PreferenceController} for this fragment.
|
||||
* Get a list of {@link AbstractPreferenceController} for this fragment.
|
||||
*/
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new BackupSettingsPreferenceController(context));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ import android.content.Intent;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class BackupSettingsPreferenceController extends PreferenceController {
|
||||
public class BackupSettingsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
private static final String BACKUP_SETTINGS = "backup_settings";
|
||||
private static final String MANUFACTURER_SETTINGS = "manufacturer_backup";
|
||||
private Intent mBackupSettingsIntent;
|
||||
|
||||
@@ -20,8 +20,9 @@ import android.content.Context;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
@@ -31,8 +32,9 @@ import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
* This class provides common lifecycle and bluetooth device event registration for Bluetooth device
|
||||
* details controllers.
|
||||
*/
|
||||
public abstract class BluetoothDetailsController extends PreferenceController
|
||||
implements CachedBluetoothDevice.Callback, LifecycleObserver, OnPause, OnResume {
|
||||
public abstract class BluetoothDetailsController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, CachedBluetoothDevice.Callback, LifecycleObserver,
|
||||
OnPause, OnResume {
|
||||
|
||||
protected final Context mContext;
|
||||
protected final PreferenceFragment mFragment;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.Pair;
|
||||
@@ -51,11 +51,12 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
|
||||
}
|
||||
|
||||
protected void setHeaderProperties() {
|
||||
Pair<Integer, String> pair = Utils.getBtClassDrawableWithDescription
|
||||
(mContext.getResources(), mCachedDevice);
|
||||
final Pair<Drawable, String> pair = Utils.getBtClassDrawableWithDescription(
|
||||
mContext, mCachedDevice,
|
||||
mContext.getResources().getFraction(R.fraction.bt_battery_scale_fraction, 1, 1));
|
||||
String summaryText = mCachedDevice.getConnectionSummary();
|
||||
mHeaderController.setLabel(mCachedDevice.getName());
|
||||
mHeaderController.setIcon(mContext.getDrawable(pair.first));
|
||||
mHeaderController.setIcon(pair.first);
|
||||
mHeaderController.setIconContentDescription(pair.second);
|
||||
mHeaderController.setSummary(summaryText);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import android.view.MenuItem;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -136,8 +136,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
ArrayList<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
|
||||
if (mCachedDevice != null) {
|
||||
Lifecycle lifecycle = getLifecycle();
|
||||
|
||||
@@ -29,9 +29,10 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
@@ -40,8 +41,8 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
/**
|
||||
* Controller that shows and updates the bluetooth device name
|
||||
*/
|
||||
public class BluetoothDeviceNamePreferenceController extends PreferenceController implements
|
||||
LifecycleObserver, OnStart, OnStop {
|
||||
public class BluetoothDeviceNamePreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
|
||||
private static final String TAG = "BluetoothNamePrefCtrl";
|
||||
|
||||
public static final String KEY_DEVICE_NAME = "device_name";
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
@@ -53,16 +54,17 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
private final UserManager mUserManager;
|
||||
|
||||
private AlertDialog mDisconnectDialog;
|
||||
|
||||
private String contentDescription = null;
|
||||
|
||||
private DeviceListPreferenceFragment mDeviceListPreferenceFragment;
|
||||
/* Talk-back descriptions for various BT icons */
|
||||
Resources mResources;
|
||||
|
||||
public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
|
||||
public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
|
||||
DeviceListPreferenceFragment deviceListPreferenceFragment) {
|
||||
super(context, null);
|
||||
mResources = getContext().getResources();
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mDeviceListPreferenceFragment = deviceListPreferenceFragment;
|
||||
|
||||
if (sDimAlpha == Integer.MIN_VALUE) {
|
||||
TypedValue outValue = new TypedValue();
|
||||
@@ -120,9 +122,9 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
// Null check is done at the framework
|
||||
setSummary(mCachedDevice.getConnectionSummary());
|
||||
|
||||
Pair<Integer, String> pair = Utils.getBtClassDrawableWithDescription(mResources,
|
||||
final Pair<Drawable, String> pair = Utils.getBtClassDrawableWithDescription(getContext(),
|
||||
mCachedDevice);
|
||||
if (pair.first != 0) {
|
||||
if (pair.first != null) {
|
||||
setIcon(pair.first);
|
||||
contentDescription = pair.second;
|
||||
}
|
||||
@@ -130,6 +132,11 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
// Used to gray out the item
|
||||
setEnabled(!mCachedDevice.isBusy());
|
||||
|
||||
// Device is only visible in the UI if it has a valid name besides MAC address or when user
|
||||
// allows showing devices without user-friendly name in developer settings
|
||||
setVisible(mDeviceListPreferenceFragment.shouldShowDevicesWithoutNames()
|
||||
|| mCachedDevice.hasHumanReadableName());
|
||||
|
||||
// This could affect ordering, so notify that
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
@@ -181,22 +188,27 @@ public final class BluetoothDevicePreference extends GearPreference implements
|
||||
}
|
||||
|
||||
void onClicked() {
|
||||
Context context = getContext();
|
||||
int bondState = mCachedDevice.getBondState();
|
||||
|
||||
final MetricsFeatureProvider metricsFeatureProvider =
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider();
|
||||
FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
|
||||
if (mCachedDevice.isConnected()) {
|
||||
metricsFeatureProvider.action(getContext(),
|
||||
metricsFeatureProvider.action(context,
|
||||
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
|
||||
askDisconnect();
|
||||
} else if (bondState == BluetoothDevice.BOND_BONDED) {
|
||||
metricsFeatureProvider.action(getContext(),
|
||||
metricsFeatureProvider.action(context,
|
||||
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT);
|
||||
mCachedDevice.connect(true);
|
||||
} else if (bondState == BluetoothDevice.BOND_NONE) {
|
||||
metricsFeatureProvider.action(getContext(),
|
||||
metricsFeatureProvider.action(context,
|
||||
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
|
||||
if (!mCachedDevice.hasHumanReadableName()) {
|
||||
metricsFeatureProvider.action(context,
|
||||
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
|
||||
}
|
||||
pair();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
maybeEnforceRestrictions();
|
||||
final boolean restricted = maybeEnforceRestrictions();
|
||||
|
||||
if (mLocalAdapter == null) {
|
||||
mSwitchWidget.setEnabled(false);
|
||||
@@ -114,7 +114,9 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
|
||||
}
|
||||
|
||||
// Bluetooth state is not sticky, so set it manually
|
||||
handleStateChanged(mLocalAdapter.getBluetoothState());
|
||||
if (!restricted) {
|
||||
handleStateChanged(mLocalAdapter.getBluetoothState());
|
||||
}
|
||||
|
||||
mSwitchWidget.startListening();
|
||||
mContext.registerReceiver(mReceiver, mIntentFilter);
|
||||
@@ -155,7 +157,9 @@ public final class BluetoothEnabler implements SwitchWidgetController.OnSwitchCh
|
||||
}
|
||||
|
||||
private void setChecked(boolean isChecked) {
|
||||
if (isChecked != mSwitchWidget.isChecked()) {
|
||||
final boolean currentState =
|
||||
(mSwitchWidget.getSwitch() != null) && mSwitchWidget.getSwitch().isChecked();
|
||||
if (isChecked != currentState) {
|
||||
// set listener to null, so onCheckedChanged won't be called
|
||||
// if the checked status on Switch isn't changed by user click
|
||||
if (mValidListener) {
|
||||
|
||||
@@ -22,14 +22,16 @@ import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
/**
|
||||
* Controller that shows received files
|
||||
*/
|
||||
public class BluetoothFilesPreferenceController extends PreferenceController {
|
||||
public class BluetoothFilesPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
private static final String TAG = "BluetoothFilesPrefCtrl";
|
||||
|
||||
public static final String KEY_RECEIVED_FILES = "bt_received_files";
|
||||
|
||||
@@ -25,21 +25,22 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.MasterSwitchController;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
public class BluetoothMasterSwitchPreferenceController extends PreferenceController
|
||||
implements OnSummaryChangeListener,
|
||||
LifecycleObserver, OnResume, OnPause, OnStart, OnStop {
|
||||
public class BluetoothMasterSwitchPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, OnSummaryChangeListener, LifecycleObserver, OnResume,
|
||||
OnPause, OnStart, OnStop {
|
||||
|
||||
public static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth";
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -184,8 +184,8 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context,
|
||||
getLifecycle());
|
||||
controllers.add(mDeviceNamePrefController);
|
||||
|
||||
@@ -108,12 +108,6 @@ public class BluetoothPairingDialog extends Activity {
|
||||
@VisibleForTesting
|
||||
void dismiss() {
|
||||
if (!isFinishing()) {
|
||||
BluetoothPairingDialogFragment bluetoothFragment =
|
||||
(BluetoothPairingDialogFragment) getFragmentManager()
|
||||
.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (bluetoothFragment != null) {
|
||||
bluetoothFragment.dismiss();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.InputFilter.LengthFilter;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -34,6 +35,7 @@ import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
@@ -185,6 +187,19 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return the text of the pin entry field - this exists primarily to help us
|
||||
* simulate having existing text when the dialog is recreated, for example after a screen
|
||||
* rotation.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
CharSequence getPairingViewText() {
|
||||
if (mPairingView != null) {
|
||||
return mPairingView.getText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dialog with UI elements that allow a user to provide input.
|
||||
*/
|
||||
@@ -196,7 +211,9 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i
|
||||
mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
|
||||
AlertDialog dialog = mBuilder.create();
|
||||
dialog.setOnShowListener(d -> {
|
||||
mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
if (TextUtils.isEmpty(getPairingViewText())) {
|
||||
mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
}
|
||||
if (mPairingView != null && mPairingView.requestFocus()) {
|
||||
InputMethodManager imm = (InputMethodManager)
|
||||
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
@@ -22,14 +22,16 @@ import android.support.v7.preference.Preference;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
|
||||
/**
|
||||
* Controller that shows and updates the bluetooth device name
|
||||
*/
|
||||
public class BluetoothPairingPreferenceController extends PreferenceController {
|
||||
public class BluetoothPairingPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
private static final String TAG = "BluetoothPairingPrefCtrl";
|
||||
|
||||
public static final String KEY_PAIRING = "pref_bt_pairing";
|
||||
@@ -74,7 +76,7 @@ public class BluetoothPairingPreferenceController extends PreferenceController {
|
||||
public Preference createBluetoothPairingPreference(int order) {
|
||||
mPreference = new Preference(mFragment.getPreferenceScreen().getContext());
|
||||
mPreference.setKey(KEY_PAIRING);
|
||||
mPreference.setIcon(R.drawable.ic_add);
|
||||
mPreference.setIcon(R.drawable.ic_menu_add);
|
||||
mPreference.setOrder(order);
|
||||
mPreference.setTitle(R.string.bluetooth_pairing_pref_title);
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
@@ -39,7 +39,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.LinkifyUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.location.ScanningSettings;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
@@ -60,9 +59,6 @@ import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
/**
|
||||
* BluetoothSettings is the Settings screen for Bluetooth configuration and
|
||||
@@ -144,6 +140,8 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
|
||||
mBluetoothEnabler.resume(getActivity());
|
||||
}
|
||||
super.onStart();
|
||||
// Always show paired devices regardless whether user-friendly name exists
|
||||
mShowDevicesWithoutNames = true;
|
||||
if (isUiRestricted()) {
|
||||
getPreferenceScreen().removeAll();
|
||||
if (!isUiRestrictedByOnlyAdmin()) {
|
||||
@@ -362,8 +360,8 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
final Lifecycle lifecycle = getLifecycle();
|
||||
mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context, lifecycle);
|
||||
mPairingPrefController = new BluetoothPairingPreferenceController(context, this,
|
||||
|
||||
@@ -42,31 +42,21 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
private final LocalBluetoothManager mBluetoothManager;
|
||||
private final LocalBluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
private boolean mEnabled;
|
||||
private int mConnectionState;
|
||||
|
||||
public BluetoothSummaryUpdater(Context context, OnSummaryChangeListener listener,
|
||||
LocalBluetoothManager bluetoothManager) {
|
||||
super(context, listener);
|
||||
mBluetoothManager = bluetoothManager;
|
||||
mBluetoothAdapter = mBluetoothManager != null
|
||||
? mBluetoothManager.getBluetoothAdapter() : null;
|
||||
? mBluetoothManager.getBluetoothAdapter() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
mEnabled = bluetoothState == BluetoothAdapter.STATE_ON
|
||||
|| bluetoothState == BluetoothAdapter.STATE_TURNING_ON;
|
||||
if (!mEnabled) {
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
}
|
||||
notifyChangeIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
mConnectionState = state;
|
||||
updateConnected();
|
||||
notifyChangeIfNeeded();
|
||||
}
|
||||
|
||||
@@ -92,8 +82,6 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
return;
|
||||
}
|
||||
if (listening) {
|
||||
mEnabled = mBluetoothAdapter.isEnabled();
|
||||
mConnectionState = mBluetoothAdapter.getConnectionState();
|
||||
notifyChangeIfNeeded();
|
||||
mBluetoothManager.getEventManager().registerCallback(this);
|
||||
} else {
|
||||
@@ -103,10 +91,10 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
if (!mEnabled) {
|
||||
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
|
||||
return mContext.getString(R.string.bluetooth_disabled);
|
||||
}
|
||||
switch (mConnectionState) {
|
||||
switch (mBluetoothAdapter.getConnectionState()) {
|
||||
case BluetoothAdapter.STATE_CONNECTED:
|
||||
return getConnectedDeviceSummary();
|
||||
case BluetoothAdapter.STATE_CONNECTING:
|
||||
@@ -118,50 +106,17 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConnected() {
|
||||
if (mBluetoothAdapter == null) {
|
||||
return;
|
||||
}
|
||||
// Make sure our connection state is up to date.
|
||||
int state = mBluetoothAdapter.getConnectionState();
|
||||
if (state != mConnectionState) {
|
||||
mConnectionState = state;
|
||||
return;
|
||||
}
|
||||
final Collection<CachedBluetoothDevice> devices = getDevices();
|
||||
if (devices == null) {
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
if (mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
|
||||
CachedBluetoothDevice connectedDevice = null;
|
||||
for (CachedBluetoothDevice device : devices) {
|
||||
if (device.isConnected()) {
|
||||
connectedDevice = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connectedDevice == null) {
|
||||
// If somehow we think we are connected, but have no connected devices, we
|
||||
// aren't connected.
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<CachedBluetoothDevice> getDevices() {
|
||||
return mBluetoothManager != null
|
||||
? mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
|
||||
: null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String getConnectedDeviceSummary() {
|
||||
String deviceName = null;
|
||||
int count = 0;
|
||||
final Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
|
||||
if (devices == null || devices.isEmpty()) {
|
||||
return null;
|
||||
if (devices == null) {
|
||||
Log.e(TAG, "getConnectedDeviceSummary, bonded devices are null");
|
||||
return mContext.getString(R.string.bluetooth_disabled);
|
||||
} else if (devices.isEmpty()) {
|
||||
Log.e(TAG, "getConnectedDeviceSummary, no bonded devices");
|
||||
return mContext.getString(R.string.disconnected);
|
||||
}
|
||||
for (BluetoothDevice device : devices) {
|
||||
if (device.isConnected()) {
|
||||
@@ -173,12 +128,13 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
}
|
||||
}
|
||||
if (deviceName == null) {
|
||||
Log.w(TAG, "getConnectedDeviceSummary, deviceName is null, numBondedDevices="
|
||||
Log.e(TAG, "getConnectedDeviceSummary, deviceName is null, numBondedDevices="
|
||||
+ devices.size());
|
||||
for (BluetoothDevice device : devices) {
|
||||
Log.w(TAG, "getConnectedDeviceSummary, device=" + device.getName() + "["
|
||||
Log.e(TAG, "getConnectedDeviceSummary, device=" + device.getName() + "["
|
||||
+ device.getAddress() + "]" + ", isConnected=" + device.isConnected());
|
||||
}
|
||||
return mContext.getString(R.string.disconnected);
|
||||
}
|
||||
return count > 1 ? mContext.getString(R.string.bluetooth_connected_multiple_devices_summary)
|
||||
: mContext.getString(R.string.bluetooth_connected_summary, deviceName);
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.bluetooth;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
@@ -52,6 +53,10 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
|
||||
private static final String KEY_BT_SCAN = "bt_scan";
|
||||
|
||||
// Copied from DevelopmentSettings.java
|
||||
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
|
||||
"persist.bluetooth.showdeviceswithoutnames";
|
||||
|
||||
private BluetoothDeviceFilter.Filter mFilter;
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -68,6 +73,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
final WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference> mDevicePreferenceMap =
|
||||
new WeakHashMap<CachedBluetoothDevice, BluetoothDevicePreference>();
|
||||
|
||||
boolean mShowDevicesWithoutNames;
|
||||
|
||||
DeviceListPreferenceFragment(String restrictedKey) {
|
||||
super(restrictedKey);
|
||||
mFilter = BluetoothDeviceFilter.ALL_FILTER;
|
||||
@@ -103,6 +110,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mShowDevicesWithoutNames = SystemProperties.getBoolean(
|
||||
BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
|
||||
if (mLocalManager == null || isUiRestricted()) return;
|
||||
|
||||
mLocalManager.setForegroundActivity(getActivity());
|
||||
@@ -181,7 +190,7 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
|
||||
|
||||
if (preference == null) {
|
||||
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice);
|
||||
preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice, this);
|
||||
preference.setKey(key);
|
||||
mDeviceListGroup.addPreference(preference);
|
||||
} else {
|
||||
@@ -271,4 +280,8 @@ public abstract class DeviceListPreferenceFragment extends
|
||||
* Return the key of the {@link PreferenceGroup} that contains the bluetooth devices
|
||||
*/
|
||||
public abstract String getDeviceListKey();
|
||||
|
||||
public boolean shouldShowDevicesWithoutNames() {
|
||||
return mShowDevicesWithoutNames;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.bluetooth;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothDevicePicker;
|
||||
@@ -29,10 +31,8 @@ import android.view.MenuInflater;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -170,7 +170,7 @@ public final class DevicePickerFragment extends DeviceListPreferenceFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@ import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Pair;
|
||||
import android.widget.Toast;
|
||||
@@ -36,6 +39,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
|
||||
import com.android.settingslib.bluetooth.Utils.ErrorListener;
|
||||
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -150,27 +154,39 @@ public final class Utils {
|
||||
}
|
||||
};
|
||||
|
||||
static Pair<Integer, String> getBtClassDrawableWithDescription(Resources r,
|
||||
static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
|
||||
CachedBluetoothDevice cachedDevice) {
|
||||
return getBtClassDrawableWithDescription(context, cachedDevice, 1 /* iconScale */);
|
||||
}
|
||||
|
||||
static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
|
||||
CachedBluetoothDevice cachedDevice, float iconScale) {
|
||||
BluetoothClass btClass = cachedDevice.getBtClass();
|
||||
final int level = cachedDevice.getBatteryLevel();
|
||||
if (btClass != null) {
|
||||
switch (btClass.getMajorDeviceClass()) {
|
||||
case BluetoothClass.Device.Major.COMPUTER:
|
||||
return new Pair<Integer, String>(R.drawable.ic_bt_laptop,
|
||||
r.getString(R.string.bluetooth_talkback_computer));
|
||||
return new Pair<>(getBluetoothDrawable(context, R.drawable.ic_bt_laptop, level,
|
||||
iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_computer));
|
||||
|
||||
case BluetoothClass.Device.Major.PHONE:
|
||||
return new Pair<Integer, String>(R.drawable.ic_bt_cellphone,
|
||||
r.getString(R.string.bluetooth_talkback_phone));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, R.drawable.ic_bt_cellphone, level,
|
||||
iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_phone));
|
||||
|
||||
case BluetoothClass.Device.Major.PERIPHERAL:
|
||||
return new Pair<Integer, String>(HidProfile.getHidClassDrawable(btClass),
|
||||
r.getString(
|
||||
R.string.bluetooth_talkback_input_peripheral));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, HidProfile.getHidClassDrawable(btClass),
|
||||
level, iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_input_peripheral));
|
||||
|
||||
case BluetoothClass.Device.Major.IMAGING:
|
||||
return new Pair<Integer, String>(R.drawable.ic_settings_print,
|
||||
r.getString(R.string.bluetooth_talkback_imaging));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, R.drawable.ic_settings_print, level,
|
||||
iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_imaging));
|
||||
|
||||
default:
|
||||
// unrecognized device class; continue
|
||||
@@ -181,20 +197,38 @@ public final class Utils {
|
||||
for (LocalBluetoothProfile profile : profiles) {
|
||||
int resId = profile.getDrawableResource(btClass);
|
||||
if (resId != 0) {
|
||||
return new Pair<Integer, String>(resId, null);
|
||||
return new Pair<>(getBluetoothDrawable(context, resId, level, iconScale), null);
|
||||
}
|
||||
}
|
||||
if (btClass != null) {
|
||||
if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
|
||||
return new Pair<Integer, String>(R.drawable.ic_bt_headset_hfp,
|
||||
r.getString(R.string.bluetooth_talkback_headset));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, R.drawable.ic_bt_headset_hfp, level,
|
||||
iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_headset));
|
||||
}
|
||||
if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
|
||||
return new Pair<Integer, String>(R.drawable.ic_bt_headphones_a2dp,
|
||||
r.getString(R.string.bluetooth_talkback_headphone));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, R.drawable.ic_bt_headphones_a2dp, level,
|
||||
iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_headphone));
|
||||
}
|
||||
}
|
||||
return new Pair<Integer, String>(R.drawable.ic_settings_bluetooth,
|
||||
r.getString(R.string.bluetooth_talkback_bluetooth));
|
||||
return new Pair<>(
|
||||
getBluetoothDrawable(context, R.drawable.ic_settings_bluetooth, level, iconScale),
|
||||
context.getString(R.string.bluetooth_talkback_bluetooth));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static Drawable getBluetoothDrawable(Context context, @DrawableRes int resId,
|
||||
int batteryLevel, float iconScale) {
|
||||
if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
|
||||
return BluetoothDeviceLayerDrawable.createLayerDrawable(context, resId, batteryLevel,
|
||||
iconScale);
|
||||
} else if (resId != 0) {
|
||||
return context.getDrawable(resId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,14 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
|
||||
import com.android.settings.bluetooth.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.deviceinfo.UsbBackend;
|
||||
import com.android.settings.nfc.NfcPreferenceController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -65,8 +66,8 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
final Lifecycle lifecycle = getLifecycle();
|
||||
final NfcPreferenceController nfcPreferenceController =
|
||||
new NfcPreferenceController(context);
|
||||
@@ -81,6 +82,12 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
(SettingsActivity) getActivity());
|
||||
lifecycle.addObserver(bluetoothPreferenceController);
|
||||
controllers.add(bluetoothPreferenceController);
|
||||
|
||||
SmsMirroringFeatureProvider smsMirroringFeatureProvider =
|
||||
FeatureFactory.getFactory(context).getSmsMirroringFeatureProvider();
|
||||
AbstractPreferenceController smsMirroringController =
|
||||
smsMirroringFeatureProvider.getController(context);
|
||||
controllers.add(smsMirroringController);
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -143,6 +150,13 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
keys.add(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
|
||||
}
|
||||
keys.add(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
|
||||
|
||||
SmsMirroringFeatureProvider smsMirroringFeatureProvider =
|
||||
FeatureFactory.getFactory(context).getSmsMirroringFeatureProvider();
|
||||
SmsMirroringPreferenceController smsMirroringController =
|
||||
smsMirroringFeatureProvider.getController(context);
|
||||
smsMirroringController.updateNonIndexableKeys(keys);
|
||||
|
||||
return keys;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.connecteddevice;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public interface SmsMirroringFeatureProvider {
|
||||
|
||||
/** Returns whether to show SMS mirroring. */
|
||||
boolean shouldShowSmsMirroring(Context context);
|
||||
|
||||
/** Returns a preference controller for SMS mirroring. */
|
||||
SmsMirroringPreferenceController getController(Context context);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.connecteddevice;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public class SmsMirroringFeatureProviderImpl implements SmsMirroringFeatureProvider {
|
||||
@Override
|
||||
public boolean shouldShowSmsMirroring(Context context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsMirroringPreferenceController getController(Context context) {
|
||||
return new SmsMirroringPreferenceController(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.connecteddevice;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
public class SmsMirroringPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
static final String KEY_SMS_MIRRORING = "sms_mirroring";
|
||||
|
||||
private SmsMirroringFeatureProvider mFeatureProvider;
|
||||
|
||||
public SmsMirroringPreferenceController(Context context) {
|
||||
super(context);
|
||||
mFeatureProvider = FeatureFactory.getFactory(context).getSmsMirroringFeatureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mFeatureProvider.shouldShowSmsMirroring(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_SMS_MIRRORING;
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,16 @@ import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.deviceinfo.UsbBackend;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
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 UsbModePreferenceController extends PreferenceController
|
||||
implements LifecycleObserver, OnResume, OnPause {
|
||||
public class UsbModePreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_USB_MODE = "usb_mode";
|
||||
|
||||
|
||||
@@ -20,12 +20,13 @@ import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
public abstract class DynamicAvailabilityPreferenceController extends PreferenceController
|
||||
implements LifecycleObserver, OnResume {
|
||||
public abstract class DynamicAvailabilityPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, LifecycleObserver, OnResume {
|
||||
|
||||
private Preference mPreference;
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
@@ -15,21 +15,28 @@
|
||||
*/
|
||||
package com.android.settings.core;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A controller that manages event for preference.
|
||||
* A controller mixin that adds mobile settings specific functionality
|
||||
*/
|
||||
public abstract class PreferenceController extends AbstractPreferenceController {
|
||||
public interface PreferenceControllerMixin {
|
||||
|
||||
public PreferenceController(Context context) {
|
||||
super(context);
|
||||
/**
|
||||
* Updates non-indexable keys for search provider.
|
||||
*
|
||||
* Called by SearchIndexProvider#getNonIndexableKeys
|
||||
*/
|
||||
default void updateNonIndexableKeys(List<String> keys) {
|
||||
if (this instanceof AbstractPreferenceController) {
|
||||
if (!((AbstractPreferenceController) this).isAvailable()) {
|
||||
keys.add(((AbstractPreferenceController) this).getPreferenceKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,13 +44,13 @@ public abstract class PreferenceController extends AbstractPreferenceController
|
||||
*
|
||||
* Called by SearchIndexProvider#getRawDataToIndex
|
||||
*/
|
||||
public void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
|
||||
default void updateRawDataToIndex(List<SearchIndexableRaw> rawData) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ResultPayload} corresponding to the search result type for the preference.
|
||||
*/
|
||||
public ResultPayload getResultPayload() {
|
||||
default ResultPayload getResultPayload() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class TouchOverlayManager {
|
||||
|
||||
private final Context mContext;
|
||||
private final IBinder mToken = new Binder();
|
||||
|
||||
public TouchOverlayManager(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void setOverlayAllowed(boolean allowed) {
|
||||
final AppOpsManager aom = mContext.getSystemService(AppOpsManager.class);
|
||||
if (aom != null) {
|
||||
aom.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
|
||||
aom.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import com.android.settings.Settings;
|
||||
import com.android.settings.TestingSettings;
|
||||
import com.android.settings.TetherSettings;
|
||||
import com.android.settings.TrustedCredentialsSettings;
|
||||
import com.android.settings.UserDictionarySettings;
|
||||
import com.android.settings.WifiCallingSettings;
|
||||
import com.android.settings.accessibility.AccessibilitySettings;
|
||||
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
|
||||
@@ -41,7 +40,7 @@ import com.android.settings.accounts.AccountSyncSettings;
|
||||
import com.android.settings.accounts.ChooseAccountActivity;
|
||||
import com.android.settings.accounts.ManagedProfileSettings;
|
||||
import com.android.settings.accounts.UserAndAccountDashboardFragment;
|
||||
import com.android.settings.applications.AdvancedAppSettings;
|
||||
import com.android.settings.applications.DefaultAppSettings;
|
||||
import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.DrawOverlayDetails;
|
||||
import com.android.settings.applications.ExternalSourcesDetails;
|
||||
@@ -53,6 +52,7 @@ import com.android.settings.applications.PictureInPictureDetails;
|
||||
import com.android.settings.applications.PictureInPictureSettings;
|
||||
import com.android.settings.applications.ProcessStatsSummary;
|
||||
import com.android.settings.applications.ProcessStatsUi;
|
||||
import com.android.settings.applications.SpecialAccessSettings;
|
||||
import com.android.settings.applications.UsageAccessDetails;
|
||||
import com.android.settings.applications.VrListenerSettings;
|
||||
import com.android.settings.applications.WriteSettingsDetails;
|
||||
@@ -61,6 +61,8 @@ import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
|
||||
import com.android.settings.bluetooth.BluetoothSettings;
|
||||
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
|
||||
import com.android.settings.dashboard.SupportFragment;
|
||||
import com.android.settings.datausage.DataPlanUsageSummary;
|
||||
import com.android.settings.datausage.DataUsageList;
|
||||
import com.android.settings.datausage.DataUsageSummary;
|
||||
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
|
||||
import com.android.settings.development.DevelopmentSettings;
|
||||
@@ -89,6 +91,7 @@ import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
|
||||
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
|
||||
import com.android.settings.inputmethod.SpellCheckersSettings;
|
||||
import com.android.settings.inputmethod.UserDictionaryList;
|
||||
import com.android.settings.inputmethod.UserDictionarySettings;
|
||||
import com.android.settings.language.LanguageAndInputSettings;
|
||||
import com.android.settings.localepicker.LocaleListEditor;
|
||||
import com.android.settings.location.LocationSettings;
|
||||
@@ -184,9 +187,11 @@ public class SettingsGateway {
|
||||
PickupGestureSettings.class.getName(),
|
||||
DoubleTwistGestureSettings.class.getName(),
|
||||
CryptKeeperSettings.class.getName(),
|
||||
DataPlanUsageSummary.class.getName(),
|
||||
DataUsageSummary.class.getName(),
|
||||
DreamSettings.class.getName(),
|
||||
UserSettings.class.getName(),
|
||||
SpecialAccessSettings.class.getName(),
|
||||
NotificationAccessSettings.class.getName(),
|
||||
ZenAccessSettings.class.getName(),
|
||||
PrintSettingsFragment.class.getName(),
|
||||
@@ -217,7 +222,7 @@ public class SettingsGateway {
|
||||
DrawOverlayDetails.class.getName(),
|
||||
WriteSettingsDetails.class.getName(),
|
||||
ExternalSourcesDetails.class.getName(),
|
||||
AdvancedAppSettings.class.getName(),
|
||||
DefaultAppSettings.class.getName(),
|
||||
WallpaperTypeSettings.class.getName(),
|
||||
VrListenerSettings.class.getName(),
|
||||
PictureInPictureSettings.class.getName(),
|
||||
@@ -247,10 +252,10 @@ public class SettingsGateway {
|
||||
WebViewAppPicker.class.getName(),
|
||||
LockscreenDashboardFragment.class.getName(),
|
||||
BluetoothDeviceDetailsFragment.class.getName(),
|
||||
DataUsageList.class.getName()
|
||||
};
|
||||
|
||||
public static final String[] SETTINGS_FOR_RESTRICTED = {
|
||||
// New IA
|
||||
// Home page
|
||||
Settings.NetworkDashboardActivity.class.getName(),
|
||||
Settings.ConnectedDeviceDashboardActivity.class.getName(),
|
||||
@@ -266,6 +271,7 @@ public class SettingsGateway {
|
||||
SupportDashboardActivity.class.getName(),
|
||||
// Home page > Network & Internet
|
||||
Settings.WifiSettingsActivity.class.getName(),
|
||||
Settings.DataPlanUsageSummaryActivity.class.getName(),
|
||||
Settings.DataUsageSummaryActivity.class.getName(),
|
||||
Settings.SimSettingsActivity.class.getName(),
|
||||
// Home page > Connected devices
|
||||
|
||||
@@ -120,19 +120,29 @@ public class SharedPreferencesLogger implements SharedPreferences {
|
||||
|
||||
final Pair<Integer, Object> valueData;
|
||||
if (value instanceof Long) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
|
||||
value);
|
||||
final Long longVal = (Long) value;
|
||||
final int intVal;
|
||||
if (longVal > Integer.MAX_VALUE) {
|
||||
intVal = Integer.MAX_VALUE;
|
||||
} else if (longVal < Integer.MIN_VALUE) {
|
||||
intVal = Integer.MIN_VALUE;
|
||||
} else {
|
||||
intVal = longVal.intValue();
|
||||
}
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
intVal);
|
||||
} else if (value instanceof Integer) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
|
||||
((Integer) value).longValue());
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
value);
|
||||
} else if (value instanceof Boolean) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
|
||||
(Boolean) value ? 1L : 0L);
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
(Boolean) value ? 1 : 0);
|
||||
} else if (value instanceof Float) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
|
||||
value);
|
||||
} else if (value instanceof String) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE, value);
|
||||
Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
|
||||
valueData = null;
|
||||
} else {
|
||||
Log.w(LOG_TAG, "Tried to log unloggable object" + value);
|
||||
valueData = null;
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -47,6 +48,7 @@ import com.android.settings.dashboard.conditional.ConditionAdapter;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionAdapter;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionDismissController;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionLogHelper;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
@@ -111,7 +113,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
List<Condition> conditions, SuggestionParser suggestionParser,
|
||||
SuggestionDismissController.Callback callback) {
|
||||
List<Tile> suggestions = null;
|
||||
List<DashboardCategory> categories = null;
|
||||
DashboardCategory category = null;
|
||||
int suggestionConditionMode = DashboardData.HEADER_MODE_DEFAULT;
|
||||
|
||||
mContext = context;
|
||||
@@ -127,9 +129,9 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
suggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
|
||||
categories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
|
||||
category = savedInstanceState.getParcelable(STATE_CATEGORY_LIST);
|
||||
suggestionConditionMode = savedInstanceState.getInt(
|
||||
STATE_SUGGESTION_CONDITION_MODE, suggestionConditionMode);
|
||||
STATE_SUGGESTION_CONDITION_MODE, suggestionConditionMode);
|
||||
mSuggestionsShownLogged = savedInstanceState.getStringArrayList(
|
||||
STATE_SUGGESTIONS_SHOWN_LOGGED);
|
||||
} else {
|
||||
@@ -139,7 +141,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
mDashboardData = new DashboardData.Builder()
|
||||
.setConditions(conditions)
|
||||
.setSuggestions(suggestions)
|
||||
.setCategories(categories)
|
||||
.setCategory(category)
|
||||
.setSuggestionConditionMode(suggestionConditionMode)
|
||||
.build();
|
||||
}
|
||||
@@ -148,37 +150,15 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
return mDashboardData.getSuggestions();
|
||||
}
|
||||
|
||||
public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
|
||||
public void setCategoriesAndSuggestions(DashboardCategory category,
|
||||
List<Tile> suggestions) {
|
||||
if (mDashboardFeatureProvider.shouldTintIcon()) {
|
||||
// TODO: Better place for tinting?
|
||||
final TypedArray a = mContext.obtainStyledAttributes(new int[]{
|
||||
android.R.attr.colorControlNormal});
|
||||
final int tintColor = a.getColor(0, mContext.getColor(R.color.fallback_tintColor));
|
||||
a.recycle();
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
for (int j = 0; j < categories.get(i).tiles.size(); j++) {
|
||||
final Tile tile = categories.get(i).tiles.get(j);
|
||||
|
||||
if (tile.isIconTintable) {
|
||||
// If this drawable is tintable, tint it to match the color.
|
||||
tile.icon.setTint(tintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Tile suggestion : suggestions) {
|
||||
if (suggestion.isIconTintable) {
|
||||
suggestion.icon.setTint(tintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
tintIcons(category, suggestions);
|
||||
|
||||
final DashboardData prevData = mDashboardData;
|
||||
mDashboardData = new DashboardData.Builder(prevData)
|
||||
.setSuggestions(suggestions.subList(0,
|
||||
Math.min(suggestions.size(), MAX_SUGGESTION_TO_SHOW)))
|
||||
.setCategories(categories)
|
||||
.setCategory(category)
|
||||
.build();
|
||||
notifyDashboardDataChanged(prevData);
|
||||
List<Tile> shownSuggestions = null;
|
||||
@@ -194,17 +174,19 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
final String identifier = mSuggestionFeatureProvider.getSuggestionIdentifier(
|
||||
mContext, suggestion);
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, identifier);
|
||||
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, identifier,
|
||||
getSuggestionTaggedData());
|
||||
mSuggestionsShownLogged.add(identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCategory(List<DashboardCategory> category) {
|
||||
public void setCategory(DashboardCategory category) {
|
||||
tintIcons(category, null);
|
||||
final DashboardData prevData = mDashboardData;
|
||||
Log.d(TAG, "adapter setCategory called");
|
||||
mDashboardData = new DashboardData.Builder(prevData)
|
||||
.setCategories(category)
|
||||
.setCategory(category)
|
||||
.build();
|
||||
notifyDashboardDataChanged(prevData);
|
||||
}
|
||||
@@ -262,10 +244,6 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
public void onBindViewHolder(DashboardItemHolder holder, int position) {
|
||||
final int type = mDashboardData.getItemTypeByPosition(position);
|
||||
switch (type) {
|
||||
case R.layout.dashboard_category:
|
||||
onBindCategory(holder,
|
||||
(DashboardCategory) mDashboardData.getItemEntityByPosition(position));
|
||||
break;
|
||||
case R.layout.dashboard_tile:
|
||||
final Tile tile = (Tile) mDashboardData.getItemEntityByPosition(position);
|
||||
onBindTile(holder, tile);
|
||||
@@ -274,7 +252,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
break;
|
||||
case R.layout.suggestion_condition_container:
|
||||
onBindConditionAndSuggestion(
|
||||
(SuggestionAndConditionContainerHolder) holder, position);
|
||||
(SuggestionAndConditionContainerHolder) holder, position);
|
||||
break;
|
||||
case R.layout.suggestion_condition_header:
|
||||
onBindSuggestionConditionHeader((SuggestionAndConditionHeaderHolder) holder,
|
||||
@@ -287,7 +265,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, false);
|
||||
DashboardData prevData = mDashboardData;
|
||||
mDashboardData = new DashboardData.Builder(prevData).setSuggestionConditionMode(
|
||||
DashboardData.HEADER_MODE_COLLAPSED).build();
|
||||
DashboardData.HEADER_MODE_COLLAPSED).build();
|
||||
notifyDashboardDataChanged(prevData);
|
||||
mRecyclerView.scrollToPosition(SUGGESTION_CONDITION_HEADER_POSITION);
|
||||
});
|
||||
@@ -327,7 +305,8 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
mContext, suggestion);
|
||||
if (mSuggestionsShownLogged.contains(suggestionId)) {
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, suggestionId);
|
||||
mContext, MetricsEvent.ACTION_HIDE_SETTINGS_SUGGESTION, suggestionId,
|
||||
getSuggestionTaggedData());
|
||||
}
|
||||
}
|
||||
mSuggestionsShownLogged.clear();
|
||||
@@ -354,13 +333,17 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
}
|
||||
|
||||
private void logSuggestions() {
|
||||
for (Tile suggestion : mDashboardData.getSuggestions()) {
|
||||
final List<Tile> suggestions = mDashboardData.getSuggestions();
|
||||
if (suggestions == null) {
|
||||
return;
|
||||
}
|
||||
for (Tile suggestion : suggestions) {
|
||||
final String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier(
|
||||
mContext, suggestion);
|
||||
mContext, suggestion);
|
||||
if (!mSuggestionsShownLogged.contains(suggestionId)) {
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION,
|
||||
suggestionId);
|
||||
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, suggestionId,
|
||||
getSuggestionTaggedData());
|
||||
mSuggestionsShownLogged.add(suggestionId);
|
||||
}
|
||||
}
|
||||
@@ -371,9 +354,9 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
SuggestionConditionHeaderData data) {
|
||||
final int curMode = mDashboardData.getSuggestionConditionMode();
|
||||
final int nextMode = data.hiddenSuggestionCount > 0 && data.conditionCount > 0
|
||||
&& curMode != DashboardData.HEADER_MODE_SUGGESTION_EXPANDED
|
||||
? DashboardData.HEADER_MODE_SUGGESTION_EXPANDED
|
||||
: DashboardData.HEADER_MODE_FULLY_EXPANDED;
|
||||
&& curMode != DashboardData.HEADER_MODE_SUGGESTION_EXPANDED
|
||||
? DashboardData.HEADER_MODE_SUGGESTION_EXPANDED
|
||||
: DashboardData.HEADER_MODE_FULLY_EXPANDED;
|
||||
final boolean moreSuggestions = data.hiddenSuggestionCount > 0;
|
||||
final boolean hasConditions = data.conditionCount > 0;
|
||||
if (data.conditionCount > 0) {
|
||||
@@ -398,22 +381,22 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
if (curMode == DashboardData.HEADER_MODE_COLLAPSED) {
|
||||
if (data.conditionCount > 0) {
|
||||
holder.summary.setText(mContext.getResources().getQuantityString(
|
||||
R.plurals.suggestions_collapsed_summary,
|
||||
data.hiddenSuggestionCount, data.hiddenSuggestionCount));
|
||||
R.plurals.suggestions_collapsed_summary,
|
||||
data.hiddenSuggestionCount, data.hiddenSuggestionCount));
|
||||
} else {
|
||||
holder.title.setText(mContext.getResources().getQuantityString(
|
||||
R.plurals.suggestions_collapsed_title,
|
||||
data.hiddenSuggestionCount, data.hiddenSuggestionCount));
|
||||
R.plurals.suggestions_collapsed_title,
|
||||
data.hiddenSuggestionCount, data.hiddenSuggestionCount));
|
||||
holder.title.setTextColor(Color.BLACK);
|
||||
holder.summary.setText(null);
|
||||
}
|
||||
} else if (curMode == DashboardData.HEADER_MODE_DEFAULT) {
|
||||
if (data.conditionCount > 0) {
|
||||
holder.summary.setText(mContext.getString(
|
||||
R.string.suggestions_summary, data.hiddenSuggestionCount));
|
||||
R.string.suggestions_summary, data.hiddenSuggestionCount));
|
||||
} else {
|
||||
holder.title.setText(mContext.getString(
|
||||
R.string.suggestions_more_title, data.hiddenSuggestionCount));
|
||||
R.string.suggestions_more_title, data.hiddenSuggestionCount));
|
||||
holder.title.setTextColor(Color.BLACK);
|
||||
holder.summary.setText(null);
|
||||
}
|
||||
@@ -421,7 +404,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
} else if (data.conditionCount > 1) {
|
||||
holder.summary.setTextColor(Utils.getColorAccent(mContext));
|
||||
holder.summary.setText(
|
||||
mContext.getString(R.string.condition_summary, data.conditionCount));
|
||||
mContext.getString(R.string.condition_summary, data.conditionCount));
|
||||
} else {
|
||||
holder.summary.setText(null);
|
||||
}
|
||||
@@ -434,16 +417,16 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
holder.itemView.setPadding(0, padding, 0, padding);
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (moreSuggestions ) {
|
||||
if (moreSuggestions) {
|
||||
logSuggestions();
|
||||
} else if (hasConditions) {
|
||||
mMetricsFeatureProvider.action(mContext,
|
||||
MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true);
|
||||
MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true);
|
||||
}
|
||||
DashboardData prevData = mDashboardData;
|
||||
final boolean wasCollapsed = curMode == DashboardData.HEADER_MODE_COLLAPSED;
|
||||
mDashboardData = new DashboardData.Builder(prevData)
|
||||
.setSuggestionConditionMode(nextMode).build();
|
||||
.setSuggestionConditionMode(nextMode).build();
|
||||
notifyDashboardDataChanged(prevData);
|
||||
if (wasCollapsed) {
|
||||
mRecyclerView.scrollToPosition(SUGGESTION_CONDITION_HEADER_POSITION);
|
||||
@@ -460,13 +443,13 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
if (position == SUGGESTION_CONDITION_HEADER_POSITION
|
||||
&& suggestions != null && suggestions.size() > 0) {
|
||||
mSuggestionAdapter = new SuggestionAdapter(mContext, (List<Tile>)
|
||||
mDashboardData.getItemEntityByPosition(position), mSuggestionsShownLogged);
|
||||
mDashboardData.getItemEntityByPosition(position), mSuggestionsShownLogged);
|
||||
mSuggestionDismissHandler = new SuggestionDismissController(mContext,
|
||||
holder.data, mSuggestionParser, mCallback);
|
||||
holder.data, mSuggestionParser, mCallback);
|
||||
holder.data.setAdapter(mSuggestionAdapter);
|
||||
} else {
|
||||
ConditionAdapter adapter = new ConditionAdapter(mContext,
|
||||
(List<Condition>) mDashboardData.getItemEntityByPosition(position),
|
||||
(List<Condition>) mDashboardData.getItemEntityByPosition(position),
|
||||
mDashboardData.getSuggestionConditionMode());
|
||||
adapter.addDismissHandling(holder.data);
|
||||
holder.data.setAdapter(adapter);
|
||||
@@ -491,22 +474,44 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
}
|
||||
}
|
||||
|
||||
private void onBindCategory(DashboardItemHolder holder, DashboardCategory category) {
|
||||
holder.title.setText(category.title);
|
||||
private void tintIcons(DashboardCategory category, List<Tile> suggestions) {
|
||||
if (!mDashboardFeatureProvider.shouldTintIcon()) {
|
||||
return;
|
||||
}
|
||||
// TODO: Better place for tinting?
|
||||
final TypedArray a = mContext.obtainStyledAttributes(new int[]{
|
||||
android.R.attr.colorControlNormal});
|
||||
final int tintColor = a.getColor(0, mContext.getColor(R.color.fallback_tintColor));
|
||||
a.recycle();
|
||||
if (category != null) {
|
||||
for (Tile tile : category.tiles) {
|
||||
if (tile.isIconTintable) {
|
||||
// If this drawable is tintable, tint it to match the color.
|
||||
tile.icon.setTint(tintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (suggestions != null) {
|
||||
for (Tile suggestion : suggestions) {
|
||||
if (suggestion.isIconTintable) {
|
||||
suggestion.icon.setTint(tintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onSaveInstanceState(Bundle outState) {
|
||||
final List<Tile> suggestions = mDashboardData.getSuggestions();
|
||||
final List<DashboardCategory> categories = mDashboardData.getCategories();
|
||||
final DashboardCategory category = mDashboardData.getCategory();
|
||||
if (suggestions != null) {
|
||||
outState.putParcelableArrayList(STATE_SUGGESTION_LIST, new ArrayList<>(suggestions));
|
||||
}
|
||||
if (categories != null) {
|
||||
outState.putParcelableArrayList(STATE_CATEGORY_LIST, new ArrayList<>(categories));
|
||||
if (category != null) {
|
||||
outState.putParcelable(STATE_CATEGORY_LIST, category);
|
||||
}
|
||||
outState.putStringArrayList(STATE_SUGGESTIONS_SHOWN_LOGGED, mSuggestionsShownLogged);
|
||||
outState.putInt(STATE_SUGGESTION_CONDITION_MODE,
|
||||
mDashboardData.getSuggestionConditionMode());
|
||||
mDashboardData.getSuggestionConditionMode());
|
||||
}
|
||||
|
||||
private void updateConditionIcons(List<Icon> icons, ViewGroup parent) {
|
||||
@@ -518,13 +523,18 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
|
||||
parent.removeAllViews();
|
||||
for (int i = 1, size = icons.size(); i < size; i++) {
|
||||
ImageView icon = (ImageView) inflater.inflate(
|
||||
R.layout.condition_header_icon, parent, false);
|
||||
R.layout.condition_header_icon, parent, false);
|
||||
icon.setImageIcon(icons.get(i));
|
||||
parent.addView(icon);
|
||||
}
|
||||
parent.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private Pair<Integer, Object>[] getSuggestionTaggedData() {
|
||||
return SuggestionLogHelper.getSuggestionTaggedData(
|
||||
mSuggestionFeatureProvider.isSmartSuggestionEnabled(mContext));
|
||||
}
|
||||
|
||||
public static class IconCache {
|
||||
private final Context mContext;
|
||||
private final ArrayMap<Icon, Drawable> mMap = new ArrayMap<>();
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.settings.dashboard;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.util.DiffUtil;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -29,6 +30,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Description about data list used in the DashboardAdapter. In the data list each item can be
|
||||
@@ -41,34 +43,42 @@ public class DashboardData {
|
||||
public static final int HEADER_MODE_SUGGESTION_EXPANDED = 1;
|
||||
public static final int HEADER_MODE_FULLY_EXPANDED = 2;
|
||||
public static final int HEADER_MODE_COLLAPSED = 3;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({HEADER_MODE_DEFAULT, HEADER_MODE_SUGGESTION_EXPANDED, HEADER_MODE_FULLY_EXPANDED,
|
||||
HEADER_MODE_COLLAPSED})
|
||||
public @interface HeaderMode{}
|
||||
HEADER_MODE_COLLAPSED})
|
||||
public @interface HeaderMode {
|
||||
}
|
||||
|
||||
public static final int POSITION_NOT_FOUND = -1;
|
||||
public static final int DEFAULT_SUGGESTION_COUNT = 2;
|
||||
|
||||
// id namespace for different type of items.
|
||||
private static final int NS_SPACER = 0;
|
||||
private static final int NS_ITEMS = 2000;
|
||||
private static final int NS_SUGGESTION_CONDITION = 3000;
|
||||
// stable id for different type of items.
|
||||
@VisibleForTesting
|
||||
static final int STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER = 0;
|
||||
@VisibleForTesting
|
||||
static final int STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER = 1;
|
||||
@VisibleForTesting
|
||||
static final int STABLE_ID_SUGGESTION_CONDITION_FOOTER = 2;
|
||||
@VisibleForTesting
|
||||
static final int STABLE_ID_SUGGESTION_CONTAINER = 3;
|
||||
@VisibleForTesting
|
||||
static final int STABLE_ID_CONDITION_CONTAINER = 4;
|
||||
|
||||
private final List<Item> mItems;
|
||||
private final List<DashboardCategory> mCategories;
|
||||
private final DashboardCategory mCategory;
|
||||
private final List<Condition> mConditions;
|
||||
private final List<Tile> mSuggestions;
|
||||
private final @HeaderMode int mSuggestionConditionMode;
|
||||
private int mId;
|
||||
@HeaderMode
|
||||
private final int mSuggestionConditionMode;
|
||||
|
||||
private DashboardData(Builder builder) {
|
||||
mCategories = builder.mCategories;
|
||||
mCategory = builder.mCategory;
|
||||
mConditions = builder.mConditions;
|
||||
mSuggestions = builder.mSuggestions;
|
||||
mSuggestionConditionMode = builder.mSuggestionConditionMode;
|
||||
|
||||
mItems = new ArrayList<>();
|
||||
mId = 0;
|
||||
|
||||
buildItemsData();
|
||||
}
|
||||
@@ -102,8 +112,8 @@ public class DashboardData {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<DashboardCategory> getCategories() {
|
||||
return mCategories;
|
||||
public DashboardCategory getCategory() {
|
||||
return mCategory;
|
||||
}
|
||||
|
||||
public List<Condition> getConditions() {
|
||||
@@ -185,33 +195,18 @@ public class DashboardData {
|
||||
return suggestionSize;
|
||||
}
|
||||
|
||||
public boolean hasMoreSuggestions() {
|
||||
return mSuggestionConditionMode == HEADER_MODE_COLLAPSED && mSuggestions.size() > 0
|
||||
|| mSuggestionConditionMode == HEADER_MODE_DEFAULT
|
||||
&& mSuggestions.size() > DEFAULT_SUGGESTION_COUNT;
|
||||
}
|
||||
|
||||
private void resetCount() {
|
||||
mId = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the item and add it into list when {@paramref add} is true.
|
||||
* Add item into list when {@paramref add} is true.
|
||||
*
|
||||
* Note that {@link #mId} will increment automatically and the real
|
||||
* id stored in {@link Item} is shifted by {@paramref nameSpace}. This is a
|
||||
* simple way to keep the id stable.
|
||||
*
|
||||
* @param object maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
|
||||
* @param type type of the item, and value is the layout id
|
||||
* @param add flag about whether to add item into list
|
||||
* @param nameSpace namespace based on the type
|
||||
* @param item maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
|
||||
* @param type type of the item, and value is the layout id
|
||||
* @param stableId The stable id for this item
|
||||
* @param add flag about whether to add item into list
|
||||
*/
|
||||
private void countItem(Object object, int type, boolean add, int nameSpace) {
|
||||
private void addToItemList(Object item, int type, int stableId, boolean add) {
|
||||
if (add) {
|
||||
mItems.add(new Item(object, type, mId + nameSpace));
|
||||
mItems.add(new Item(item, type, stableId));
|
||||
}
|
||||
mId++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,55 +222,59 @@ public class DashboardData {
|
||||
final int hiddenSuggestion =
|
||||
hasSuggestions ? sizeOf(mSuggestions) - sizeOf(suggestions) : 0;
|
||||
|
||||
resetCount();
|
||||
/* Top suggestion/condition header. This will be present when there is any suggestion
|
||||
* and the mode is collapsed, or it only has conditions and the mode is not fully
|
||||
* expanded. */
|
||||
countItem(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
|
||||
R.layout.suggestion_condition_header,
|
||||
hasSuggestions && mSuggestionConditionMode == HEADER_MODE_COLLAPSED
|
||||
|| !hasSuggestions && hasConditions
|
||||
&& mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED,
|
||||
NS_SUGGESTION_CONDITION);
|
||||
final boolean hasSuggestionAndCollapsed = hasSuggestions
|
||||
&& mSuggestionConditionMode == HEADER_MODE_COLLAPSED;
|
||||
final boolean onlyHasConditionAndCollapsed = !hasSuggestions
|
||||
&& hasConditions
|
||||
&& mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED;
|
||||
|
||||
/* Suggestion container. This is the card view that contains the list of suggestions.
|
||||
* This will be added whenever the suggestion list is not empty */
|
||||
countItem(suggestions, R.layout.suggestion_condition_container, sizeOf(suggestions) > 0,
|
||||
NS_SUGGESTION_CONDITION);
|
||||
|
||||
/* Second suggestion/condition header. This will be added when there is at least one
|
||||
* suggestion or condition that is not currently displayed, and the user can expand the
|
||||
* section to view more items. */
|
||||
countItem(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
|
||||
/* Top suggestion/condition header. This will be present when there is any suggestion
|
||||
* and the mode is collapsed */
|
||||
addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
|
||||
R.layout.suggestion_condition_header,
|
||||
STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER, hasSuggestionAndCollapsed);
|
||||
|
||||
/* Use mid header if there is only condition & it's in collapsed mode */
|
||||
addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
|
||||
R.layout.suggestion_condition_header,
|
||||
STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER, onlyHasConditionAndCollapsed);
|
||||
|
||||
/* Suggestion container. This is the card view that contains the list of suggestions.
|
||||
* This will be added whenever the suggestion list is not empty */
|
||||
addToItemList(suggestions, R.layout.suggestion_condition_container,
|
||||
STABLE_ID_SUGGESTION_CONTAINER, sizeOf(suggestions) > 0);
|
||||
|
||||
/* Second suggestion/condition header. This will be added when there is at least one
|
||||
* suggestion or condition that is not currently displayed, and the user can expand the
|
||||
* section to view more items. */
|
||||
addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
|
||||
R.layout.suggestion_condition_header,
|
||||
STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER,
|
||||
mSuggestionConditionMode != HEADER_MODE_COLLAPSED
|
||||
&& mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED
|
||||
&& (hiddenSuggestion > 0
|
||||
|| hasConditions && hasSuggestions),
|
||||
NS_SUGGESTION_CONDITION);
|
||||
&& (hiddenSuggestion > 0 || hasConditions && hasSuggestions));
|
||||
|
||||
/* Condition container. This is the card view that contains the list of conditions.
|
||||
* This will be added whenever the condition list is not empty */
|
||||
countItem(conditions, R.layout.suggestion_condition_container,
|
||||
hasConditions && mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED,
|
||||
NS_SUGGESTION_CONDITION);
|
||||
addToItemList(conditions, R.layout.suggestion_condition_container,
|
||||
STABLE_ID_CONDITION_CONTAINER,
|
||||
hasConditions && mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED);
|
||||
|
||||
/* Suggestion/condition footer. This will be present when the section is fully expanded
|
||||
* or when there is no conditions and no hidden suggestions */
|
||||
countItem(null, R.layout.suggestion_condition_footer,
|
||||
(hasConditions || hasSuggestions) &&
|
||||
mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED
|
||||
|| hasSuggestions && !hasConditions && hiddenSuggestion == 0,
|
||||
NS_SUGGESTION_CONDITION);
|
||||
addToItemList(null /* item */, R.layout.suggestion_condition_footer,
|
||||
STABLE_ID_SUGGESTION_CONDITION_FOOTER,
|
||||
(hasConditions || hasSuggestions)
|
||||
&& mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED
|
||||
|| hasSuggestions
|
||||
&& !hasConditions
|
||||
&& hiddenSuggestion == 0);
|
||||
|
||||
resetCount();
|
||||
for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
|
||||
DashboardCategory category = mCategories.get(i);
|
||||
countItem(category, R.layout.dashboard_category,
|
||||
!TextUtils.isEmpty(category.title), NS_ITEMS);
|
||||
for (int j = 0; j < category.tiles.size(); j++) {
|
||||
Tile tile = category.tiles.get(j);
|
||||
countItem(tile, R.layout.dashboard_tile, true, NS_ITEMS);
|
||||
if(mCategory != null) {
|
||||
for (int j = 0; j < mCategory.tiles.size(); j++) {
|
||||
final Tile tile = mCategory.tiles.get(j);
|
||||
addToItemList(tile, R.layout.dashboard_tile, Objects.hash(tile.title),
|
||||
true /* add */);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,9 +315,10 @@ public class DashboardData {
|
||||
* {@link #mSuggestionConditionMode} have default value while others are not.
|
||||
*/
|
||||
public static class Builder {
|
||||
private @HeaderMode int mSuggestionConditionMode = HEADER_MODE_DEFAULT;
|
||||
@HeaderMode
|
||||
private int mSuggestionConditionMode = HEADER_MODE_DEFAULT;
|
||||
|
||||
private List<DashboardCategory> mCategories;
|
||||
private DashboardCategory mCategory;
|
||||
private List<Condition> mConditions;
|
||||
private List<Tile> mSuggestions;
|
||||
|
||||
@@ -326,14 +326,14 @@ public class DashboardData {
|
||||
}
|
||||
|
||||
public Builder(DashboardData dashboardData) {
|
||||
mCategories = dashboardData.mCategories;
|
||||
mCategory = dashboardData.mCategory;
|
||||
mConditions = dashboardData.mConditions;
|
||||
mSuggestions = dashboardData.mSuggestions;
|
||||
mSuggestionConditionMode = dashboardData.mSuggestionConditionMode;
|
||||
}
|
||||
|
||||
public Builder setCategories(List<DashboardCategory> categories) {
|
||||
this.mCategories = categories;
|
||||
public Builder setCategory(DashboardCategory category) {
|
||||
this.mCategory = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -395,27 +395,27 @@ public class DashboardData {
|
||||
/**
|
||||
* An item contains the data needed in the DashboardData.
|
||||
*/
|
||||
private static class Item {
|
||||
static class Item {
|
||||
// valid types in field type
|
||||
private static final int TYPE_DASHBOARD_CATEGORY = R.layout.dashboard_category;
|
||||
private static final int TYPE_DASHBOARD_TILE = R.layout.dashboard_tile;
|
||||
private static final int TYPE_SUGGESTION_CONDITION_CONTAINER =
|
||||
R.layout.suggestion_condition_container;
|
||||
R.layout.suggestion_condition_container;
|
||||
private static final int TYPE_SUGGESTION_CONDITION_HEADER =
|
||||
R.layout.suggestion_condition_header;
|
||||
R.layout.suggestion_condition_header;
|
||||
private static final int TYPE_SUGGESTION_CONDITION_FOOTER =
|
||||
R.layout.suggestion_condition_footer;
|
||||
private static final int TYPE_DASHBOARD_SPACER = R.layout.dashboard_spacer;
|
||||
|
||||
@IntDef({TYPE_DASHBOARD_CATEGORY, TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_CONDITION_CONTAINER,
|
||||
@IntDef({TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_CONDITION_CONTAINER,
|
||||
TYPE_SUGGESTION_CONDITION_HEADER, TYPE_SUGGESTION_CONDITION_FOOTER,
|
||||
TYPE_DASHBOARD_SPACER})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ItemTypes{}
|
||||
public @interface ItemTypes {
|
||||
}
|
||||
|
||||
/**
|
||||
* The main data object in item, usually is a {@link Tile}, {@link Condition} or
|
||||
* {@link DashboardCategory} object. This object can also be null when the
|
||||
* The main data object in item, usually is a {@link Tile}, {@link Condition}
|
||||
* object. This object can also be null when the
|
||||
* item is an divider line. Please refer to {@link #buildItemsData()} for
|
||||
* detail usage of the Item.
|
||||
*/
|
||||
@@ -424,7 +424,8 @@ public class DashboardData {
|
||||
/**
|
||||
* The type of item, value inside is the layout id(e.g. R.layout.dashboard_tile)
|
||||
*/
|
||||
public final @ItemTypes int type;
|
||||
@ItemTypes
|
||||
public final int type;
|
||||
|
||||
/**
|
||||
* Id of this item, used in the {@link ItemsDataDiffCallback} to identify the same item.
|
||||
@@ -439,6 +440,7 @@ public class DashboardData {
|
||||
|
||||
/**
|
||||
* Override it to make comparision in the {@link ItemsDataDiffCallback}
|
||||
*
|
||||
* @param obj object to compared with
|
||||
* @return true if the same object or has equal value.
|
||||
*/
|
||||
@@ -458,10 +460,6 @@ public class DashboardData {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TYPE_DASHBOARD_CATEGORY:
|
||||
// Only check title for dashboard category
|
||||
return TextUtils.equals(((DashboardCategory) entity).title,
|
||||
((DashboardCategory) targetItem.entity).title);
|
||||
case TYPE_DASHBOARD_TILE:
|
||||
final Tile localTile = (Tile) entity;
|
||||
final Tile targetTile = (Tile) targetItem.entity;
|
||||
@@ -469,6 +467,17 @@ public class DashboardData {
|
||||
// Only check title and summary for dashboard tile
|
||||
return TextUtils.equals(localTile.title, targetTile.title)
|
||||
&& TextUtils.equals(localTile.summary, targetTile.summary);
|
||||
case TYPE_SUGGESTION_CONDITION_CONTAINER:
|
||||
// If entity is suggestion and contains remote view, force refresh
|
||||
final List entities = (List) entity;
|
||||
if (!entities.isEmpty()) {
|
||||
Object firstEntity = entities.get(0);
|
||||
if (firstEntity instanceof Tile
|
||||
&& ((Tile) firstEntity).remoteViews != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Otherwise Fall through to default
|
||||
default:
|
||||
return entity == null ? targetItem.entity == null
|
||||
: entity.equals(targetItem.entity);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user