Add AppWidgetManager#getInstalledProvidersForPackage()

This allows more fine-grained control than getting all installed
providers for a user, when you might only want to check for a particular
package. For instance, Launcher can use this API to surface widgets per
app without having to ask for all the widgets.

Test: Unit test on AppWidgetServiceImplTest
$ runtest --path=services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java

Bug: 34940468
Change-Id: I182bf1c012d31182024422fc4a63f57f151c3ee5
This commit is contained in:
Tony Wickham
2017-03-29 16:01:23 -07:00
parent b7980a3bbe
commit a41da04b2d
7 changed files with 64 additions and 13 deletions

View File

@@ -7022,6 +7022,7 @@ package android.appwidget {
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();

View File

@@ -7479,6 +7479,7 @@ package android.appwidget {
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();

View File

@@ -7052,6 +7052,7 @@ package android.appwidget {
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
method public android.os.Bundle getAppWidgetOptions(int);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
method public boolean isRequestPinAppWidgetSupported();

View File

@@ -710,9 +710,9 @@ public class AppWidgetManager {
* user may have a corporate profile. In this case the parent user profile has a
* child profile, the corporate one.
*
* @param profile The profile for which to get providers. Passing null is equivaled
* to passing only the current user handle.
* @return The intalled providers.
* @param profile The profile for which to get providers. Passing null is equivalent
* to querying for only the calling user.
* @return The installed providers.
*
* @see android.os.Process#myUserHandle()
* @see android.os.UserManager#getUserProfiles()
@@ -722,7 +722,31 @@ public class AppWidgetManager {
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
profile);
profile, null);
}
/**
* Gets the AppWidget providers for the given package and user profile. User
* profile can only be the current user or a profile of the current user. For
* example, the current user may have a corporate profile. In this case the
* parent user profile has a child profile, the corporate one.
*
* @param packageName The package for which to get providers. If null, this method is
* equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
* @param profile The profile for which to get providers. Passing null is equivalent
* to querying for only the calling user.
* @return The installed providers.
*
* @see android.os.Process#myUserHandle()
* @see android.os.UserManager#getUserProfiles()
*/
public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName,
@Nullable UserHandle profile) {
if (mService == null) {
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
profile, packageName);
}
/**
@@ -733,7 +757,7 @@ public class AppWidgetManager {
return Collections.emptyList();
}
return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
null);
null, null);
}
/**
@@ -752,7 +776,7 @@ public class AppWidgetManager {
if (mService == null) {
return Collections.emptyList();
}
return getInstalledProvidersForProfile(categoryFilter, null);
return getInstalledProvidersForProfile(categoryFilter, null, null);
}
/**
@@ -766,6 +790,7 @@ public class AppWidgetManager {
* @param profile A profile of the current user which to be queried. The user
* is itself also a profile. If null, the providers only for the current user
* are returned.
* @param packageName If specified, will only return providers from the given package.
* @return The intalled providers.
*
* @see android.os.Process#myUserHandle()
@@ -774,7 +799,7 @@ public class AppWidgetManager {
* @hide
*/
public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
UserHandle profile) {
@Nullable UserHandle profile, @Nullable String packageName) {
if (mService == null) {
return Collections.emptyList();
}
@@ -785,7 +810,7 @@ public class AppWidgetManager {
try {
ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
categoryFilter, profile.getIdentifier());
categoryFilter, profile.getIdentifier(), packageName);
if (providers == null) {
return Collections.emptyList();
}

View File

@@ -55,8 +55,8 @@ interface IAppWidgetService {
in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
int profileId);
ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
String packageName);
AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName, int userId);
void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);

View File

@@ -1633,7 +1633,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
@Override
public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
int profileId) {
int profileId, String packageName) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -1655,8 +1655,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Provider provider = mProviders.get(i);
AppWidgetProviderInfo info = provider.info;
// Ignore an invalid provider or one not matching the filter.
if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
// Ignore an invalid provider, one not matching the filter,
// or one that isn't in the given package, if any.
boolean inPackage = packageName == null
|| provider.id.componentName.getPackageName().equals(packageName);
if (provider.zombie || (info.widgetCategory & categoryFilter) == 0 || !inPackage) {
continue;
}

View File

@@ -50,6 +50,7 @@ import com.android.server.LocalServices;
import org.mockito.ArgumentCaptor;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -249,6 +250,25 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase {
assertEquals(7, updates.size());
}
public void testGetInstalledProvidersForPackage() {
List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
assertTrue(!allProviders.isEmpty());
String packageName = allProviders.get(0).provider.getPackageName();
List<AppWidgetProviderInfo> providersForPackage = mManager.getInstalledProvidersForPackage(
packageName, null);
// Remove providers from allProviders that don't have the given package name.
Iterator<AppWidgetProviderInfo> iter = allProviders.iterator();
while (iter.hasNext()) {
if (!iter.next().provider.getPackageName().equals(packageName)) {
iter.remove();
}
}
assertEquals(allProviders.size(), providersForPackage.size());
for (int i = 0; i < allProviders.size(); i++) {
assertEquals(allProviders.get(i).provider, providersForPackage.get(i).provider);
}
}
private int setupHostAndWidget() {
List<PendingHostUpdate> updates = mService.startListening(
mMockHost, mPkgName, HOST_ID, new int[0]).getList();