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.IntDef;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.app.usage.IUsageStatsManager;
|
||||||
import android.app.usage.UsageEvents.Event;
|
import android.app.usage.UsageEvents.Event;
|
||||||
|
import android.app.usage.UsageStatsManager;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -25,7 +27,9 @@ import android.database.Cursor;
|
|||||||
import android.os.BatteryUsageStats;
|
import android.os.BatteryUsageStats;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -167,8 +171,10 @@ public final class ConvertUtils {
|
|||||||
/** Converts to {@link AppUsageEvent} from {@link Event} */
|
/** Converts to {@link AppUsageEvent} from {@link Event} */
|
||||||
@Nullable
|
@Nullable
|
||||||
public static AppUsageEvent convertToAppUsageEvent(
|
public static AppUsageEvent convertToAppUsageEvent(
|
||||||
Context context, final Event event, final long userId) {
|
Context context, final IUsageStatsManager usageStatsManager, final Event event,
|
||||||
if (event.getPackageName() == null) {
|
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.
|
// 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
|
// Note that system events like device shutting down should still come with the android
|
||||||
// package name.
|
// package name.
|
||||||
@@ -182,13 +188,20 @@ public final class ConvertUtils {
|
|||||||
appUsageEventBuilder
|
appUsageEventBuilder
|
||||||
.setTimestamp(event.getTimeStamp())
|
.setTimestamp(event.getTimeStamp())
|
||||||
.setType(getAppUsageEventType(event.getEventType()))
|
.setType(getAppUsageEventType(event.getEventType()))
|
||||||
.setPackageName(event.getPackageName())
|
.setPackageName(packageName)
|
||||||
.setUserId(userId);
|
.setUserId(userId);
|
||||||
|
|
||||||
|
final String taskRootPackageName = getTaskRootPackageName(event);
|
||||||
|
if (taskRootPackageName != null) {
|
||||||
|
appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String effectivePackageName =
|
||||||
|
getEffectivePackageName(usageStatsManager, packageName, taskRootPackageName);
|
||||||
try {
|
try {
|
||||||
final long uid = context
|
final long uid = context
|
||||||
.getPackageManager()
|
.getPackageManager()
|
||||||
.getPackageUidAsUser(event.getPackageName(), (int) userId);
|
.getPackageUidAsUser(effectivePackageName, (int) userId);
|
||||||
appUsageEventBuilder.setUid(uid);
|
appUsageEventBuilder.setUid(uid);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
Log.w(TAG, String.format(
|
Log.w(TAG, String.format(
|
||||||
@@ -201,10 +214,6 @@ public final class ConvertUtils {
|
|||||||
} catch (NoClassDefFoundError | NoSuchMethodError e) {
|
} catch (NoClassDefFoundError | NoSuchMethodError e) {
|
||||||
Log.w(TAG, "UsageEvent instance ID API error");
|
Log.w(TAG, "UsageEvent instance ID API error");
|
||||||
}
|
}
|
||||||
String taskRootPackageName = getTaskRootPackageName(event);
|
|
||||||
if (taskRootPackageName != null) {
|
|
||||||
appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return appUsageEventBuilder.build();
|
return appUsageEventBuilder.build();
|
||||||
}
|
}
|
||||||
@@ -267,6 +276,35 @@ public final class ConvertUtils {
|
|||||||
: Locale.getDefault();
|
: 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
|
* Returns the package name of the task root when this event was reported when {@code event} is
|
||||||
* one of:
|
* 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) {
|
private static AppUsageEventType getAppUsageEventType(final int eventType) {
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case Event.ACTIVITY_RESUMED:
|
case Event.ACTIVITY_RESUMED:
|
||||||
|
@@ -256,7 +256,8 @@ public final class DataProcessor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
final AppUsageEvent appUsageEvent =
|
final AppUsageEvent appUsageEvent =
|
||||||
ConvertUtils.convertToAppUsageEvent(context, event, userId);
|
ConvertUtils.convertToAppUsageEvent(
|
||||||
|
context, sUsageStatsManager, event, userId);
|
||||||
if (appUsageEvent != null) {
|
if (appUsageEvent != null) {
|
||||||
numEventsFetched++;
|
numEventsFetched++;
|
||||||
appUsageEventList.add(appUsageEvent);
|
appUsageEventList.add(appUsageEvent);
|
||||||
|
@@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.fuelgauge.batteryusage;
|
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 com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
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.spy;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.app.usage.IUsageStatsManager;
|
||||||
import android.app.usage.UsageEvents;
|
import android.app.usage.UsageEvents;
|
||||||
import android.app.usage.UsageEvents.Event;
|
import android.app.usage.UsageEvents.Event;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
@@ -31,6 +35,7 @@ import android.database.MatrixCursor;
|
|||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.BatteryUsageStats;
|
import android.os.BatteryUsageStats;
|
||||||
import android.os.LocaleList;
|
import android.os.LocaleList;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
|
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
|
||||||
@@ -56,6 +61,8 @@ public final class ConvertUtilsTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private BatteryUsageStats mBatteryUsageStats;
|
private BatteryUsageStats mBatteryUsageStats;
|
||||||
@Mock
|
@Mock
|
||||||
|
private IUsageStatsManager mUsageStatsManager;
|
||||||
|
@Mock
|
||||||
private BatteryEntry mMockBatteryEntry;
|
private BatteryEntry mMockBatteryEntry;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -278,7 +285,7 @@ public final class ConvertUtilsTest {
|
|||||||
|
|
||||||
final long userId = 2;
|
final long userId = 2;
|
||||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||||
mContext, event, userId);
|
mContext, mUsageStatsManager, event, userId);
|
||||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
|
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
|
||||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||||
@@ -299,7 +306,7 @@ public final class ConvertUtilsTest {
|
|||||||
|
|
||||||
final long userId = 1;
|
final long userId = 1;
|
||||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||||
mContext, event, userId);
|
mContext, mUsageStatsManager, event, userId);
|
||||||
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
|
||||||
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
|
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
|
||||||
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
|
||||||
@@ -315,7 +322,7 @@ public final class ConvertUtilsTest {
|
|||||||
event.mPackage = null;
|
event.mPackage = null;
|
||||||
|
|
||||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||||
mContext, event, /*userId=*/ 0);
|
mContext, mUsageStatsManager, event, /*userId=*/ 0);
|
||||||
|
|
||||||
assertThat(appUsageEvent).isNull();
|
assertThat(appUsageEvent).isNull();
|
||||||
}
|
}
|
||||||
@@ -331,7 +338,7 @@ public final class ConvertUtilsTest {
|
|||||||
|
|
||||||
final long userId = 1;
|
final long userId = 1;
|
||||||
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
|
||||||
mContext, event, userId);
|
mContext, mUsageStatsManager, event, userId);
|
||||||
|
|
||||||
assertThat(appUsageEvent).isNull();
|
assertThat(appUsageEvent).isNull();
|
||||||
}
|
}
|
||||||
@@ -415,4 +422,53 @@ public final class ConvertUtilsTest {
|
|||||||
mContext.getResources().getConfiguration().setLocales(new LocaleList());
|
mContext.getResources().getConfiguration().setLocales(new LocaleList());
|
||||||
assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
|
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