import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.os.BatteryManager;
+import android.content.pm.ResolveInfo;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Build;
import android.support.annotation.StringRes;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.SparseLongArray;
return true;
}
- return isSystemUid(uid) || isSystemApp(mPackageManager, packageNames)
- || powerWhitelistBackend.isSysWhitelistedExceptIdle(packageNames);
+ return isSystemUid(uid) || powerWhitelistBackend.isSysWhitelistedExceptIdle(packageNames)
+ || (isSystemApp(mPackageManager, packageNames) && !hasLauncherEntry(packageNames));
}
private boolean isSystemUid(int uid) {
return false;
}
+
+ private boolean hasLauncherEntry(String[] packageNames) {
+ final Intent launchIntent = new Intent(Intent.ACTION_MAIN, null);
+ launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ // If we do not specify MATCH_DIRECT_BOOT_AWARE or
+ // MATCH_DIRECT_BOOT_UNAWARE, system will derive and update the flags
+ // according to the user's lock state. When the user is locked,
+ // components
+ // with ComponentInfo#directBootAware == false will be filtered. We should
+ // explicitly include both direct boot aware and unaware components here.
+ final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(launchIntent,
+ PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_SYSTEM_ONLY);
+ for (int i = 0, size = resolveInfos.size(); i < size; i++) {
+ final ResolveInfo resolveInfo = resolveInfos.get(i);
+ if (ArrayUtils.contains(packageNames, resolveInfo.activityInfo.packageName)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Bundle;
}
@Test
- public void testShouldHideAnomaly_systemApp_returnTrue() {
+ public void testShouldHideAnomaly_systemAppWithLauncher_returnTrue() {
+ final List<ResolveInfo> resolveInfos = new ArrayList<>();
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = new ActivityInfo();
+ resolveInfo.activityInfo.packageName = HIGH_SDK_PACKAGE;
+
+ doReturn(resolveInfos).when(mPackageManager).queryIntentActivities(any(), anyInt());
+ doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
+ mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+ assertThat(mBatteryUtils.shouldHideAnomaly(mPowerWhitelistBackend, UID)).isTrue();
+ }
+
+ @Test
+ public void testShouldHideAnomaly_systemAppWithoutLauncher_returnTrue() {
+ doReturn(new ArrayList<>()).when(mPackageManager).queryIntentActivities(any(), anyInt());
doReturn(new String[]{HIGH_SDK_PACKAGE}).when(mPackageManager).getPackagesForUid(UID);
mHighApplicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;