Merge "Update AppOps & UsageStats when app widget tapped." into rvc-dev

This commit is contained in:
Hui Yu
2020-03-21 19:54:59 +00:00
committed by Android (Google) Code Review
5 changed files with 83 additions and 19 deletions

View File

@@ -27,6 +27,7 @@ import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP; import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE; import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
@@ -580,6 +581,18 @@ public final class UsageStats implements Parcelable {
incrementServiceTimeUsed(timeStamp); incrementServiceTimeUsed(timeStamp);
} }
break; break;
case USER_INTERACTION:
if (hasForegroundActivity()) {
incrementTimeUsed(timeStamp);
} else {
mLastTimeUsed = timeStamp;
}
if (hasVisibleActivity()) {
incrementTimeVisible(timeStamp);
} else {
mLastTimeVisible = timeStamp;
}
break;
default: default:
break; break;
} }

View File

@@ -1240,4 +1240,18 @@ public class AppWidgetManager {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
} }
/**
* Note an app widget is tapped on.
* @param uid App UID.
* @param packageName App package name.
* @hide
*/
public void noteAppWidgetTapped(int uid, @NonNull String packageName) {
try {
mService.noteAppWidgetTapped(uid, packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
} }

View File

@@ -29,6 +29,7 @@ import android.app.Application;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.RemoteInput; import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper; import android.content.ContextWrapper;
@@ -4130,8 +4131,18 @@ public class RemoteViews implements Parcelable, Filter {
// The NEW_TASK flags are applied through the activity options and not as a part of // The NEW_TASK flags are applied through the activity options and not as a part of
// the call to startIntentSender() to ensure that they are consistently applied to // the call to startIntentSender() to ensure that they are consistently applied to
// both mutable and immutable PendingIntents. // both mutable and immutable PendingIntents.
final IntentSender intentSender = pendingIntent.getIntentSender();
final int uid = intentSender.getCreatorUid();
final String packageName = intentSender.getCreatorPackage();
if (uid != -1 && packageName != null) {
final AppWidgetManager appWidgetManager =
context.getSystemService(AppWidgetManager.class);
if (appWidgetManager != null) {
appWidgetManager.noteAppWidgetTapped(uid, packageName);
}
}
context.startIntentSender( context.startIntentSender(
pendingIntent.getIntentSender(), options.first, intentSender, options.first,
0, 0, 0, options.second.toBundle()); 0, 0, 0, options.second.toBundle());
} catch (IntentSender.SendIntentException e) { } catch (IntentSender.SendIntentException e) {
Log.e(LOG_TAG, "Cannot send pending intent: ", e); Log.e(LOG_TAG, "Cannot send pending intent: ", e);

View File

@@ -77,5 +77,6 @@ interface IAppWidgetService {
boolean requestPinAppWidget(String packageName, in ComponentName providerComponent, boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
in Bundle extras, in IntentSender resultIntent); in Bundle extras, in IntentSender resultIntent);
boolean isRequestPinAppWidgetSupported(); boolean isRequestPinAppWidgetSupported();
void noteAppWidgetTapped(int uid, String packageName);
} }

View File

@@ -35,6 +35,8 @@ import android.app.KeyguardManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener; import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManagerInternal; import android.appwidget.AppWidgetManagerInternal;
import android.appwidget.AppWidgetProviderInfo; import android.appwidget.AppWidgetProviderInfo;
@@ -235,6 +237,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private PackageManagerInternal mPackageManagerInternal; private PackageManagerInternal mPackageManagerInternal;
private ActivityManagerInternal mActivityManagerInternal; private ActivityManagerInternal mActivityManagerInternal;
private AppOpsManagerInternal mAppOpsManagerInternal; private AppOpsManagerInternal mAppOpsManagerInternal;
private UsageStatsManagerInternal mUsageStatsManagerInternal;
private SecurityPolicy mSecurityPolicy; private SecurityPolicy mSecurityPolicy;
@@ -278,6 +281,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
void systemServicesReady() { void systemServicesReady() {
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class); mAppOpsManagerInternal = LocalServices.getService(AppOpsManagerInternal.class);
mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
} }
private void computeMaximumWidgetBitmapMemory() { private void computeMaximumWidgetBitmapMemory() {
@@ -879,8 +883,6 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
outUpdates.add(updatesMap.valueAt(j)); outUpdates.add(updatesMap.valueAt(j));
} }
} }
updateAppOpsLocked(host, true);
// Reset the update counter once all the updates have been calculated // Reset the update counter once all the updates have been calculated
host.lastWidgetUpdateSequenceNo = updateSequenceNo; host.lastWidgetUpdateSequenceNo = updateSequenceNo;
return new ParceledListSlice<>(outUpdates); return new ParceledListSlice<>(outUpdates);
@@ -909,7 +911,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (host != null) { if (host != null) {
host.callbacks = null; host.callbacks = null;
pruneHostLocked(host); pruneHostLocked(host);
updateAppOpsLocked(host, false); mAppOpsManagerInternal.updateAppWidgetVisibility(host.getWidgetUids(), false);
} }
} }
} }
@@ -3646,26 +3648,49 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return false; return false;
} }
private void updateAppOpsLocked(Host host, boolean visible) { /**
if (visible) { * Note an app widget is tapped on. If a app widget is tapped, the underlying app is treated as
final int procState = mActivityManagerInternal.getUidProcessState(host.id.uid); * foreground so the app can get while-in-use permission.
*
* @param uid UID of the underlying app.
* @param packageName Package name of the app.
*/
@Override
public void noteAppWidgetTapped(int uid, String packageName) {
final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
// The launcher must be at TOP.
final int procState = mActivityManagerInternal.getUidProcessState(callingUid);
if (procState > ActivityManager.PROCESS_STATE_TOP) { if (procState > ActivityManager.PROCESS_STATE_TOP) {
// The launcher must be at TOP.
return; return;
} }
}
final List<ResolveInfo> allHomeCandidates = new ArrayList<>(); // Default launcher from package manager.
// Default launcher from package manager. final ComponentName defaultLauncher = mPackageManagerInternal
final ComponentName defaultLauncher = mPackageManagerInternal .getDefaultHomeActivity(UserHandle.getUserId(callingUid));
.getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getUserId(host.id.uid)); int defaultLauncherUid = 0;
// The launcher must be default launcher. try {
if (defaultLauncher == null defaultLauncherUid = mPackageManager.getApplicationInfo(
|| !defaultLauncher.getPackageName().equals(host.id.packageName)) { defaultLauncher.getPackageName(), 0 ,
return; UserHandle.getUserId(callingUid)).uid;
} catch (RemoteException e) {
Slog.e(TAG, "Failed to getApplicationInfo for package:"
+ defaultLauncher.getPackageName(), e);
return;
}
// The callingUid must be default launcher uid.
if (defaultLauncherUid != callingUid) {
return;
}
final SparseArray<String> uid2PackageName = new SparseArray<String>();
uid2PackageName.put(uid, packageName);
mAppOpsManagerInternal.updateAppWidgetVisibility(uid2PackageName, true);
mUsageStatsManagerInternal.reportEvent(packageName, UserHandle.getUserId(uid),
UsageEvents.Event.USER_INTERACTION);
} finally {
Binder.restoreCallingIdentity(ident);
} }
mAppOpsManagerInternal.updateAppWidgetVisibility(host.getWidgetUids(), visible);
} }
private final class CallbackHandler extends Handler { private final class CallbackHandler extends Handler {