diff options
| author | Amith Yamasani <yamasani@google.com> | 2015-06-19 22:08:09 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-19 22:08:13 +0000 |
| commit | b94761d0a48522b23c54f786445658bb58258da4 (patch) | |
| tree | c9ce8934b3ebc20fdef46834c697f60376e87f72 | |
| parent | a36de70ad4c652fd6582630a15a941a7b85cc70b (diff) | |
| parent | 37a40c24deb02bca3868a8085069afae112f22e4 (diff) | |
| download | frameworks_base-b94761d0a48522b23c54f786445658bb58258da4.zip frameworks_base-b94761d0a48522b23c54f786445658bb58258da4.tar.gz frameworks_base-b94761d0a48522b23c54f786445658bb58258da4.tar.bz2 | |
Merge "App Standby : Association between content providers and their sync adapter" into mnc-dev
| -rw-r--r-- | core/java/android/app/usage/UsageStatsManagerInternal.java | 8 | ||||
| -rw-r--r-- | core/java/android/content/ContentResolver.java | 15 | ||||
| -rw-r--r-- | core/java/android/content/IContentService.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/content/SyncAdaptersCache.java | 62 | ||||
| -rw-r--r-- | core/java/android/content/pm/RegisteredServicesCache.java | 12 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 121 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 12 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UserState.java (renamed from services/core/java/com/android/server/am/UserStartedState.java) | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/ContentService.java | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/content/SyncManager.java | 4 | ||||
| -rw-r--r-- | services/usage/java/com/android/server/usage/UsageStatsService.java | 48 |
11 files changed, 248 insertions, 62 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 diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1134556..c0c401d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -676,9 +676,9 @@ public final class ActivityManagerService extends ActivityManagerNative final SparseArray<UidRecord> mActiveUids = new SparseArray<>(); /** - * Which uses have been started, so are allowed to run code. + * Which users have been started, so are allowed to run code. */ - final SparseArray<UserStartedState> mStartedUsers = new SparseArray<>(); + final SparseArray<UserState> mStartedUsers = new SparseArray<>(); /** * LRU list of history of current users. Most recently current is at the end. @@ -1781,15 +1781,15 @@ public final class ActivityManagerService extends ActivityManagerNative break; } case REPORT_USER_SWITCH_MSG: { - dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case CONTINUE_USER_SWITCH_MSG: { - continueUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case USER_SWITCH_TIMEOUT_MSG: { - timeoutUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case IMMERSIVE_MODE_LOCK_MSG: { @@ -2309,7 +2309,7 @@ public final class ActivityManagerService extends ActivityManagerNative mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); // User 0 is the first and only user that runs at boot. - mStartedUsers.put(UserHandle.USER_OWNER, new UserStartedState(UserHandle.OWNER, true)); + mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true)); mUserLru.add(UserHandle.USER_OWNER); updateStartedUserArrayLocked(); @@ -6305,9 +6305,9 @@ public final class ActivityManagerService extends ActivityManagerNative SystemProperties.set("dev.bootcomplete", "1"); } for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); - if (uss.mState == UserStartedState.STATE_BOOTING) { - uss.mState = UserStartedState.STATE_RUNNING; + UserState uss = mStartedUsers.valueAt(i); + if (uss.mState == UserState.STATE_BOOTING) { + uss.mState = UserState.STATE_RUNNING; final int userId = mStartedUsers.keyAt(i); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); @@ -9434,6 +9434,7 @@ public final class ActivityManagerService extends ActivityManagerNative } checkTime(startTime, "getContentProviderImpl: before updateOomAdj"); boolean success = updateOomAdjLocked(cpr.proc); + maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name); checkTime(startTime, "getContentProviderImpl: after updateOomAdj"); if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success); // NOTE: there is still a race here where a signal could be @@ -9823,6 +9824,8 @@ public final class ActivityManagerService extends ActivityManagerNative dst.notifyAll(); } updateOomAdjLocked(r); + maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, + src.info.authority); } } @@ -13335,7 +13338,7 @@ public final class ActivityManagerService extends ActivityManagerNative needSep = false; pw.println(" mStartedUsers:"); for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); + UserState uss = mStartedUsers.valueAt(i); pw.print(" User #"); pw.print(uss.mHandle.getIdentifier()); pw.print(": "); uss.dump("", pw); } @@ -18607,6 +18610,22 @@ public final class ActivityManagerService extends ActivityManagerNative uidRec.pendingChange.processState = uidRec.setProcState; } + private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName, + String authority) { + if (app == null) return; + if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { + UserState userState = mStartedUsers.get(app.userId); + if (userState == null) return; + final long now = SystemClock.elapsedRealtime(); + Long lastReported = userState.mProviderLastReportedFg.get(authority); + if (lastReported == null || lastReported < now - 60 * 1000L) { + mUsageStatsService.reportContentProviderUsage( + authority, providerPkgName, app.userId); + userState.mProviderLastReportedFg.put(authority, now); + } + } + } + private void maybeUpdateUsageStatsLocked(ProcessRecord app) { if (DEBUG_USAGE_STATS) { Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) @@ -19594,7 +19613,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If the user we are switching to is not currently started, then // we need to start it now. if (mStartedUsers.get(userId) == null) { - mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false)); + mStartedUsers.put(userId, new UserState(new UserHandle(userId), false)); updateStartedUserArrayLocked(); needStart = true; } @@ -19619,26 +19638,26 @@ public final class ActivityManagerService extends ActivityManagerNative mUserLru.add(currentUserIdInt); } - final UserStartedState uss = mStartedUsers.get(userId); + final UserState uss = mStartedUsers.get(userId); // Make sure user is in the started state. If it is currently // stopping, we need to knock that off. - if (uss.mState == UserStartedState.STATE_STOPPING) { + if (uss.mState == UserState.STATE_STOPPING) { // If we are stopping, we haven't sent ACTION_SHUTDOWN, // so we can just fairly silently bring the user back from // the almost-dead. - uss.mState = UserStartedState.STATE_RUNNING; + uss.mState = UserState.STATE_RUNNING; updateStartedUserArrayLocked(); needStart = true; - } else if (uss.mState == UserStartedState.STATE_SHUTDOWN) { + } else if (uss.mState == UserState.STATE_SHUTDOWN) { // This means ACTION_SHUTDOWN has been sent, so we will // need to treat this as a new boot of the user. - uss.mState = UserStartedState.STATE_BOOTING; + uss.mState = UserState.STATE_BOOTING; updateStartedUserArrayLocked(); needStart = true; } - if (uss.mState == UserStartedState.STATE_BOOTING) { + if (uss.mState == UserState.STATE_BOOTING) { // Booting up a new user, need to tell system services about it. // Note that this is on the same handler as scheduling of broadcasts, // which is important because it needs to go first. @@ -19776,7 +19795,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void dispatchUserSwitch(final UserStartedState uss, final int oldUserId, + void dispatchUserSwitch(final UserState uss, final int oldUserId, final int newUserId) { final int N = mUserSwitchObservers.beginBroadcast(); if (N > 0) { @@ -19813,21 +19832,21 @@ public final class ActivityManagerService extends ActivityManagerNative mUserSwitchObservers.finishBroadcast(); } - void timeoutUserSwitch(UserStartedState uss, int oldUserId, int newUserId) { + void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) { synchronized (this) { Slog.w(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId); sendContinueUserSwitchLocked(uss, oldUserId, newUserId); } } - void sendContinueUserSwitchLocked(UserStartedState uss, int oldUserId, int newUserId) { + void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) { mCurUserSwitchCallback = null; mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG, oldUserId, newUserId, uss)); } - void onUserInitialized(UserStartedState uss, boolean foreground, int oldUserId, int newUserId) { + void onUserInitialized(UserState uss, boolean foreground, int oldUserId, int newUserId) { synchronized (this) { if (foreground) { moveUserToForeground(uss, oldUserId, newUserId); @@ -19837,7 +19856,7 @@ public final class ActivityManagerService extends ActivityManagerNative completeSwitchAndInitalize(uss, newUserId, true, false); } - void moveUserToForeground(UserStartedState uss, int oldUserId, int newUserId) { + void moveUserToForeground(UserState uss, int oldUserId, int newUserId) { boolean homeInFront = mStackSupervisor.switchUserLocked(newUserId, uss); if (homeInFront) { startHomeActivityLocked(newUserId, "moveUserToFroreground"); @@ -19849,11 +19868,11 @@ public final class ActivityManagerService extends ActivityManagerNative sendUserSwitchBroadcastsLocked(oldUserId, newUserId); } - void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) { + void continueUserSwitch(UserState uss, int oldUserId, int newUserId) { completeSwitchAndInitalize(uss, newUserId, false, true); } - void completeSwitchAndInitalize(UserStartedState uss, int newUserId, + void completeSwitchAndInitalize(UserState uss, int newUserId, boolean clearInitializing, boolean clearSwitching) { boolean unfrozen = false; synchronized (this) { @@ -19890,10 +19909,10 @@ public final class ActivityManagerService extends ActivityManagerNative final int num = mUserLru.size(); for (int i = 0; i < num; i++) { Integer oldUserId = mUserLru.get(i); - UserStartedState oldUss = mStartedUsers.get(oldUserId); + UserState oldUss = mStartedUsers.get(oldUserId); if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId - || oldUss.mState == UserStartedState.STATE_STOPPING - || oldUss.mState == UserStartedState.STATE_SHUTDOWN) { + || oldUss.mState == UserState.STATE_STOPPING + || oldUss.mState == UserState.STATE_SHUTDOWN) { continue; } UserInfo userInfo = mUserManager.getUserInfo(oldUserId); @@ -19934,11 +19953,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void finishUserBoot(UserStartedState uss) { + void finishUserBoot(UserState uss) { synchronized (this) { - if (uss.mState == UserStartedState.STATE_BOOTING + if (uss.mState == UserState.STATE_BOOTING && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) { - uss.mState = UserStartedState.STATE_RUNNING; + uss.mState = UserState.STATE_RUNNING; final int userId = uss.mHandle.getIdentifier(); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); @@ -19951,7 +19970,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void finishUserSwitch(UserStartedState uss) { + void finishUserSwitch(UserState uss) { synchronized (this) { finishUserBoot(uss); @@ -19961,15 +19980,15 @@ public final class ActivityManagerService extends ActivityManagerNative int i = 0; while (num > MAX_RUNNING_USERS && i < mUserLru.size()) { Integer oldUserId = mUserLru.get(i); - UserStartedState oldUss = mStartedUsers.get(oldUserId); + UserState oldUss = mStartedUsers.get(oldUserId); if (oldUss == null) { // Shouldn't happen, but be sane if it does. mUserLru.remove(i); num--; continue; } - if (oldUss.mState == UserStartedState.STATE_STOPPING - || oldUss.mState == UserStartedState.STATE_SHUTDOWN) { + if (oldUss.mState == UserState.STATE_STOPPING + || oldUss.mState == UserState.STATE_SHUTDOWN) { // This user is already stopping, doesn't count. num--; i++; @@ -20014,7 +20033,7 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManager.USER_OP_IS_CURRENT; } - final UserStartedState uss = mStartedUsers.get(userId); + final UserState uss = mStartedUsers.get(userId); if (uss == null) { // User is not started, nothing to do... but we do need to // callback if requested. @@ -20036,9 +20055,9 @@ public final class ActivityManagerService extends ActivityManagerNative uss.mStopCallbacks.add(callback); } - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { - uss.mState = UserStartedState.STATE_STOPPING; + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { + uss.mState = UserState.STATE_STOPPING; updateStartedUserArrayLocked(); long ident = Binder.clearCallingIdentity(); @@ -20066,11 +20085,11 @@ public final class ActivityManagerService extends ActivityManagerNative Bundle extras, boolean ordered, boolean sticky, int sendingUser) { // On to the next. synchronized (ActivityManagerService.this) { - if (uss.mState != UserStartedState.STATE_STOPPING) { + if (uss.mState != UserState.STATE_STOPPING) { // Whoops, we are being started back up. Abort, abort! return; } - uss.mState = UserStartedState.STATE_SHUTDOWN; + uss.mState = UserState.STATE_SHUTDOWN; } mBatteryStatsService.noteEvent( BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH, @@ -20094,7 +20113,7 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManager.USER_OP_SUCCESS; } - void finishUserStop(UserStartedState uss) { + void finishUserStop(UserState uss) { final int userId = uss.mHandle.getIdentifier(); boolean stopped; ArrayList<IStopUserCallback> callbacks; @@ -20102,7 +20121,7 @@ public final class ActivityManagerService extends ActivityManagerNative callbacks = new ArrayList<IStopUserCallback>(uss.mStopCallbacks); if (mStartedUsers.get(userId) != uss) { stopped = false; - } else if (uss.mState != UserStartedState.STATE_SHUTDOWN) { + } else if (uss.mState != UserState.STATE_SHUTDOWN) { stopped = false; } else { stopped = true; @@ -20176,15 +20195,15 @@ public final class ActivityManagerService extends ActivityManagerNative } boolean isUserRunningLocked(int userId, boolean orStopped) { - UserStartedState state = mStartedUsers.get(userId); + UserState state = mStartedUsers.get(userId); if (state == null) { return false; } if (orStopped) { return true; } - return state.mState != UserStartedState.STATE_STOPPING - && state.mState != UserStartedState.STATE_SHUTDOWN; + return state.mState != UserState.STATE_STOPPING + && state.mState != UserState.STATE_SHUTDOWN; } @Override @@ -20206,19 +20225,19 @@ public final class ActivityManagerService extends ActivityManagerNative private void updateStartedUserArrayLocked() { int num = 0; for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); + UserState uss = mStartedUsers.valueAt(i); // This list does not include stopping users. - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { num++; } } mStartedUserArray = new int[num]; num = 0; for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { + UserState uss = mStartedUsers.valueAt(i); + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { mStartedUserArray[num] = mStartedUsers.keyAt(i); num++; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 4e98576..c54a96d 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -233,10 +233,10 @@ public final class ActivityStackSupervisor implements DisplayListener { final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>(); /** Used on user changes */ - final ArrayList<UserStartedState> mStartingUsers = new ArrayList<>(); + final ArrayList<UserState> mStartingUsers = new ArrayList<>(); /** Used to queue up any background users being started */ - final ArrayList<UserStartedState> mStartingBackgroundUsers = new ArrayList<>(); + final ArrayList<UserState> mStartingBackgroundUsers = new ArrayList<>(); /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity * is being brought in front of us. */ @@ -2376,7 +2376,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityRecord> stops = null; ArrayList<ActivityRecord> finishes = null; - ArrayList<UserStartedState> startingUsers = null; + ArrayList<UserState> startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; @@ -2473,7 +2473,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } // Complete starting up of background users if (mStartingBackgroundUsers.size() > 0) { - startingUsers = new ArrayList<UserStartedState>(mStartingBackgroundUsers); + startingUsers = new ArrayList<UserState>(mStartingBackgroundUsers); mStartingBackgroundUsers.clear(); for (int i = 0; i < startingUsers.size(); i++) { mService.finishUserBoot(startingUsers.get(i)); @@ -3235,7 +3235,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - boolean switchUserLocked(int userId, UserStartedState uss) { + boolean switchUserLocked(int userId, UserState uss) { mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId()); final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID); mCurrentUser = userId; @@ -3276,7 +3276,7 @@ public final class ActivityStackSupervisor implements DisplayListener { * @param userId The user being started in the background * @param uss The state object for the user. */ - public void startBackgroundUserLocked(int userId, UserStartedState uss) { + public void startBackgroundUserLocked(int userId, UserState uss) { mStartingBackgroundUsers.add(uss); } diff --git a/services/core/java/com/android/server/am/UserStartedState.java b/services/core/java/com/android/server/am/UserState.java index d3e73d5..b3d82bc 100644 --- a/services/core/java/com/android/server/am/UserStartedState.java +++ b/services/core/java/com/android/server/am/UserState.java @@ -21,8 +21,9 @@ import java.util.ArrayList; import android.app.IStopUserCallback; import android.os.UserHandle; +import android.util.ArrayMap; -public final class UserStartedState { +public final class UserState { // User is first coming up. public final static int STATE_BOOTING = 0; // User is in the normal running state. @@ -40,7 +41,13 @@ public final class UserStartedState { public boolean switching; public boolean initializing; - public UserStartedState(UserHandle handle, boolean initial) { + /** + * The last time that a provider was reported to usage stats as being brought to important + * foreground procstate. + */ + public final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); + + public UserState(UserHandle handle, boolean initial) { mHandle = handle; } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index ea461e5..93ed2ee 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -506,6 +506,21 @@ public final class ContentService extends IContentService.Stub { } @Override + public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) { + enforceCrossUserPermission(userId, + "no permission to read sync settings for user " + userId); + // This makes it so that future permission checks will be in the context of this + // process rather than the caller's process. We will restore this before returning. + final long identityToken = clearCallingIdentity(); + try { + SyncManager syncManager = getSyncManager(); + return syncManager.getSyncAdapterPackagesForAuthorityAsUser(authority, userId); + } finally { + restoreCallingIdentity(identityToken); + } + } + + @Override public boolean getSyncAutomatically(Account account, String providerName) { return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId()); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 2eb8797..cd9c7fe 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -908,6 +908,10 @@ public class SyncManager { return types; } + public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) { + return mSyncAdapters.getSyncAdapterPackagesForAuthority(authority, userId); + } + private void sendSyncAlarmMessage() { if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_ALARM"); mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_SYNC_ALARM); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 3767fce..3b7ed91 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -31,9 +31,12 @@ import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SyncAdapterType; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; @@ -69,6 +72,7 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; +import com.android.internal.os.SomeArgs; import com.android.internal.util.IndentingPrintWriter; import com.android.server.DeviceIdleController; import com.android.server.SystemService; @@ -117,6 +121,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_CHECK_IDLE_STATES = 5; static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_PAROLE_END_TIMEOUT = 7; + static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; private final Object mLock = new Object(); Handler mHandler; @@ -583,6 +588,29 @@ public class UsageStatsService extends SystemService implements } } + void reportContentProviderUsage(String authority, String providerPkgName, int userId) { + // Get sync adapters for the authority + String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser( + authority, userId); + for (String packageName: packages) { + // Only force the sync adapters to active if the provider is not in the same package and + // the sync adapter is a system package. + try { + PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo( + packageName, 0, userId); + if (pi == null || pi.applicationInfo == null + || !pi.applicationInfo.isSystemApp()) { + continue; + } + if (!packageName.equals(providerPkgName)) { + forceIdleState(packageName, userId, false); + } + } catch (RemoteException re) { + // Shouldn't happen + } + } + } + /** * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle, * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind @@ -605,7 +633,7 @@ public class UsageStatsService extends SystemService implements timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000); // Inform listeners if necessary if (previouslyIdle != idle) { - // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); + // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); if (!idle) { @@ -916,6 +944,14 @@ public class UsageStatsService extends SystemService implements setAppIdleParoled(false); break; + case MSG_REPORT_CONTENT_PROVIDER_USAGE: + SomeArgs args = (SomeArgs) msg.obj; + reportContentProviderUsage((String) args.arg1, // authority name + (String) args.arg2, // package name + (int) args.arg3); // userId + args.recycle(); + break; + default: super.handleMessage(msg); break; @@ -1177,6 +1213,16 @@ public class UsageStatsService extends SystemService implements } @Override + public void reportContentProviderUsage(String name, String packageName, int userId) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = name; + args.arg2 = packageName; + args.arg3 = userId; + mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args) + .sendToTarget(); + } + + @Override public boolean isAppIdle(String packageName, int userId) { return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); } |
