Use taskRootPackageName instead of packageName to load uid when usage
resource is USAGE_SOURCE_TASK_ROOT_ACTIVITY and taskRootPackageName is not empty. This logic is consistent with digital wellbeing: assign the screen-on time onto task root activity when usage resource is USAGE_SOURCE_TASK_ROOT_ACTIVITY. Bug: 260964679 Test: make RunSettingsRoboTests + manual Change-Id: I4c7ed342d8c00951879f5826bf79575f330ce86e
This commit is contained in:
@@ -17,7 +17,9 @@ package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.app.usage.UsageEvents.Event;
|
||||
import android.app.usage.UsageStatsManager;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -25,7 +27,9 @@ import android.database.Cursor;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.Build;
|
||||
import android.os.LocaleList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
@@ -167,8 +171,10 @@ public final class ConvertUtils {
|
||||
/** Converts to {@link AppUsageEvent} from {@link Event} */
|
||||
@Nullable
|
||||
public static AppUsageEvent convertToAppUsageEvent(
|
||||
Context context, final Event event, final long userId) {
|
||||
if (event.getPackageName() == null) {
|
||||
Context context, final IUsageStatsManager usageStatsManager, final Event event,
|
||||
final long userId) {
|
||||
final String packageName = event.getPackageName();
|
||||
if (packageName == null) {
|
||||
// See b/190609174: Event package names should never be null, but sometimes they are.
|
||||
// Note that system events like device shutting down should still come with the android
|
||||
// package name.
|
||||
@@ -182,13 +188,20 @@ public final class ConvertUtils {
|
||||
appUsageEventBuilder
|
||||
.setTimestamp(event.getTimeStamp())
|
||||
.setType(getAppUsageEventType(event.getEventType()))
|
||||
.setPackageName(event.getPackageName())
|
||||
.setPackageName(packageName)
|
||||
.setUserId(userId);
|
||||
|
||||
final String taskRootPackageName = getTaskRootPackageName(event);
|
||||
if (taskRootPackageName != null) {
|
||||
appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
|
||||
}
|
||||
|
||||
final String effectivePackageName =
|
||||
getEffectivePackageName(usageStatsManager, packageName, taskRootPackageName);
|
||||
try {
|
||||
final long uid = context
|
||||
.getPackageManager()
|
||||
.getPackageUidAsUser(event.getPackageName(), (int) userId);
|
||||
.getPackageUidAsUser(effectivePackageName, (int) userId);
|
||||
appUsageEventBuilder.setUid(uid);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, String.format(
|
||||
@@ -201,10 +214,6 @@ public final class ConvertUtils {
|
||||
} catch (NoClassDefFoundError | NoSuchMethodError e) {
|
||||
Log.w(TAG, "UsageEvent instance ID API error");
|
||||
}
|
||||
String taskRootPackageName = getTaskRootPackageName(event);
|
||||
if (taskRootPackageName != null) {
|
||||
appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
|
||||
}
|
||||
|
||||
return appUsageEventBuilder.build();
|
||||
}
|
||||
@@ -267,6 +276,35 @@ public final class ConvertUtils {
|
||||
: Locale.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the package name the app usage should be attributed to.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
|
||||
* UsageStatsManager#USAGE_SOURCE_CURRENT_ACTIVITY}, this method will return packageName.
|
||||
* <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
|
||||
* UsageStatsManager#USAGE_SOURCE_TASK_ROOT_ACTIVITY}, this method will return
|
||||
* taskRootPackageName if it exists, or packageName otherwise.
|
||||
* </ul>
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static String getEffectivePackageName(
|
||||
final IUsageStatsManager usageStatsManager, final String packageName,
|
||||
final String taskRootPackageName) {
|
||||
int usageSource = getUsageSource(usageStatsManager);
|
||||
switch (usageSource) {
|
||||
case UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY:
|
||||
return !TextUtils.isEmpty(taskRootPackageName)
|
||||
? taskRootPackageName
|
||||
: packageName;
|
||||
case UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY:
|
||||
return packageName;
|
||||
default:
|
||||
Log.e(TAG, "Unexpected usage source: " + usageSource);
|
||||
return packageName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the package name of the task root when this event was reported when {@code event} is
|
||||
* one of:
|
||||
@@ -298,6 +336,20 @@ public final class ConvertUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns what App Usage Observers will consider the source of usage for an activity.
|
||||
*
|
||||
* @see UsageStatsManager#getUsageSource()
|
||||
*/
|
||||
private static int getUsageSource(final IUsageStatsManager usageStatsManager) {
|
||||
try {
|
||||
return usageStatsManager.getUsageSource();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to getUsageSource", e);
|
||||
return UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
|
||||
}
|
||||
}
|
||||
|
||||
private static AppUsageEventType getAppUsageEventType(final int eventType) {
|
||||
switch (eventType) {
|
||||
case Event.ACTIVITY_RESUMED:
|
||||
|
@@ -256,7 +256,8 @@ public final class DataProcessor {
|
||||
break;
|
||||
}
|
||||
final AppUsageEvent appUsageEvent =
|
||||
ConvertUtils.convertToAppUsageEvent(context, event, userId);
|
||||
ConvertUtils.convertToAppUsageEvent(
|
||||
context, sUsageStatsManager, event, userId);
|
||||
if (appUsageEvent != null) {
|
||||
numEventsFetched++;
|
||||
appUsageEventList.add(appUsageEvent);
|
||||
|
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
|
||||
import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -22,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.app.usage.UsageEvents.Event;
|
||||
import android.content.ContentValues;
|
||||
@@ -31,6 +35,7 @@ import android.database.MatrixCursor;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.BatteryUsageStats;
|
||||
import android.os.LocaleList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
|
||||
@@ -56,6 +61,8 @@ public final class ConvertUtilsTest {
|
||||
@Mock
|
||||
private BatteryUsageStats mBatteryUsageStats;
|
||||
@Mock
|
||||
private IUsageStatsManager mUsageStatsManager;
|
||||
@Mock
|
||||
private BatteryEntry mMockBatteryEntry;
|
||||
|
||||
@Before
|
||||
@@ -278,7 +285,7 @@ public final class ConvertUtilsTest {
|
||||
|
||||
final long userId = 2;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, event, userId);
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
|
||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||
@@ -299,7 +306,7 @@ public final class ConvertUtilsTest {
|
||||
|
||||
final long userId = 1;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, event, userId);
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
|
||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||
@@ -315,7 +322,7 @@ public final class ConvertUtilsTest {
|
||||
event.mPackage = null;
|
||||
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, event, /*userId=*/ 0);
|
||||
mContext, mUsageStatsManager, event, /*userId=*/ 0);
|
||||
|
||||
assertThat(appUsageEvent).isNull();
|
||||
}
|
||||
@@ -331,7 +338,7 @@ public final class ConvertUtilsTest {
|
||||
|
||||
final long userId = 1;
|
||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||
mContext, event, userId);
|
||||
mContext, mUsageStatsManager, event, userId);
|
||||
|
||||
assertThat(appUsageEvent).isNull();
|
||||
}
|
||||
@@ -415,4 +422,53 @@ public final class ConvertUtilsTest {
|
||||
mContext.getResources().getConfiguration().setLocales(new LocaleList());
|
||||
assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_currentActivity_returnPackageName() throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_CURRENT_ACTIVITY);
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_usageSourceThrowException_returnPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_rootActivity_returnTaskRootPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
final String packageName = "com.android.settings1";
|
||||
final String taskRootPackageName = "com.android.settings2";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, taskRootPackageName))
|
||||
.isEqualTo(taskRootPackageName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName()
|
||||
throws RemoteException {
|
||||
when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
|
||||
final String packageName = "com.android.settings1";
|
||||
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, /*taskRootPackageName=*/ null))
|
||||
.isEqualTo(packageName);
|
||||
assertThat(ConvertUtils.getEffectivePackageName(
|
||||
mUsageStatsManager, packageName, /*taskRootPackageName=*/ ""))
|
||||
.isEqualTo(packageName);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user