Fix bugs in auto restriction.

1. Dismiss this tip once user clicks it and goes to detail page.
2. In auto restriction, since apps are automatically restricted,
we need to remove apps in list that unrestricted by user.
3. Refactor the code to remove the unnecessary parameter(i.e.
SettingsActivity)

Bug: 78187414
Test: RunSettingsRoboTests
Change-Id: I1c950f7c55df35795641c2ea8579ce9e011dba28
This commit is contained in:
Lei Yu
2018-04-17 17:41:07 -07:00
parent 1257466d0b
commit 252d4e1fc0
14 changed files with 234 additions and 51 deletions

View File

@@ -43,7 +43,6 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
@VisibleForTesting
List<AppInfo> mAppInfos;
private AppOpsManager mAppOpsManager;
private SettingsActivity mSettingsActivity;
private InstrumentedPreferenceFragment mPreferenceFragment;
private UserManager mUserManager;
@@ -53,10 +52,8 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
mUserManager = context.getSystemService(UserManager.class);
}
public RestrictAppPreferenceController(SettingsActivity settingsActivity,
InstrumentedPreferenceFragment preferenceFragment) {
this(settingsActivity.getApplicationContext());
mSettingsActivity = settingsActivity;
public RestrictAppPreferenceController(InstrumentedPreferenceFragment preferenceFragment) {
this(preferenceFragment.getContext());
mPreferenceFragment = preferenceFragment;
}
@@ -83,7 +80,7 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
public boolean handlePreferenceTreeClick(Preference preference) {
if (getPreferenceKey().equals(preference.getKey())) {
// start fragment
RestrictedAppDetails.startRestrictedAppDetails(mSettingsActivity, mPreferenceFragment,
RestrictedAppDetails.startRestrictedAppDetails(mPreferenceFragment,
mAppInfos);
return true;
}

View File

@@ -67,12 +67,12 @@ public class RestrictedAppDetails extends DashboardFragment {
private final FooterPreferenceMixin mFooterPreferenceMixin =
new FooterPreferenceMixin(this, getLifecycle());
public static void startRestrictedAppDetails(SettingsActivity caller,
InstrumentedPreferenceFragment fragment, List<AppInfo> appInfos) {
public static void startRestrictedAppDetails(InstrumentedPreferenceFragment fragment,
List<AppInfo> appInfos) {
final Bundle args = new Bundle();
args.putParcelableList(EXTRA_APP_INFO_LIST, appInfos);
new SubSettingLauncher(caller)
new SubSettingLauncher(fragment.getContext())
.setDestination(RestrictedAppDetails.class.getName())
.setArguments(args)
.setTitle(R.string.restricted_app_title)

View File

@@ -71,7 +71,7 @@ public class SmartBatterySettings extends DashboardFragment {
controllers.add(new SmartBatteryPreferenceController(context));
if (settingsActivity != null && fragment != null) {
controllers.add(
new RestrictAppPreferenceController(settingsActivity, fragment));
new RestrictAppPreferenceController(fragment));
} else {
controllers.add(new RestrictAppPreferenceController(context));
}

View File

@@ -100,6 +100,7 @@ public class AnomalyDetectionJobService extends JobService {
.getFactory(this).getPowerUsageFeatureProvider(this);
final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory
.getFactory(this).getMetricsFeatureProvider();
batteryUtils.initBatteryStatsHelper(batteryStatsHelper, null /* bundle */, userManager);
for (JobWorkItem item = params.dequeueWork(); item != null;
item = params.dequeueWork()) {

View File

@@ -101,8 +101,7 @@ public class BatteryTipUtils {
}
case BatteryTip.TipType.APP_RESTRICTION:
if (batteryTip.getState() == BatteryTip.StateType.HANDLED) {
return new OpenRestrictAppFragmentAction(settingsActivity, fragment,
(RestrictAppTip) batteryTip);
return new OpenRestrictAppFragmentAction(fragment, (RestrictAppTip) batteryTip);
} else {
return new RestrictAppAction(settingsActivity, (RestrictAppTip) batteryTip);
}

View File

@@ -16,15 +16,16 @@
package com.android.settings.fuelgauge.batterytip.actions;
import android.app.Fragment;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.RestrictedAppDetails;
import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settingslib.utils.ThreadUtils;
import java.util.List;
@@ -33,17 +34,16 @@ import java.util.List;
*/
public class OpenRestrictAppFragmentAction extends BatteryTipAction {
private final RestrictAppTip mRestrictAppTip;
private final BatteryUtils mBatteryUtils;
private final SettingsActivity mSettingsActivity;
private final InstrumentedPreferenceFragment mFragment;
@VisibleForTesting
BatteryDatabaseManager mBatteryDatabaseManager;
public OpenRestrictAppFragmentAction(SettingsActivity settingsActivity,
InstrumentedPreferenceFragment fragment, RestrictAppTip tip) {
public OpenRestrictAppFragmentAction(InstrumentedPreferenceFragment fragment,
RestrictAppTip tip) {
super(fragment.getContext());
mSettingsActivity = settingsActivity;
mFragment = fragment;
mRestrictAppTip = tip;
mBatteryUtils = BatteryUtils.getInstance(mContext);
mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(mContext);
}
/**
@@ -54,7 +54,10 @@ public class OpenRestrictAppFragmentAction extends BatteryTipAction {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_TIP_OPEN_APP_RESTRICTION_PAGE, metricsKey);
final List<AppInfo> mAppInfos = mRestrictAppTip.getRestrictAppList();
RestrictedAppDetails.startRestrictedAppDetails(mSettingsActivity, mFragment,
mAppInfos);
RestrictedAppDetails.startRestrictedAppDetails(mFragment, mAppInfos);
// Mark all the anomalies as handled, so it won't show up again.
ThreadUtils.postOnBackgroundThread(() -> mBatteryDatabaseManager.updateAnomalies(mAppInfos,
AnomalyDatabaseHelper.State.HANDLED));
}
}

View File

@@ -20,18 +20,17 @@ import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.text.format.DateUtils;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
import com.android.settings.fuelgauge.batterytip.tips.AppInfoPredicate;
import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
* Detector whether to show summary tip. This detector should be executed as the last
@@ -45,13 +44,15 @@ public class RestrictAppDetector implements BatteryTipDetector {
BatteryDatabaseManager mBatteryDatabaseManager;
private Context mContext;
private AppInfoPredicate mAppInfoPredicate;
private AppRestrictionPredicate mAppRestrictionPredicate;
private AppLabelPredicate mAppLabelPredicate;
public RestrictAppDetector(Context context, BatteryTipPolicy policy) {
mContext = context;
mPolicy = policy;
mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
mAppInfoPredicate = new AppInfoPredicate(context);
mAppRestrictionPredicate = new AppRestrictionPredicate(context);
mAppLabelPredicate = new AppLabelPredicate(context);
}
@Override
@@ -64,7 +65,8 @@ public class RestrictAppDetector implements BatteryTipDetector {
final long oneDayBeforeMs = System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS;
final List<AppInfo> highUsageApps = mBatteryDatabaseManager.queryAllAnomalies(
oneDayBeforeMs, AnomalyDatabaseHelper.State.NEW);
highUsageApps.removeIf(mAppInfoPredicate);
// Remove it if it doesn't have label or been restricted
highUsageApps.removeIf(mAppLabelPredicate.or(mAppRestrictionPredicate));
if (!highUsageApps.isEmpty()) {
// If there are new anomalies, show them
return new RestrictAppTip(BatteryTip.StateType.NEW, highUsageApps);
@@ -72,7 +74,8 @@ public class RestrictAppDetector implements BatteryTipDetector {
// Otherwise, show auto-handled one if it exists
final List<AppInfo> autoHandledApps = mBatteryDatabaseManager.queryAllAnomalies(
oneDayBeforeMs, AnomalyDatabaseHelper.State.AUTO_HANDLED);
autoHandledApps.removeIf(mAppInfoPredicate);
// Remove it if it doesn't have label or unrestricted
autoHandledApps.removeIf(mAppLabelPredicate.or(mAppRestrictionPredicate.negate()));
return new RestrictAppTip(autoHandledApps.isEmpty() ? BatteryTip.StateType.INVISIBLE
: BatteryTip.StateType.HANDLED, autoHandledApps);
}

View File

@@ -25,22 +25,20 @@ import com.android.settings.fuelgauge.batterytip.AppInfo;
import java.util.function.Predicate;
/**
* {@link Predicate} for {@link AppInfo} to check whether it has label or restricted.
* {@link Predicate} for {@link AppInfo} to check whether it has label
*/
public class AppInfoPredicate implements Predicate<AppInfo> {
public class AppLabelPredicate implements Predicate<AppInfo> {
private Context mContext;
private AppOpsManager mAppOpsManager;
public AppInfoPredicate(Context context) {
public AppLabelPredicate(Context context) {
mContext = context;
mAppOpsManager = context.getSystemService(AppOpsManager.class);
}
@Override
public boolean test(AppInfo appInfo) {
// Return true if app doesn't have label or already been restricted
return Utils.getApplicationLabel(mContext, appInfo.packageName) == null
|| mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
appInfo.uid, appInfo.packageName) == AppOpsManager.MODE_IGNORED;
// Return true if app doesn't have label
return Utils.getApplicationLabel(mContext, appInfo.packageName) == null;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2018 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.fuelgauge.batterytip.tips;
import android.app.AppOpsManager;
import android.content.Context;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import java.util.function.Predicate;
/**
* {@link Predicate} for {@link AppInfo} to check whether it is restricted.
*/
public class AppRestrictionPredicate implements Predicate<AppInfo> {
private AppOpsManager mAppOpsManager;
public AppRestrictionPredicate(Context context) {
mAppOpsManager = context.getSystemService(AppOpsManager.class);
}
@Override
public boolean test(AppInfo appInfo) {
// Return true if app already been restricted
return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
appInfo.uid, appInfo.packageName) == AppOpsManager.MODE_IGNORED;
}
}