Merge "Exclude bound app widgets from idle app list" into mnc-dev

This commit is contained in:
Amith Yamasani
2015-05-01 18:21:39 +00:00
committed by Android (Google) Code Review
4 changed files with 124 additions and 10 deletions

View File

@@ -1053,6 +1053,20 @@ public class AppWidgetManager {
} }
} }
/**
* @hide
*/
public boolean isBoundWidgetPackage(String packageName, int userId) {
if (mService == null) {
return false;
}
try {
return mService.isBoundWidgetPackage(packageName, userId);
} catch (RemoteException re) {
throw new RuntimeException("system server dead?", re);
}
}
private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId, private boolean bindAppWidgetIdIfAllowed(int appWidgetId, int profileId,
ComponentName provider, Bundle options) { ComponentName provider, Bundle options) {
if (mService == null) { if (mService == null) {

View File

@@ -65,5 +65,6 @@ interface IAppWidgetService {
in IBinder connection); in IBinder connection);
void unbindRemoteViewsService(String callingPackage, int appWidgetId, in Intent intent); void unbindRemoteViewsService(String callingPackage, int appWidgetId, in Intent intent);
int[] getAppWidgetIds(in ComponentName providerComponent); int[] getAppWidgetIds(in ComponentName providerComponent);
boolean isBoundWidgetPackage(String packageName, int userId);
} }

View File

@@ -63,6 +63,7 @@ import android.util.AtomicFile;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Pair; import android.util.Pair;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.util.TypedValue; import android.util.TypedValue;
import android.util.Xml; import android.util.Xml;
@@ -171,6 +172,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private final SparseIntArray mLoadedUserIds = new SparseIntArray(); private final SparseIntArray mLoadedUserIds = new SparseIntArray();
private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
private final BackupRestoreController mBackupRestoreController; private final BackupRestoreController mBackupRestoreController;
private final Context mContext; private final Context mContext;
@@ -572,7 +575,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
widget.host = host; widget.host = host;
host.widgets.add(widget); host.widgets.add(widget);
mWidgets.add(widget); addWidgetLocked(widget);
saveGroupStateAsync(userId); saveGroupStateAsync(userId);
@@ -800,6 +803,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
widget.provider = provider; widget.provider = provider;
widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle(); widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle();
onWidgetProviderAddedOrChangedLocked(widget);
// We need to provide a default value for the widget category if it is not specified // We need to provide a default value for the widget category if it is not specified
if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) { if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
@@ -1410,7 +1415,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
host.widgets.remove(widget); host.widgets.remove(widget);
pruneHostLocked(host); pruneHostLocked(host);
mWidgets.remove(widget); removeWidgetLocked(widget);
Provider provider = widget.provider; Provider provider = widget.provider;
if (provider != null) { if (provider != null) {
@@ -1874,7 +1879,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
updateAppWidgetInstanceLocked(widget, null, false); updateAppWidgetInstanceLocked(widget, null, false);
// clear out references to this appWidgetId // clear out references to this appWidgetId
widget.host.widgets.remove(widget); widget.host.widgets.remove(widget);
mWidgets.remove(widget); removeWidgetLocked(widget);
widget.provider = null; widget.provider = null;
pruneHostLocked(widget.host); pruneHostLocked(widget.host);
widget.host = null; widget.host = null;
@@ -2277,14 +2282,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (version >= 0) { if (version >= 0) {
// Hooke'm up... // Hooke'm up...
bindLoadedWidgets(loadedWidgets); bindLoadedWidgetsLocked(loadedWidgets);
// upgrade the database if needed // upgrade the database if needed
performUpgradeLocked(version); performUpgradeLocked(version);
} else { } else {
// failed reading, clean up // failed reading, clean up
Slog.w(TAG, "Failed to read state, clearing widgets and hosts."); Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
mWidgets.clear(); clearWidgetsLocked();
mHosts.clear(); mHosts.clear();
final int N = mProviders.size(); final int N = mProviders.size();
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
@@ -2293,7 +2298,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
} }
} }
private void bindLoadedWidgets(List<LoadedWidgetState> loadedWidgets) { private void bindLoadedWidgetsLocked(List<LoadedWidgetState> loadedWidgets) {
final int loadedWidgetCount = loadedWidgets.size(); final int loadedWidgetCount = loadedWidgets.size();
for (int i = loadedWidgetCount - 1; i >= 0; i--) { for (int i = loadedWidgetCount - 1; i >= 0; i--) {
LoadedWidgetState loadedWidget = loadedWidgets.remove(i); LoadedWidgetState loadedWidget = loadedWidgets.remove(i);
@@ -2314,7 +2319,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
widget.provider.widgets.add(widget); widget.provider.widgets.add(widget);
widget.host.widgets.add(widget); widget.host.widgets.add(widget);
mWidgets.add(widget); addWidgetLocked(widget);
} }
} }
@@ -2346,6 +2351,91 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return null; return null;
} }
/**
* Adds the widget to mWidgets and tracks the package name in mWidgetPackages.
*/
void addWidgetLocked(Widget widget) {
mWidgets.add(widget);
onWidgetProviderAddedOrChangedLocked(widget);
}
/**
* Checks if the provider is assigned and updates the mWidgetPackages to track packages
* that have bound widgets.
*/
void onWidgetProviderAddedOrChangedLocked(Widget widget) {
if (widget.provider == null) return;
int userId = widget.provider.getUserId();
ArraySet<String> packages = mWidgetPackages.get(userId);
if (packages == null) {
mWidgetPackages.put(userId, packages = new ArraySet<String>());
}
packages.add(widget.provider.info.provider.getPackageName());
}
/**
* Removes a widget from mWidgets and updates the cache of bound widget provider packages.
* If there are other widgets with the same package, leaves it in the cache, otherwise it
* removes the associated package from the cache.
*/
void removeWidgetLocked(Widget widget) {
mWidgets.remove(widget);
onWidgetRemovedLocked(widget);
}
private void onWidgetRemovedLocked(Widget widget) {
if (widget.provider == null) return;
final int userId = widget.provider.getUserId();
final String packageName = widget.provider.info.provider.getPackageName();
ArraySet<String> packages = mWidgetPackages.get(userId);
if (packages == null) {
return;
}
// Check if there is any other widget with the same package name.
// Remove packageName if none.
final int N = mWidgets.size();
for (int i = 0; i < N; i++) {
Widget w = mWidgets.get(i);
if (w.provider == null) continue;
if (w.provider.getUserId() == userId
&& packageName.equals(w.provider.info.provider.getPackageName())) {
return;
}
}
packages.remove(packageName);
}
/**
* Clears all widgets and associated cache of packages with bound widgets.
*/
void clearWidgetsLocked() {
mWidgets.clear();
onWidgetsClearedLocked();
}
private void onWidgetsClearedLocked() {
mWidgetPackages.clear();
}
@Override
public boolean isBoundWidgetPackage(String packageName, int userId) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system process can call this");
}
synchronized (mLock) {
final ArraySet<String> packages = mWidgetPackages.get(userId);
if (packages != null) {
return packages.contains(packageName);
}
}
return false;
}
private void saveStateLocked(int userId) { private void saveStateLocked(int userId) {
tagProvidersAndHosts(); tagProvidersAndHosts();
@@ -2692,7 +2782,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// as we do not want to make host callbacks and provider broadcasts // as we do not want to make host callbacks and provider broadcasts
// as the host and the provider will be killed. // as the host and the provider will be killed.
if (hostInUser && (!hasProvider || providerInUser)) { if (hostInUser && (!hasProvider || providerInUser)) {
mWidgets.remove(i); removeWidgetLocked(widget);
widget.host.widgets.remove(widget); widget.host.widgets.remove(widget);
widget.host = null; widget.host = null;
if (hasProvider) { if (hasProvider) {
@@ -3751,7 +3841,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Slog.i(TAG, "New restored id " + restoredId Slog.i(TAG, "New restored id " + restoredId
+ " now " + id); + " now " + id);
} }
mWidgets.add(id); addWidgetLocked(id);
} }
if (id.provider.info != null) { if (id.provider.info != null) {
stashProviderRestoreUpdateLocked(id.provider, stashProviderRestoreUpdateLocked(id.provider,
@@ -4013,7 +4103,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
host.widgets.remove(widget); host.widgets.remove(widget);
provider.widgets.remove(widget); provider.widgets.remove(widget);
unbindAppWidgetRemoteViewsServicesLocked(widget); unbindAppWidgetRemoteViewsServicesLocked(widget);
mWidgets.remove(i); removeWidgetLocked(widget);
} }
} }
mPrunedApps.add(pkg); mPrunedApps.add(pkg);

View File

@@ -28,6 +28,7 @@ import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats; import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManagerInternal; import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -56,6 +57,7 @@ import android.util.ArraySet;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread; import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemConfig; import com.android.server.SystemConfig;
@@ -96,6 +98,7 @@ public class UsageStatsService extends SystemService implements
Handler mHandler; Handler mHandler;
AppOpsManager mAppOps; AppOpsManager mAppOps;
UserManager mUserManager; UserManager mUserManager;
AppWidgetManager mAppWidgetManager;
private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
private File mUsageStatsDir; private File mUsageStatsDir;
@@ -158,6 +161,7 @@ public class UsageStatsService extends SystemService implements
if (phase == PHASE_SYSTEM_SERVICES_READY) { if (phase == PHASE_SYSTEM_SERVICES_READY) {
// Observe changes to the threshold // Observe changes to the threshold
new SettingsObserver(mHandler).registerObserver(); new SettingsObserver(mHandler).registerObserver();
mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
} else if (phase == PHASE_BOOT_COMPLETED) { } else if (phase == PHASE_BOOT_COMPLETED) {
setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
} }
@@ -500,6 +504,11 @@ public class UsageStatsService extends SystemService implements
return false; return false;
} }
if (mAppWidgetManager != null
&& mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
return false;
}
final long lastUsed = getLastPackageAccessTime(packageName, userId); final long lastUsed = getLastPackageAccessTime(packageName, userId);
return hasPassedIdleDuration(lastUsed); return hasPassedIdleDuration(lastUsed);
} }