New dialog for ignore battery optimizations

Bug: 21375688
Change-Id: I7240cc0615044cf5a34349e5ffdf2ae2e0f6333f
This commit is contained in:
Jason Monk
2015-06-10 11:03:06 -04:00
parent da6a4904a9
commit 3a90d7cc69
5 changed files with 224 additions and 33 deletions

View File

@@ -944,6 +944,11 @@
<activity android:name="Settings$HighPowerApplicationsActivity" <activity android:name="Settings$HighPowerApplicationsActivity"
android:label="@string/high_power_apps" android:label="@string/high_power_apps"
android:taskAffinity=""> android:taskAffinity="">
<intent-filter android:priority="1">
<action android:name="android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS" <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.ManageApplications" /> android:value="com.android.settings.applications.ManageApplications" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<com.android.settings.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall">
<CheckedTextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
android:paddingStart="20dp"
android:paddingEnd="?android:attr/dialogPreferredPadding"
android:drawableStart="?android:attr/listChoiceIndicatorSingle"
android:ellipsize="marquee" />
<TextView android:id="@+android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:paddingStart="52dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
</com.android.settings.CheckableLinearLayout>

View File

@@ -0,0 +1,72 @@
/*
* 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.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.Checkable;
import android.widget.LinearLayout;
public class CheckableLinearLayout extends LinearLayout implements Checkable {
private boolean mChecked;
private float mDisabledAlpha;
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedValue alpha = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, alpha, true);
mDisabledAlpha = alpha.getFloat();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
final int N = getChildCount();
for (int i = 0; i < N; i++) {
getChildAt(i).setAlpha(enabled ? 1 : mDisabledAlpha);
}
}
@Override
public void setChecked(boolean checked) {
mChecked = checked;
updateChecked();
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
private void updateChecked() {
final int N = getChildCount();
for (int i = 0; i < N; i++) {
View child = getChildAt(i);
if (child instanceof Checkable) {
((Checkable) child).setChecked(mChecked);
}
}
}
}

View File

@@ -27,6 +27,7 @@ import android.os.Environment;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.preference.PreferenceFrameLayout; import android.preference.PreferenceFrameLayout;
import android.provider.Settings;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -239,6 +240,15 @@ public class ManageApplications extends InstrumentedFragment
mListType = LIST_TYPE_HIGH_POWER; mListType = LIST_TYPE_HIGH_POWER;
// Default to showing system. // Default to showing system.
mShowSystem = true; mShowSystem = true;
if (intent != null && Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
.equals(intent.getAction())) {
mCurrentPkgName = intent.getData().getSchemeSpecificPart();
if (mCurrentPkgName != null) {
mCurrentUid = mApplicationsState.getEntry(mCurrentPkgName,
UserHandle.myUserId()).info.uid;
startApplicationDetailsActivity();
}
}
} else { } else {
mListType = LIST_TYPE_MAIN; mListType = LIST_TYPE_MAIN;
} }
@@ -440,7 +450,7 @@ public class ManageApplications extends InstrumentedFragment
startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings); startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
break; break;
case LIST_TYPE_HIGH_POWER: case LIST_TYPE_HIGH_POWER:
startAppInfoFragment(HighPowerDetail.class, R.string.high_power_apps); HighPowerDetail.show(getActivity(), mCurrentPkgName);
break; break;
// TODO: Figure out if there is a way where we can spin up the profile's settings // 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. // process ahead of time, to avoid a long load of data when user clicks on a managed app.

View File

@@ -16,60 +16,85 @@
package com.android.settings.fuelgauge; package com.android.settings.fuelgauge;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.util.Pair;
import android.preference.Preference.OnPreferenceChangeListener; import android.util.SparseBooleanArray;
import android.preference.SwitchPreference; import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader; import com.android.settings.applications.AppInfoBase;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
public class HighPowerDetail extends AppInfoWithHeader implements OnPreferenceChangeListener { public class HighPowerDetail extends DialogFragment implements OnClickListener {
private static final String KEY_HIGH_POWER_SWITCH = "high_power_switch";
private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance(); private final PowerWhitelistBackend mBackend = PowerWhitelistBackend.getInstance();
private SwitchPreference mUsageSwitch; private String mPackageName;
private CharSequence mLabel;
private Adapter mAdapter;
private int mSelectedIndex;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.high_power_details); mPackageName = getArguments().getString(AppInfoBase.ARG_PACKAGE_NAME);
mUsageSwitch = (SwitchPreference) findPreference(KEY_HIGH_POWER_SWITCH); PackageManager pm = getContext().getPackageManager();
mUsageSwitch.setOnPreferenceChangeListener(this); try {
} mLabel = pm.getApplicationInfo(mPackageName, 0).loadLabel(pm);
} catch (NameNotFoundException e) {
@Override mLabel = mPackageName;
protected boolean refreshUi() { }
mUsageSwitch.setEnabled(!mBackend.isSysWhitelisted(mPackageName)); mAdapter = new Adapter(getContext(), R.layout.radio_with_summary);
mUsageSwitch.setChecked(mBackend.isWhitelisted(mPackageName)); mAdapter.add(new Pair<String, String>(getString(R.string.ignore_optimizations_on),
return true; getString(R.string.ignore_optimizations_on_desc)));
} mAdapter.add(new Pair<String, String>(getString(R.string.ignore_optimizations_off),
getString(R.string.ignore_optimizations_off_desc)));
@Override mSelectedIndex = mBackend.isWhitelisted(mPackageName) ? 0 : 1;
public boolean onPreferenceChange(Preference preference, Object newValue) { if (mBackend.isSysWhitelisted(mPackageName)) {
if (newValue == Boolean.TRUE) { mAdapter.setEnabled(1, false);
mBackend.addApp(mPackageName);
} else {
mBackend.removeApp(mPackageName);
} }
return true;
} }
@Override @Override
protected AlertDialog createDialog(int id, int errorCode) { public Dialog onCreateDialog(Bundle savedInstanceState) {
return null; AlertDialog.Builder b = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.ignore_optimizations_title, mLabel))
.setNegativeButton(R.string.cancel, null)
.setSingleChoiceItems(mAdapter, mSelectedIndex, this);
if (!mBackend.isSysWhitelisted(mPackageName)) {
b.setPositiveButton(R.string.done, this);
}
return b.create();
} }
@Override @Override
protected int getMetricsCategory() { public void onClick(DialogInterface dialog, int which) {
return MetricsLogger.FUELGAUGE_HIGH_POWER_DETAILS; if (which == DialogInterface.BUTTON_POSITIVE) {
boolean newValue = mSelectedIndex == 0;
boolean oldValue = mBackend.isWhitelisted(mPackageName);
if (newValue != oldValue) {
if (newValue) {
mBackend.addApp(mPackageName);
} else {
mBackend.removeApp(mPackageName);
}
}
} else {
mSelectedIndex = which;
}
} }
public static CharSequence getSummary(Context context, AppEntry entry) { public static CharSequence getSummary(Context context, AppEntry entry) {
@@ -81,4 +106,36 @@ public class HighPowerDetail extends AppInfoWithHeader implements OnPreferenceCh
? R.string.high_power_on : R.string.high_power_off); ? R.string.high_power_on : R.string.high_power_off);
} }
public static void show(Activity activity, String packageName) {
HighPowerDetail fragment = new HighPowerDetail();
Bundle args = new Bundle();
args.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
fragment.setArguments(args);
fragment.show(activity.getFragmentManager(), HighPowerDetail.class.getSimpleName());
}
private class Adapter extends ArrayAdapter<Pair<String, String>> {
private final SparseBooleanArray mEnabled = new SparseBooleanArray();
public Adapter(Context context, int resource) {
super(context, resource, android.R.id.title);
}
public void setEnabled(int index, boolean enabled) {
mEnabled.put(index, enabled);
}
public boolean isEnabled(int position) {
return mEnabled.get(position, true);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
((TextView) view.findViewById(android.R.id.title)).setText(getItem(position).first);
((TextView) view.findViewById(android.R.id.summary)).setText(getItem(position).second);
view.setEnabled(isEnabled(position));
return view;
}
}
} }