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.BatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
BatteryDatabaseManager mBatteryDatabaseManager;
private Context mContext;
- private Predicate<AppInfo> mAppInfoPredicate = new Predicate<AppInfo>() {
- @Override
- public boolean test(AppInfo appInfo) {
- return Utils.getApplicationLabel(mContext, appInfo.packageName) == null;
- }
- };
+ private AppInfoPredicate mAppInfoPredicate;
public RestrictAppDetector(Context context, BatteryTipPolicy policy) {
mContext = context;
mPolicy = policy;
mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
+ mAppInfoPredicate = new AppInfoPredicate(context);
}
@Override
--- /dev/null
+/*
+ * 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 has label or restricted.
+ */
+public class AppInfoPredicate implements Predicate<AppInfo> {
+ private Context mContext;
+ private AppOpsManager mAppOpsManager;
+
+ public AppInfoPredicate(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;
+ }
+}
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@RunWith(SettingsRobolectricTestRunner.class)
public class RestrictAppDetectorTest {
+ private static final int RESTRICTED_UID = 222;
private static final String PACKAGE_NAME = "com.android.app";
private static final String UNINSTALLED_PACKAGE_NAME = "com.android.uninstalled";
+ private static final String RESTRICTED_PACKAGE_NAME = "com.android.restricted";
private Context mContext;
private BatteryTipPolicy mPolicy;
private RestrictAppDetector mRestrictAppDetector;
private PackageManager mPackageManager;
@Mock
private ApplicationInfo mApplicationInfo;
+ @Mock
+ private AppOpsManager mAppOpsManager;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
mContext = spy(RuntimeEnvironment.application);
mPolicy = spy(new BatteryTipPolicy(mContext));
- mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
- mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+
+ doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
+ doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(
+ AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, RESTRICTED_UID, RESTRICTED_PACKAGE_NAME);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(eq(PACKAGE_NAME),
doReturn(PACKAGE_NAME).when(mApplicationInfo).loadLabel(any());
doThrow(new PackageManager.NameNotFoundException()).when(
mPackageManager).getApplicationInfo(eq(UNINSTALLED_PACKAGE_NAME), anyInt());
+
+ mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
+ mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+
}
@After
}
@Test
+ public void testDetect_hasRestrictedAnomaly_removeIt() throws
+ PackageManager.NameNotFoundException {
+ mAppInfoList.add(new AppInfo.Builder()
+ .setUid(RESTRICTED_UID)
+ .setPackageName(RESTRICTED_PACKAGE_NAME)
+ .build());
+ doReturn(mAppInfoList).when(mBatteryDatabaseManager)
+ .queryAllAnomalies(anyLong(), eq(AnomalyDatabaseHelper.State.NEW));
+ doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(
+ eq(RESTRICTED_PACKAGE_NAME), anyInt());
+
+ final RestrictAppTip restrictAppTip = (RestrictAppTip) mRestrictAppDetector.detect();
+ assertThat(restrictAppTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
+ assertThat(restrictAppTip.getRestrictAppList()).containsExactly(mAppInfo);
+ }
+
+ @Test
public void testDetect_noAnomaly_tipInvisible() {
doReturn(new ArrayList<AppInfo>()).when(mBatteryDatabaseManager)
.queryAllAnomalies(anyLong(), anyInt());