am b94761d0: Merge "App Standby : Association between content providers and their sync adapter" into mnc-dev
* commit 'b94761d0a48522b23c54f786445658bb58258da4': App Standby : Association between content providers and their sync adapter
This commit is contained in:
@@ -53,6 +53,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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1935,6 +1937,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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -505,6 +505,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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -1176,6 +1212,16 @@ public class UsageStatsService extends SystemService implements
|
||||
mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
Reference in New Issue
Block a user