Initial stab at background check.
Actually, this implementation is more what we want for ephemeral
apps. I am realizing the two are not really the same thing. :(
For this implementation, we now keep track of how long a uid has
been in the background, and after a certain amount of time
(currently 1 minute) we mark it as "idle". Any packages associated
with that uid are then no longer allowed to run in the background.
This means, until the app next goes in the foreground:
- No manifest broadcast receivers in the app will execute.
- No services can be started (binding services is still okay,
as this is outside dependencies on the app that should still
be represented).
- All alarms for the app are cancelled and no more can be set.
- All jobs for the app are cancelled and no more can be scheduled.
- All syncs for the app are cancelled and no more can be requested.
Change-Id: If53714ca4beed35faf2e89f916ce9eaaabd9290d
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index cca0c16..8266c08 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -27,6 +27,7 @@
import android.content.SyncInfo;
import android.content.SyncRequest;
import android.content.SyncStatusInfo;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
@@ -42,6 +43,7 @@
import android.util.AtomicFile;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.ArrayMap;
import android.util.Xml;
@@ -227,14 +229,16 @@
public final static EndPoint USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL =
new EndPoint(null, null, UserHandle.USER_ALL);
final ComponentName service;
+ final int serviceUid; // -1 for "any"
final Account account;
final int userId;
final String provider;
final boolean target_service;
final boolean target_provider;
- public EndPoint(ComponentName service, int userId) {
+ public EndPoint(ComponentName service, int userId, int uid) {
this.service = service;
+ this.serviceUid = uid;
this.userId = userId;
this.account = null;
this.provider = null;
@@ -247,6 +251,7 @@
this.provider = provider;
this.userId = userId;
this.service = null;
+ this.serviceUid = -1;
this.target_service = false;
this.target_provider = true;
}
@@ -264,6 +269,11 @@
return false;
}
if (target_service && spec.target_service) {
+ if (serviceUid != spec.serviceUid
+ && serviceUid >= 0
+ && spec.serviceUid >= 0) {
+ return false;
+ }
return service.equals(spec.service);
} else if (target_provider && spec.target_provider) {
boolean accountsMatch;
@@ -290,8 +300,9 @@
.append("/")
.append(provider == null ? "ALL PDRS" : provider);
} else if (target_service) {
- sb.append(service.getPackageName() + "/")
- .append(service.getClassName());
+ service.appendShortString(sb);
+ sb.append(":");
+ UserHandle.formatUid(sb,serviceUid);
} else {
sb.append("invalid target");
}
@@ -737,7 +748,7 @@
synchronized (mAuthorities) {
if (cname != null) {
AuthorityInfo authority = getAuthorityLocked(
- new EndPoint(cname, userId),
+ new EndPoint(cname, userId, -1),
"get service active");
if (authority == null) {
return false;
@@ -749,7 +760,7 @@
}
public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) {
- setSyncableStateForEndPoint(new EndPoint(cname, userId), active ?
+ setSyncableStateForEndPoint(new EndPoint(cname, userId, -1), active ?
AuthorityInfo.SYNCABLE : AuthorityInfo.NOT_SYNCABLE);
}
@@ -2064,18 +2075,30 @@
new Account(accountName, accountType),
authorityName, userId);
} else {
- info = new EndPoint(
- new ComponentName(packageName, className),
- userId);
+ final ComponentName cname = new ComponentName(packageName, className);
+ android.content.pm.ServiceInfo sinfo = null;
+ try {
+ sinfo = mContext.getPackageManager().getServiceInfo(cname, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.w(TAG, "Not restoring sync " + cname
+ + " -- can't find service for user " + userId);
+ }
+ if (sinfo != null) {
+ info = new EndPoint(cname, userId, sinfo.applicationInfo.uid);
+ } else {
+ info = null;
+ }
}
- authority = getOrCreateAuthorityLocked(info, id, false);
- // If the version is 0 then we are upgrading from a file format that did not
- // know about periodic syncs. In that case don't clear the list since we
- // want the default, which is a daily periodic sync.
- // Otherwise clear out this default list since we will populate it later with
- // the periodic sync descriptions that are read from the configuration file.
- if (version > 0) {
- authority.periodicSyncs.clear();
+ if (info != null) {
+ authority = getOrCreateAuthorityLocked(info, id, false);
+ // If the version is 0 then we are upgrading from a file format that did not
+ // know about periodic syncs. In that case don't clear the list since we
+ // want the default, which is a daily periodic sync.
+ // Otherwise clear out this default list since we will populate it later with
+ // the periodic sync descriptions that are read from the configuration file.
+ if (version > 0) {
+ authority.periodicSyncs.clear();
+ }
}
}
if (authority != null) {