diff options
Diffstat (limited to 'core/java/android')
5 files changed, 97 insertions, 2 deletions
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index 7bcc038..8a31390 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -54,6 +54,14 @@ public abstract class UsageStatsManagerInternal { public abstract void reportConfigurationChange(Configuration config, int userId); /** + * Reports that a content provider has been accessed by a foreground app. + * @param name The authority of the content provider + * @param pkgName The package name of the content provider + * @param userId The user in which the content provider was accessed. + */ + public abstract void reportContentProviderUsage(String name, String pkgName, int userId); + + /** * Prepares the UsageStatsService for shutdown. */ public abstract void prepareShutdown(); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 057001c..d37dda0 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -48,6 +48,7 @@ import android.util.Log; import dalvik.system.CloseGuard; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import java.io.File; @@ -57,6 +58,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Random; @@ -1936,6 +1938,19 @@ public abstract class ContentResolver { } /** + * @hide + * Returns the package names of syncadapters that match a given user and authority. + */ + public static String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, + int userId) { + try { + return getContentService().getSyncAdapterPackagesForAuthorityAsUser(authority, userId); + } catch (RemoteException e) { + } + return ArrayUtils.emptyArray(String.class); + } + + /** * Check if the provider should be synced when a network tickle is received * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl index 9998f08..8b471a0 100644 --- a/core/java/android/content/IContentService.aidl +++ b/core/java/android/content/IContentService.aidl @@ -143,6 +143,8 @@ interface IContentService { SyncAdapterType[] getSyncAdapterTypes(); SyncAdapterType[] getSyncAdapterTypesAsUser(int userId); + String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId); + /** * Returns true if there is currently a operation for the given account/authority or service * actively being processed. diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java index 8bb3ee7..6704b75 100644 --- a/core/java/android/content/SyncAdaptersCache.java +++ b/core/java/android/content/SyncAdaptersCache.java @@ -20,12 +20,19 @@ import android.content.pm.RegisteredServicesCache; import android.content.pm.XmlSerializerAndParser; import android.content.res.Resources; import android.content.res.TypedArray; +import android.util.ArrayMap; import android.util.AttributeSet; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; /** * A cache of services that export the {@link android.content.ISyncAdapter} interface. @@ -39,6 +46,10 @@ public class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> private static final String ATTRIBUTES_NAME = "sync-adapter"; private static final MySerializer sSerializer = new MySerializer(); + @GuardedBy("mServicesLock") + private SparseArray<ArrayMap<String,String[]>> mAuthorityToSyncAdapters + = new SparseArray<>(); + public SyncAdaptersCache(Context context) { super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, sSerializer); } @@ -76,6 +87,57 @@ public class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> } } + @Override + protected void onServicesChangedLocked(int userId) { + synchronized (mServicesLock) { + ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId); + if (adapterMap != null) { + adapterMap.clear(); + } + } + + super.onServicesChangedLocked(userId); + } + + public String[] getSyncAdapterPackagesForAuthority(String authority, int userId) { + synchronized (mServicesLock) { + ArrayMap<String,String[]> adapterMap = mAuthorityToSyncAdapters.get(userId); + if (adapterMap == null) { + adapterMap = new ArrayMap<>(); + mAuthorityToSyncAdapters.put(userId, adapterMap); + } + // If the mapping exists, return it + if (adapterMap.containsKey(authority)) { + return adapterMap.get(authority); + } + // Create the mapping and cache it + String[] syncAdapterPackages; + final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos; + serviceInfos = getAllServices(userId); + ArrayList<String> packages = new ArrayList<>(); + for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) { + if (authority.equals(serviceInfo.type.authority) + && serviceInfo.componentName != null) { + packages.add(serviceInfo.componentName.getPackageName()); + } + } + syncAdapterPackages = new String[packages.size()]; + packages.toArray(syncAdapterPackages); + adapterMap.put(authority, syncAdapterPackages); + + return syncAdapterPackages; + } + } + + @Override + protected void onUserRemoved(int userId) { + synchronized (mServicesLock) { + mAuthorityToSyncAdapters.remove(userId); + } + + super.onUserRemoved(userId); + } + static class MySerializer implements XmlSerializerAndParser<SyncAdapterType> { public void writeAsXml(SyncAdapterType item, XmlSerializer out) throws IOException { out.attribute(null, "authority", item.authority); diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java index 0bd2a3b..b293e2a 100644 --- a/core/java/android/content/pm/RegisteredServicesCache.java +++ b/core/java/android/content/pm/RegisteredServicesCache.java @@ -84,7 +84,7 @@ public abstract class RegisteredServicesCache<V> { private final String mAttributesName; private final XmlSerializerAndParser<V> mSerializerAndParser; - private final Object mServicesLock = new Object(); + protected final Object mServicesLock = new Object(); @GuardedBy("mServicesLock") private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>(2); @@ -232,6 +232,7 @@ public abstract class RegisteredServicesCache<V> { synchronized (mServicesLock) { final UserServices<V> user = findOrCreateUserLocked(userId); user.services = null; + onServicesChangedLocked(userId); } } @@ -489,11 +490,16 @@ public abstract class RegisteredServicesCache<V> { } } if (changed) { + onServicesChangedLocked(userId); writePersistentServicesLocked(user, userId); } } } + protected void onServicesChangedLocked(int userId) { + // Feel free to override + } + /** * Returns true if the list of changed uids is null (wildcard) or the specified uid * is contained in the list of changed uids. @@ -687,7 +693,9 @@ public abstract class RegisteredServicesCache<V> { @VisibleForTesting protected void onUserRemoved(int userId) { - mUserServices.remove(userId); + synchronized (mServicesLock) { + mUserServices.remove(userId); + } } @VisibleForTesting |
