summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/Android.bp2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java35
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java32
-rw-r--r--services/core/java/com/android/server/RescueParty.java51
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java2
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java2
-rw-r--r--services/core/java/com/android/server/compat/CompatChange.java12
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java36
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java28
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java28
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java47
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java35
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java65
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java138
-rw-r--r--services/core/java/com/android/server/wm/Task.java9
-rw-r--r--services/core/xsd/platform-compat-config.xsd5
-rw-r--r--services/core/xsd/platform-compat-schema/current.txt2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java36
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java84
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java145
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java477
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java24
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java130
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java35
-rw-r--r--services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/EnterpriseSpecificIdCalculatorTest.java107
-rw-r--r--services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java80
-rw-r--r--services/translation/Android.bp13
-rw-r--r--services/translation/OWNERS8
-rw-r--r--services/translation/java/com/android/server/translation/RemoteTranslationService.java87
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerService.java92
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java125
40 files changed, 1611 insertions, 477 deletions
diff --git a/services/Android.bp b/services/Android.bp
index b51e4b014b27..da24719c0f68 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -30,6 +30,7 @@ filegroup {
":services.searchui-sources",
":services.startop.iorap-sources",
":services.systemcaptions-sources",
+ ":services.translation-sources",
":services.usage-sources",
":services.usb-sources",
":services.voiceinteraction-sources",
@@ -76,6 +77,7 @@ java_library {
"services.searchui",
"services.startop",
"services.systemcaptions",
+ "services.translation",
"services.usage",
"services.usb",
"services.voiceinteraction",
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 397eeb23396c..020c17a77084 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -620,7 +620,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private LingerMonitor mLingerMonitor;
// sequence number of NetworkRequests
- private int mNextNetworkRequestId = 1;
+ private int mNextNetworkRequestId = NetworkRequest.FIRST_REQUEST_ID;
// Sequence number for NetworkProvider IDs.
private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
@@ -1238,6 +1238,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private synchronized int nextNetworkRequestId() {
+ // TODO: Consider handle wrapping and exclude {@link NetworkRequest#REQUEST_ID_NONE} if
+ // doing that.
return mNextNetworkRequestId++;
}
@@ -1329,15 +1331,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Check if UID should be blocked from using the specified network.
*/
- private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
- boolean ignoreBlocked) {
+ private boolean isNetworkWithCapabilitiesBlocked(@Nullable final NetworkCapabilities nc,
+ final int uid, final boolean ignoreBlocked) {
// Networks aren't blocked when ignoring blocked status
if (ignoreBlocked) {
return false;
}
if (isUidBlockedByVpn(uid, mVpnBlockedUidRanges)) return true;
- final String iface = (lp == null ? "" : lp.getInterfaceName());
- return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final boolean metered = nc == null ? true : nc.isMetered();
+ return mPolicyManager.isUidNetworkingBlocked(uid, metered);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1375,12 +1382,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Apply any relevant filters to {@link NetworkState} for the given UID. For
* example, this may mark the network as {@link DetailedState#BLOCKED} based
- * on {@link #isNetworkWithLinkPropertiesBlocked}.
+ * on {@link #isNetworkWithCapabilitiesBlocked}.
*/
private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
if (state == null || state.networkInfo == null || state.linkProperties == null) return;
- if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
+ if (isNetworkWithCapabilitiesBlocked(state.networkCapabilities, uid,
+ ignoreBlocked)) {
state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
}
synchronized (mVpns) {
@@ -1440,8 +1448,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
nai = getDefaultNetwork();
- if (nai != null
- && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
+ if (nai != null && isNetworkWithCapabilitiesBlocked(
+ nai.networkCapabilities, uid, ignoreBlocked)) {
nai = null;
}
return nai != null ? nai.network : null;
@@ -1513,7 +1521,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
enforceAccessPermission();
final int uid = mDeps.getCallingUid();
NetworkState state = getFilteredNetworkState(networkType, uid);
- if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
+ if (!isNetworkWithCapabilitiesBlocked(state.networkCapabilities, uid, false)) {
return state.network;
}
return null;
@@ -4471,7 +4479,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!nai.everConnected) {
return;
}
- if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, false)) {
+ final NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
+ if (isNetworkWithCapabilitiesBlocked(nc, uid, false)) {
return;
}
nai.networkMonitor().forceReevaluation(uid);
@@ -7065,11 +7074,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
log(" accepting network in place of " + previousSatisfier.toShortString());
}
previousSatisfier.removeRequest(nri.request.requestId);
- previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs);
+ previousSatisfier.lingerRequest(nri.request.requestId, now, mLingerDelayMs);
} else {
if (VDBG || DDBG) log(" accepting network in place of null");
}
- newSatisfier.unlingerRequest(nri.request);
+ newSatisfier.unlingerRequest(nri.request.requestId);
if (!newSatisfier.addRequest(nri.request)) {
Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
+ nri.request);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 99a1d86d244e..8b506bac4a85 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -54,9 +54,13 @@ import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
@@ -149,6 +153,11 @@ public class PackageWatchdog {
private static final String ATTR_PASSED_HEALTH_CHECK = "passed-health-check";
private static final String ATTR_MITIGATION_CALLS = "mitigation-calls";
+ // A file containing information about the current mitigation count in the case of a boot loop.
+ // This allows boot loop information to persist in the case of an fs-checkpoint being
+ // aborted.
+ private static final String METADATA_FILE = "/metadata/watchdog/mitigation_count.txt";
+
@GuardedBy("PackageWatchdog.class")
private static PackageWatchdog sPackageWatchdog;
@@ -492,6 +501,7 @@ public class PackageWatchdog {
}
if (currentObserverToNotify != null) {
mBootThreshold.setMitigationCount(mitigationCount);
+ mBootThreshold.saveMitigationCountToMetadata();
currentObserverToNotify.executeBootLoopMitigation(mitigationCount);
}
}
@@ -1700,9 +1710,31 @@ public class PackageWatchdog {
SystemProperties.set(property, Long.toString(newStart));
}
+ public void saveMitigationCountToMetadata() {
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(METADATA_FILE))) {
+ writer.write(String.valueOf(getMitigationCount()));
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not save metadata to file: " + e);
+ }
+ }
+
+ public void readMitigationCountFromMetadataIfNecessary() {
+ File bootPropsFile = new File(METADATA_FILE);
+ if (bootPropsFile.exists()) {
+ try (BufferedReader reader = new BufferedReader(new FileReader(METADATA_FILE))) {
+ String mitigationCount = reader.readLine();
+ setMitigationCount(Integer.parseInt(mitigationCount));
+ bootPropsFile.delete();
+ } catch (Exception e) {
+ Slog.i(TAG, "Could not read metadata file: " + e);
+ }
+ }
+ }
+
/** Increments the boot counter, and returns whether the device is bootlooping. */
public boolean incrementAndTest() {
+ readMitigationCountFromMetadataIfNecessary();
final long now = mSystemClock.uptimeMillis();
if (now - getStart() < 0) {
Slog.e(TAG, "Window was less than zero. Resetting start to current time.");
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index a1cf8162f0e9..db36e62e44a3 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -31,6 +31,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
+import android.os.PowerManager;
import android.os.RecoverySystem;
import android.os.RemoteCallback;
import android.os.SystemClock;
@@ -77,6 +78,7 @@ public class RescueParty {
@VisibleForTesting
static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
static final String PROP_ATTEMPTING_FACTORY_RESET = "sys.attempting_factory_reset";
+ static final String PROP_ATTEMPTING_REBOOT = "sys.attempting_reboot";
static final String PROP_MAX_RESCUE_LEVEL_ATTEMPTED = "sys.max_rescue_level_attempted";
@VisibleForTesting
static final int LEVEL_NONE = 0;
@@ -87,7 +89,9 @@ public class RescueParty {
@VisibleForTesting
static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
@VisibleForTesting
- static final int LEVEL_FACTORY_RESET = 4;
+ static final int LEVEL_WARM_REBOOT = 4;
+ @VisibleForTesting
+ static final int LEVEL_FACTORY_RESET = 5;
@VisibleForTesting
static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
@VisibleForTesting
@@ -159,12 +163,24 @@ public class RescueParty {
}
/**
- * Check if we're currently attempting to reboot for a factory reset.
+ * Check if we're currently attempting to reboot for a factory reset. This method must
+ * return true if RescueParty tries to reboot early during a boot loop, since the device
+ * will not be fully booted at this time.
+ *
+ * TODO(gavincorkery): Rename method since its scope has expanded.
*/
public static boolean isAttemptingFactoryReset() {
+ return isFactoryResetPropertySet() || isRebootPropertySet();
+ }
+
+ static boolean isFactoryResetPropertySet() {
return SystemProperties.getBoolean(PROP_ATTEMPTING_FACTORY_RESET, false);
}
+ static boolean isRebootPropertySet() {
+ return SystemProperties.getBoolean(PROP_ATTEMPTING_REBOOT, false);
+ }
+
/**
* Called when {@code SettingsProvider} has been published, which is a good
* opportunity to reset any settings depending on our rescue level.
@@ -329,8 +345,10 @@ public class RescueParty {
return LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
} else if (mitigationCount == 3) {
return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
- } else if (mitigationCount >= 4) {
- return getMaxRescueLevel();
+ } else if (mitigationCount == 4) {
+ return Math.min(getMaxRescueLevel(), LEVEL_WARM_REBOOT);
+ } else if (mitigationCount >= 5) {
+ return Math.min(getMaxRescueLevel(), LEVEL_FACTORY_RESET);
} else {
Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
return LEVEL_NONE;
@@ -356,6 +374,8 @@ public class RescueParty {
// Try our best to reset all settings possible, and once finished
// rethrow any exception that we encountered
Exception res = null;
+ Runnable runnable;
+ Thread thread;
switch (level) {
case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
try {
@@ -396,11 +416,26 @@ public class RescueParty {
res = e;
}
break;
- case LEVEL_FACTORY_RESET:
+ case LEVEL_WARM_REBOOT:
// Request the reboot from a separate thread to avoid deadlock on PackageWatchdog
// when device shutting down.
+ SystemProperties.set(PROP_ATTEMPTING_REBOOT, "true");
+ runnable = () -> {
+ try {
+ PowerManager pm = context.getSystemService(PowerManager.class);
+ if (pm != null) {
+ pm.reboot(TAG);
+ }
+ } catch (Throwable t) {
+ logRescueException(level, t);
+ }
+ };
+ thread = new Thread(runnable);
+ thread.start();
+ break;
+ case LEVEL_FACTORY_RESET:
SystemProperties.set(PROP_ATTEMPTING_FACTORY_RESET, "true");
- Runnable runnable = new Runnable() {
+ runnable = new Runnable() {
@Override
public void run() {
try {
@@ -410,7 +445,7 @@ public class RescueParty {
}
}
};
- Thread thread = new Thread(runnable);
+ thread = new Thread(runnable);
thread.start();
break;
}
@@ -433,6 +468,7 @@ public class RescueParty {
case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
return PackageHealthObserverImpact.USER_IMPACT_LOW;
case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
+ case LEVEL_WARM_REBOOT:
case LEVEL_FACTORY_RESET:
return PackageHealthObserverImpact.USER_IMPACT_HIGH;
default:
@@ -714,6 +750,7 @@ public class RescueParty {
case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS: return "RESET_SETTINGS_UNTRUSTED_DEFAULTS";
case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES: return "RESET_SETTINGS_UNTRUSTED_CHANGES";
case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS: return "RESET_SETTINGS_TRUSTED_DEFAULTS";
+ case LEVEL_WARM_REBOOT: return "WARM_REBOOT";
case LEVEL_FACTORY_RESET: return "FACTORY_RESET";
default: return Integer.toString(level);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b0f2e24e3be2..c951fd438b78 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1716,7 +1716,7 @@ class StorageManagerService extends IStorageManager.Stub
public StorageManagerService(Context context) {
sSelf = this;
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mContext = context;
mResolver = mContext.getContentResolver();
mCallbacks = new Callbacks(FgThread.get().getLooper());
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 53d75d1ddd06..6f6cad043a42 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -711,7 +711,7 @@ public final class ProcessList {
mAppDataIsolationEnabled =
SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
- ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+ ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
mAppDataIsolationWhitelistedApps = new ArrayList<>(
SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index 18907a19f96d..9ba957ef27ae 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -64,7 +64,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
private Map<String, Boolean> mDeferredOverrides;
public CompatChange(long changeId) {
- this(changeId, null, -1, -1, false, false, null);
+ this(changeId, null, -1, -1, false, false, null, false);
}
/**
@@ -77,9 +77,10 @@ public final class CompatChange extends CompatibilityChangeInfo {
* @param disabled If {@code true}, overrides any {@code enableAfterTargetSdk} set.
*/
public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk,
- int enableSinceTargetSdk, boolean disabled, boolean loggingOnly, String description) {
+ int enableSinceTargetSdk, boolean disabled, boolean loggingOnly, String description,
+ boolean overridable) {
super(changeId, name, enableAfterTargetSdk, enableSinceTargetSdk, disabled, loggingOnly,
- description);
+ description, overridable);
}
/**
@@ -88,7 +89,7 @@ public final class CompatChange extends CompatibilityChangeInfo {
public CompatChange(Change change) {
super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
change.getEnableSinceTargetSdk(), change.getDisabled(), change.getLoggingOnly(),
- change.getDescription());
+ change.getDescription(), change.getOverridable());
}
void registerListener(ChangeListener listener) {
@@ -274,6 +275,9 @@ public final class CompatChange extends CompatibilityChangeInfo {
if (mDeferredOverrides != null && mDeferredOverrides.size() > 0) {
sb.append("; deferredOverrides=").append(mDeferredOverrides);
}
+ if (getOverridable()) {
+ sb.append("; overridable");
+ }
return sb.append(")").toString();
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 7bde4d5a2770..55d8279a92d0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -202,28 +202,28 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// either the linger timeout expiring and the network being taken down, or the network
// satisfying a request again.
public static class LingerTimer implements Comparable<LingerTimer> {
- public final NetworkRequest request;
+ public final int requestId;
public final long expiryMs;
- public LingerTimer(NetworkRequest request, long expiryMs) {
- this.request = request;
+ public LingerTimer(int requestId, long expiryMs) {
+ this.requestId = requestId;
this.expiryMs = expiryMs;
}
public boolean equals(Object o) {
if (!(o instanceof LingerTimer)) return false;
LingerTimer other = (LingerTimer) o;
- return (request.requestId == other.request.requestId) && (expiryMs == other.expiryMs);
+ return (requestId == other.requestId) && (expiryMs == other.expiryMs);
}
public int hashCode() {
- return Objects.hash(request.requestId, expiryMs);
+ return Objects.hash(requestId, expiryMs);
}
public int compareTo(LingerTimer other) {
return (expiryMs != other.expiryMs) ?
Long.compare(expiryMs, other.expiryMs) :
- Integer.compare(request.requestId, other.request.requestId);
+ Integer.compare(requestId, other.requestId);
}
public String toString() {
- return String.format("%s, expires %dms", request.toString(),
+ return String.format("%s, expires %dms", requestId,
expiryMs - SystemClock.elapsedRealtime());
}
}
@@ -693,7 +693,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
updateRequestCounts(REMOVE, existing);
mNetworkRequests.remove(requestId);
if (existing.isRequest()) {
- unlingerRequest(existing);
+ unlingerRequest(existing.requestId);
}
}
@@ -839,33 +839,33 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
}
/**
- * Sets the specified request to linger on this network for the specified time. Called by
+ * Sets the specified requestId to linger on this network for the specified time. Called by
* ConnectivityService when the request is moved to another network with a higher score.
*/
- public void lingerRequest(NetworkRequest request, long now, long duration) {
- if (mLingerTimerForRequest.get(request.requestId) != null) {
+ public void lingerRequest(int requestId, long now, long duration) {
+ if (mLingerTimerForRequest.get(requestId) != null) {
// Cannot happen. Once a request is lingering on a particular network, we cannot
// re-linger it unless that network becomes the best for that request again, in which
// case we should have unlingered it.
- Log.wtf(TAG, toShortString() + ": request " + request.requestId + " already lingered");
+ Log.wtf(TAG, toShortString() + ": request " + requestId + " already lingered");
}
final long expiryMs = now + duration;
- LingerTimer timer = new LingerTimer(request, expiryMs);
+ LingerTimer timer = new LingerTimer(requestId, expiryMs);
if (VDBG) Log.d(TAG, "Adding LingerTimer " + timer + " to " + toShortString());
mLingerTimers.add(timer);
- mLingerTimerForRequest.put(request.requestId, timer);
+ mLingerTimerForRequest.put(requestId, timer);
}
/**
* Cancel lingering. Called by ConnectivityService when a request is added to this network.
- * Returns true if the given request was lingering on this network, false otherwise.
+ * Returns true if the given requestId was lingering on this network, false otherwise.
*/
- public boolean unlingerRequest(NetworkRequest request) {
- LingerTimer timer = mLingerTimerForRequest.get(request.requestId);
+ public boolean unlingerRequest(int requestId) {
+ LingerTimer timer = mLingerTimerForRequest.get(requestId);
if (timer != null) {
if (VDBG) Log.d(TAG, "Removing LingerTimer " + timer + " from " + toShortString());
mLingerTimers.remove(timer);
- mLingerTimerForRequest.remove(request.requestId);
+ mLingerTimerForRequest.remove(requestId);
return true;
}
return false;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 07a4b89be4e9..b250f164a264 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1850,34 +1850,6 @@ public class Vpn {
}
}
- /**
- * @param uid The target uid.
- *
- * @return {@code true} if {@code uid} is included in one of the mBlockedUidsAsToldToNetd
- * ranges and the VPN is not connected, or if the VPN is connected but does not apply to
- * the {@code uid}.
- *
- * @apiNote This method don't check VPN lockdown status.
- * @see #mBlockedUidsAsToldToConnectivity
- */
- public synchronized boolean isBlockingUid(int uid) {
- if (mNetworkInfo.isConnected()) {
- return !appliesToUid(uid);
- } else {
- return containsUid(mBlockedUidsAsToldToConnectivity, uid);
- }
- }
-
- private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) {
- if (ranges == null) return false;
- for (UidRangeParcel range : ranges) {
- if (range.start <= uid && uid <= range.stop) {
- return true;
- }
- }
- return false;
- }
-
private void updateAlwaysOnNotification(DetailedState networkState) {
final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 407cedf38917..141fa6a17873 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -44,12 +44,6 @@ public abstract class NetworkPolicyManagerInternal {
public abstract boolean isUidRestrictedOnMeteredNetworks(int uid);
/**
- * @return true if networking is blocked on the given interface for the given uid according
- * to current networking policies.
- */
- public abstract boolean isUidNetworkingBlocked(int uid, String ifname);
-
- /**
* Figure out if networking is blocked for a given set of conditions.
*
* This is used by ConnectivityService via passing stale copies of conditions, so it must not
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0e7b4b8c9c5e..7c17356fa3cc 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -5352,7 +5352,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public boolean isUidNetworkingBlocked(int uid, boolean isNetworkMetered) {
final long startTime = mStatLogger.getTime();
- mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
+ enforceAnyPermissionOf(OBSERVE_NETWORK_POLICY, PERMISSION_MAINLINE_NETWORK_STACK);
final int uidRules;
final boolean isBackgroundRestricted;
synchronized (mUidRulesFirstLock) {
@@ -5451,32 +5451,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
&& !hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED);
}
- /**
- * @return true if networking is blocked on the given interface for the given uid according
- * to current networking policies.
- */
- @Override
- public boolean isUidNetworkingBlocked(int uid, String ifname) {
- final long startTime = mStatLogger.getTime();
-
- final int uidRules;
- final boolean isBackgroundRestricted;
- synchronized (mUidRulesFirstLock) {
- uidRules = mUidRules.get(uid, RULE_NONE);
- isBackgroundRestricted = mRestrictBackground;
- }
- final boolean isNetworkMetered;
- synchronized (mMeteredIfacesLock) {
- isNetworkMetered = mMeteredIfaces.contains(ifname);
- }
- final boolean ret = isUidNetworkingBlockedInternal(uid, uidRules, isNetworkMetered,
- isBackgroundRestricted, mLogger);
-
- mStatLogger.logDurationStat(Stats.IS_UID_NETWORKING_BLOCKED, startTime);
-
- return ret;
- }
-
@Override
public void onTempPowerSaveWhitelistChange(int appId, boolean added) {
synchronized (mUidRulesFirstLock) {
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 9088d7b481a5..d65661771a84 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -138,7 +138,6 @@ import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
-import com.android.internal.os.KernelCpuSpeedReader;
import com.android.internal.os.KernelCpuThreadReader;
import com.android.internal.os.KernelCpuThreadReaderDiff;
import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
@@ -301,8 +300,6 @@ public class StatsPullAtomService extends SystemService {
@GuardedBy("mDiskIoLock")
private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
- @GuardedBy("mCpuTimePerFreqLock")
- private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
// Disables throttler on CPU time readers.
@GuardedBy("mCpuTimePerUidLock")
private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
@@ -353,7 +350,6 @@ public class StatsPullAtomService extends SystemService {
private final Object mDataBytesTransferLock = new Object();
private final Object mBluetoothBytesTransferLock = new Object();
private final Object mKernelWakelockLock = new Object();
- private final Object mCpuTimePerFreqLock = new Object();
private final Object mCpuTimePerUidLock = new Object();
private final Object mCpuTimePerUidFreqLock = new Object();
private final Object mCpuActiveTimeLock = new Object();
@@ -442,10 +438,6 @@ public class StatsPullAtomService extends SystemService {
synchronized (mKernelWakelockLock) {
return pullKernelWakelockLocked(atomTag, data);
}
- case FrameworkStatsLog.CPU_TIME_PER_FREQ:
- synchronized (mCpuTimePerFreqLock) {
- return pullCpuTimePerFreqLocked(atomTag, data);
- }
case FrameworkStatsLog.CPU_TIME_PER_UID:
synchronized (mCpuTimePerUidLock) {
return pullCpuTimePerUidLocked(atomTag, data);
@@ -722,18 +714,6 @@ public class StatsPullAtomService extends SystemService {
mKernelWakelockReader = new KernelWakelockReader();
mTmpWakelockStats = new KernelWakelockStats();
- // Initialize state for CPU_TIME_PER_FREQ atom
- PowerProfile powerProfile = new PowerProfile(mContext);
- final int numClusters = powerProfile.getNumCpuClusters();
- mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
- int firstCpuOfCluster = 0;
- for (int i = 0; i < numClusters; i++) {
- final int numSpeedSteps = powerProfile.getNumSpeedStepsInCpuCluster(i);
- mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
- numSpeedSteps);
- firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
- }
-
// Used for CPU_TIME_PER_THREAD_FREQ
mKernelCpuThreadReader =
KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
@@ -793,7 +773,6 @@ public class StatsPullAtomService extends SystemService {
mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
registerBluetoothBytesTransfer();
registerKernelWakelock();
- registerCpuTimePerFreq();
registerCpuTimePerUid();
registerCpuCyclesPerUidCluster();
registerCpuTimePerUidFreq();
@@ -1465,32 +1444,6 @@ public class StatsPullAtomService extends SystemService {
return StatsManager.PULL_SUCCESS;
}
- private void registerCpuTimePerFreq() {
- int tagId = FrameworkStatsLog.CPU_TIME_PER_FREQ;
- PullAtomMetadata metadata = new PullAtomMetadata.Builder()
- .setAdditiveFields(new int[] {3})
- .build();
- mStatsManager.setPullAtomCallback(
- tagId,
- metadata,
- DIRECT_EXECUTOR,
- mStatsCallbackImpl
- );
- }
-
- int pullCpuTimePerFreqLocked(int atomTag, List<StatsEvent> pulledData) {
- for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
- long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
- if (clusterTimeMs != null) {
- for (int speed = clusterTimeMs.length - 1; speed >= 0; --speed) {
- pulledData.add(FrameworkStatsLog.buildStatsEvent(
- atomTag, cluster, speed, clusterTimeMs[speed]));
- }
- }
- }
- return StatsManager.PULL_SUCCESS;
- }
-
private void registerCpuTimePerUid() {
int tagId = FrameworkStatsLog.CPU_TIME_PER_UID;
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index 865571e90338..d0c632350270 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -18,6 +18,8 @@ package com.android.server.timezonedetector;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.time.ITimeZoneDetectorListener;
import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
@@ -26,12 +28,14 @@ import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.content.Context;
import android.location.LocationManager;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -163,9 +167,13 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
@Override
@NonNull
public TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfig() {
+ int userId = mCallerIdentityInjector.getCallingUserId();
+ return getCapabilitiesAndConfig(userId);
+ }
+
+ TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfig(@UserIdInt int userId) {
enforceManageTimeZoneDetectorPermission();
- int userId = mCallerIdentityInjector.getCallingUserId();
final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
ConfigurationInternal configurationInternal =
@@ -178,13 +186,22 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
@Override
public boolean updateConfiguration(@NonNull TimeZoneConfiguration configuration) {
+ int callingUserId = mCallerIdentityInjector.getCallingUserId();
+ return updateConfiguration(callingUserId, configuration);
+ }
+
+ boolean updateConfiguration(
+ @UserIdInt int userId, @NonNull TimeZoneConfiguration configuration) {
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, false, "updateConfiguration", null);
+
enforceManageTimeZoneDetectorPermission();
+
Objects.requireNonNull(configuration);
- int callingUserId = mCallerIdentityInjector.getCallingUserId();
final long token = mCallerIdentityInjector.clearCallingIdentity();
try {
- return mTimeZoneDetectorStrategy.updateConfiguration(callingUserId, configuration);
+ return mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration);
} finally {
mCallerIdentityInjector.restoreCallingIdentity(token);
}
@@ -318,11 +335,17 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
return isGeoLocationTimeZoneDetectionEnabled(mContext);
}
- boolean isLocationEnabled() {
+ boolean isLocationEnabled(@UserIdInt int userId) {
enforceManageTimeZoneDetectorPermission();
- return mContext.getSystemService(LocationManager.class)
- .isLocationEnabledForUser(mContext.getUser());
+ final long token = mCallerIdentityInjector.clearCallingIdentity();
+ try {
+ UserHandle user = UserHandle.of(userId);
+ LocationManager locationManager = mContext.getSystemService(LocationManager.class);
+ return locationManager.isLocationEnabledForUser(user);
+ } finally {
+ mCallerIdentityInjector.restoreCallingIdentity(token);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
index b2630300a6aa..e965f55e49d7 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -29,6 +29,7 @@ import android.app.time.TimeZoneConfiguration;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.os.ShellCommand;
+import android.os.UserHandle;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -76,7 +77,8 @@ class TimeZoneDetectorShellCommand extends ShellCommand {
private int runIsAutoDetectionEnabled() {
final PrintWriter pw = getOutPrintWriter();
- boolean enabled = mInterface.getCapabilitiesAndConfig()
+ int userId = UserHandle.USER_CURRENT;
+ boolean enabled = mInterface.getCapabilitiesAndConfig(userId)
.getConfiguration()
.isAutoDetectionEnabled();
pw.println(enabled);
@@ -92,14 +94,16 @@ class TimeZoneDetectorShellCommand extends ShellCommand {
private int runIsLocationEnabled() {
final PrintWriter pw = getOutPrintWriter();
- boolean enabled = mInterface.isLocationEnabled();
+ int userId = UserHandle.USER_CURRENT;
+ boolean enabled = mInterface.isLocationEnabled(userId);
pw.println(enabled);
return 0;
}
private int runIsGeoDetectionEnabled() {
final PrintWriter pw = getOutPrintWriter();
- boolean enabled = mInterface.getCapabilitiesAndConfig()
+ int userId = UserHandle.USER_CURRENT;
+ boolean enabled = mInterface.getCapabilitiesAndConfig(userId)
.getConfiguration()
.isGeoDetectionEnabled();
pw.println(enabled);
@@ -108,18 +112,20 @@ class TimeZoneDetectorShellCommand extends ShellCommand {
private int runSetAutoDetectionEnabled() {
boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+ int userId = UserHandle.USER_CURRENT;
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(enabled)
.build();
- return mInterface.updateConfiguration(configuration) ? 0 : 1;
+ return mInterface.updateConfiguration(userId, configuration) ? 0 : 1;
}
private int runSetGeoDetectionEnabled() {
boolean enabled = Boolean.parseBoolean(getNextArgRequired());
+ int userId = UserHandle.USER_CURRENT;
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
.setGeoDetectionEnabled(enabled)
.build();
- return mInterface.updateConfiguration(configuration) ? 0 : 1;
+ return mInterface.updateConfiguration(userId, configuration) ? 0 : 1;
}
private int runSuggestGeolocationTimeZone() {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index b0847879f456..03cf021d0e9b 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -174,6 +174,10 @@ class ActivityMetricsLogger {
boolean allDrawn() {
return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.allDrawn();
}
+
+ boolean contains(ActivityRecord r) {
+ return mAssociatedTransitionInfo != null && mAssociatedTransitionInfo.contains(r);
+ }
}
/** The information created when an activity is confirmed to be launched. */
@@ -793,6 +797,7 @@ class ActivityMetricsLogger {
stopLaunchTrace(info);
if (abort) {
+ mSupervisor.stopWaitingForActivityVisible(info.mLastLaunchedActivity);
launchObserverNotifyActivityLaunchCancelled(info);
} else {
if (info.isInterestingToLoggerAndObserver()) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 324e3acf8e73..a9c54741fcf6 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5435,7 +5435,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final TransitionInfoSnapshot info = mTaskSupervisor
.getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
if (info != null) {
- mTaskSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+ mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,
info.windowsFullyDrawnDelayMs, info.getLaunchState());
}
}
@@ -5476,9 +5476,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// so there is no valid info. But if it is the current top activity (e.g. sleeping), the
// invalid state is still reported to make sure the waiting result is notified.
if (validInfo || this == getDisplayArea().topRunningActivity()) {
- mTaskSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
+ mTaskSupervisor.reportActivityLaunched(false /* timeout */, this,
windowsDrawnDelayMs, launchState);
- mTaskSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs, launchState);
}
finishLaunchTickingLocked();
if (task != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 375c3e138a39..c6cc83b4c3bb 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -710,8 +710,12 @@ class ActivityStarter {
// WaitResult.
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
mLastStartActivityRecord, originalOptions);
- return getExternalResult(mRequest.waitResult == null ? res
- : waitForResult(res, mLastStartActivityRecord));
+ if (mRequest.waitResult != null) {
+ mRequest.waitResult.result = res;
+ res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
+ launchingState);
+ }
+ return getExternalResult(res);
}
} finally {
onExecutionComplete();
@@ -796,48 +800,21 @@ class ActivityStarter {
/**
* Wait for activity launch completes.
*/
- private int waitForResult(int res, ActivityRecord r) {
- mRequest.waitResult.result = res;
- switch(res) {
- case START_SUCCESS: {
- mSupervisor.mWaitingActivityLaunched.add(mRequest.waitResult);
- do {
- try {
- mService.mGlobalLock.wait();
- } catch (InterruptedException e) {
- }
- } while (mRequest.waitResult.result != START_TASK_TO_FRONT
- && !mRequest.waitResult.timeout && mRequest.waitResult.who == null);
- if (mRequest.waitResult.result == START_TASK_TO_FRONT) {
- res = START_TASK_TO_FRONT;
- }
- break;
- }
- case START_DELIVERED_TO_TOP: {
- mRequest.waitResult.timeout = false;
- mRequest.waitResult.who = r.mActivityComponent;
- mRequest.waitResult.totalTime = 0;
- break;
- }
- case START_TASK_TO_FRONT: {
- // ActivityRecord may represent a different activity, but it should not be
- // in the resumed state.
- if (r.nowVisible && r.isState(RESUMED)) {
- mRequest.waitResult.timeout = false;
- mRequest.waitResult.who = r.mActivityComponent;
- mRequest.waitResult.totalTime = 0;
- } else {
- mSupervisor.waitActivityVisible(r.mActivityComponent, mRequest.waitResult);
- // Note: the timeout variable is not currently not ever set.
- do {
- try {
- mService.mGlobalLock.wait();
- } catch (InterruptedException e) {
- }
- } while (!mRequest.waitResult.timeout && mRequest.waitResult.who == null);
- }
- break;
- }
+ private int waitResultIfNeeded(WaitResult waitResult, ActivityRecord r,
+ LaunchingState launchingState) {
+ final int res = waitResult.result;
+ if (res == START_DELIVERED_TO_TOP
+ || (res == START_TASK_TO_FRONT && r.nowVisible && r.isState(RESUMED))) {
+ // The activity should already be visible, so nothing to wait.
+ waitResult.timeout = false;
+ waitResult.who = r.mActivityComponent;
+ waitResult.totalTime = 0;
+ return res;
+ }
+ mSupervisor.waitActivityVisibleOrLaunched(waitResult, r, launchingState);
+ if (res == START_SUCCESS && waitResult.result == START_TASK_TO_FRONT) {
+ // A trampoline activity is launched and it brings another existing activity to front.
+ return START_TASK_TO_FRONT;
}
return res;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 73a6efdb6799..599bf3748dd9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -266,11 +266,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
*/
private final SparseIntArray mCurTaskIdForUser = new SparseIntArray(20);
- /** List of processes waiting to find out when a specific activity becomes visible. */
- private final ArrayList<WaitInfo> mWaitingForActivityVisible = new ArrayList<>();
-
- /** List of processes waiting to find out about the next launched activity. */
- final ArrayList<WaitResult> mWaitingActivityLaunched = new ArrayList<>();
+ /** List of requests waiting for the target activity to be launched or visible. */
+ private final ArrayList<WaitInfo> mWaitingActivityLaunched = new ArrayList<>();
/** List of activities that are ready to be stopped, but waiting for the next activity to
* settle down before doing so. */
@@ -552,9 +549,21 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
return candidateTaskId;
}
- void waitActivityVisible(ComponentName name, WaitResult result) {
- final WaitInfo waitInfo = new WaitInfo(name, result);
- mWaitingForActivityVisible.add(waitInfo);
+ void waitActivityVisibleOrLaunched(WaitResult w, ActivityRecord r,
+ LaunchingState launchingState) {
+ if (w.result != ActivityManager.START_TASK_TO_FRONT
+ && w.result != ActivityManager.START_SUCCESS) {
+ // Not a result code that can make activity visible or launched.
+ return;
+ }
+ final WaitInfo waitInfo = new WaitInfo(w, r.mActivityComponent, launchingState);
+ mWaitingActivityLaunched.add(waitInfo);
+ do {
+ try {
+ mService.mGlobalLock.wait();
+ } catch (InterruptedException ignored) {
+ }
+ } while (mWaitingActivityLaunched.contains(waitInfo));
}
void cleanupActivity(ActivityRecord r) {
@@ -568,23 +577,25 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
/** There is no valid launch time, just stop waiting. */
void stopWaitingForActivityVisible(ActivityRecord r) {
- stopWaitingForActivityVisible(r, WaitResult.INVALID_DELAY, WaitResult.LAUNCH_STATE_UNKNOWN);
+ reportActivityLaunched(false /* timeout */, r, WaitResult.INVALID_DELAY,
+ WaitResult.LAUNCH_STATE_UNKNOWN);
}
- void stopWaitingForActivityVisible(ActivityRecord r, long totalTime,
+ void reportActivityLaunched(boolean timeout, ActivityRecord r, long totalTime,
@WaitResult.LaunchState int launchState) {
boolean changed = false;
- for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
- final WaitInfo w = mWaitingForActivityVisible.get(i);
- if (w.matches(r.mActivityComponent)) {
- final WaitResult result = w.getResult();
- changed = true;
- result.timeout = false;
- result.who = w.getComponent();
- result.totalTime = totalTime;
- result.launchState = launchState;
- mWaitingForActivityVisible.remove(w);
+ for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
+ final WaitInfo info = mWaitingActivityLaunched.get(i);
+ if (!info.matches(r)) {
+ continue;
}
+ final WaitResult w = info.mResult;
+ w.timeout = timeout;
+ w.who = r.mActivityComponent;
+ w.totalTime = totalTime;
+ w.launchState = launchState;
+ mWaitingActivityLaunched.remove(i);
+ changed = true;
}
if (changed) {
mService.mGlobalLock.notifyAll();
@@ -603,38 +614,18 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
boolean changed = false;
for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
- WaitResult w = mWaitingActivityLaunched.remove(i);
- if (w.who == null) {
- changed = true;
- w.result = result;
-
+ final WaitInfo info = mWaitingActivityLaunched.get(i);
+ if (!info.matches(r)) {
+ continue;
+ }
+ final WaitResult w = info.mResult;
+ w.result = result;
+ if (result == START_DELIVERED_TO_TOP) {
// Unlike START_TASK_TO_FRONT, When an intent is delivered to top, there
// will be no followup launch signals. Assign the result and launched component.
- if (result == START_DELIVERED_TO_TOP) {
- w.who = r.mActivityComponent;
- }
- }
- }
-
- if (changed) {
- mService.mGlobalLock.notifyAll();
- }
- }
-
- void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, long totalTime,
- @WaitResult.LaunchState int launchState) {
- boolean changed = false;
- for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
- WaitResult w = mWaitingActivityLaunched.remove(i);
- if (w.who == null) {
+ w.who = r.mActivityComponent;
+ mWaitingActivityLaunched.remove(i);
changed = true;
- w.timeout = timeout;
- if (r != null) {
- w.who = new ComponentName(r.info.packageName, r.info.name);
- }
- w.totalTime = totalTime;
- w.launchState = launchState;
- // Do not modify w.result.
}
}
if (changed) {
@@ -1295,8 +1286,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, r, INVALID_DELAY,
- -1 /* launchState */);
+ reportActivityLaunched(fromTimeout, r, INVALID_DELAY, -1 /* launchState */);
}
// This is a hack to semi-deal with a race condition
@@ -1940,14 +1930,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
pw.println(prefix + "mUserRootTaskInFront=" + mRootWindowContainer.mUserRootTaskInFront);
pw.println(prefix + "mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
- if (!mWaitingForActivityVisible.isEmpty()) {
- pw.println(prefix + "mWaitingForActivityVisible=");
- for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) {
- pw.print(prefix + prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix);
- }
- }
pw.print(prefix); pw.print("isHomeRecentsComponent=");
pw.println(mRecentTasks.isRecentsComponentHomeActivity(mRootWindowContainer.mCurrentUser));
+ if (!mWaitingActivityLaunched.isEmpty()) {
+ pw.println(prefix + "mWaitingActivityLaunched=");
+ for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
+ mWaitingActivityLaunched.get(i).dump(pw, prefix + " ");
+ }
+ }
pw.println();
}
@@ -2604,32 +2594,30 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
/**
* Internal container to store a match qualifier alongside a WaitResult.
*/
- static class WaitInfo {
- private final ComponentName mTargetComponent;
- private final WaitResult mResult;
-
- WaitInfo(ComponentName targetComponent, WaitResult result) {
- this.mTargetComponent = targetComponent;
- this.mResult = result;
- }
-
- public boolean matches(ComponentName targetComponent) {
- return mTargetComponent == null || mTargetComponent.equals(targetComponent);
- }
+ private static class WaitInfo {
+ final WaitResult mResult;
+ final ComponentName mTargetComponent;
+ /**
+ * The target component may not be the final drawn activity. The launching state is managed
+ * by {@link ActivityMetricsLogger} that can track consecutive launching sequence.
+ */
+ final LaunchingState mLaunchingState;
- public WaitResult getResult() {
- return mResult;
+ WaitInfo(WaitResult result, ComponentName component, LaunchingState launchingState) {
+ mResult = result;
+ mTargetComponent = component;
+ mLaunchingState = launchingState;
}
- public ComponentName getComponent() {
- return mTargetComponent;
+ boolean matches(ActivityRecord r) {
+ return mTargetComponent.equals(r.mActivityComponent) || mLaunchingState.contains(r);
}
- public void dump(PrintWriter pw, String prefix) {
+ void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "WaitInfo:");
pw.println(prefix + " mTargetComponent=" + mTargetComponent);
pw.println(prefix + " mResult=");
- mResult.dump(pw, prefix);
+ mResult.dump(pw, prefix + " ");
}
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 61410f82835e..a88e4537d1a2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5438,14 +5438,6 @@ class Task extends WindowContainer<WindowContainer> {
r.completeResumeLocked();
}
- private void clearLaunchTime(ActivityRecord r) {
- // Make sure that there is no activity waiting for this to launch.
- if (!mTaskSupervisor.mWaitingActivityLaunched.isEmpty()) {
- mTaskSupervisor.removeIdleTimeoutForActivity(r);
- mTaskSupervisor.scheduleIdleTimeout(r);
- }
- }
-
void awakeFromSleepingLocked() {
if (!isLeafTask()) {
forAllLeafTasks((task) -> task.awakeFromSleepingLocked(),
@@ -5588,7 +5580,6 @@ class Task extends WindowContainer<WindowContainer> {
mLastNoHistoryActivity = prev.isNoHistory() ? prev : null;
prev.setState(PAUSING, "startPausingLocked");
prev.getTask().touchActiveTime();
- clearLaunchTime(prev);
mAtmService.updateCpuStats();
diff --git a/services/core/xsd/platform-compat-config.xsd b/services/core/xsd/platform-compat-config.xsd
index 992470816068..a62e2c385766 100644
--- a/services/core/xsd/platform-compat-config.xsd
+++ b/services/core/xsd/platform-compat-config.xsd
@@ -31,6 +31,7 @@
<xs:attribute type="xs:int" name="enableAfterTargetSdk"/>
<xs:attribute type="xs:int" name="enableSinceTargetSdk"/>
<xs:attribute type="xs:string" name="description"/>
+ <xs:attribute type="xs:boolean" name="overridable"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
@@ -48,7 +49,3 @@
</xs:unique>
</xs:element>
</xs:schema>
-
-
-
-
diff --git a/services/core/xsd/platform-compat-schema/current.txt b/services/core/xsd/platform-compat-schema/current.txt
index e3640edd0201..fb8bbefd8374 100644
--- a/services/core/xsd/platform-compat-schema/current.txt
+++ b/services/core/xsd/platform-compat-schema/current.txt
@@ -10,6 +10,7 @@ package com.android.server.compat.config {
method public long getId();
method public boolean getLoggingOnly();
method public String getName();
+ method public boolean getOverridable();
method public String getValue();
method public void setDescription(String);
method public void setDisabled(boolean);
@@ -18,6 +19,7 @@ package com.android.server.compat.config {
method public void setId(long);
method public void setLoggingOnly(boolean);
method public void setName(String);
+ method public void setOverridable(boolean);
method public void setValue(String);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index a281180d77d1..48f8b1505d3a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -134,6 +134,8 @@ class ActiveAdmin {
private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
private static final String TAG_PASSWORD_COMPLEXITY = "password-complexity";
+ private static final String TAG_ORGANIZATION_ID = "organization-id";
+ private static final String TAG_ENROLLMENT_SPECIFIC_ID = "enrollment-specific-id";
private static final String ATTR_VALUE = "value";
private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
@@ -273,6 +275,8 @@ class ActiveAdmin {
public String mAlwaysOnVpnPackage;
public boolean mAlwaysOnVpnLockdown;
boolean mCommonCriteriaMode;
+ public String mOrganizationId;
+ public String mEnrollmentSpecificId;
ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
this.info = info;
@@ -533,6 +537,12 @@ class ActiveAdmin {
if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
}
+ if (!TextUtils.isEmpty(mOrganizationId)) {
+ writeTextToXml(out, TAG_ORGANIZATION_ID, mOrganizationId);
+ }
+ if (!TextUtils.isEmpty(mEnrollmentSpecificId)) {
+ writeTextToXml(out, TAG_ENROLLMENT_SPECIFIC_ID, mEnrollmentSpecificId);
+ }
}
void writeTextToXml(TypedXmlSerializer out, String tag, String text) throws IOException {
@@ -766,6 +776,22 @@ class ActiveAdmin {
mCommonCriteriaMode = parser.getAttributeBoolean(null, ATTR_VALUE, false);
} else if (TAG_PASSWORD_COMPLEXITY.equals(tag)) {
mPasswordComplexity = parser.getAttributeInt(null, ATTR_VALUE);
+ } else if (TAG_ORGANIZATION_ID.equals(tag)) {
+ type = parser.next();
+ if (type == TypedXmlPullParser.TEXT) {
+ mOrganizationId = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing Organization ID.");
+ }
+ } else if (TAG_ENROLLMENT_SPECIFIC_ID.equals(tag)) {
+ type = parser.next();
+ if (type == TypedXmlPullParser.TEXT) {
+ mEnrollmentSpecificId = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing Enrollment-specific ID.");
+ }
} else {
Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -1107,5 +1133,15 @@ class ActiveAdmin {
pw.print("mPasswordComplexity=");
pw.println(mPasswordComplexity);
+
+ if (!TextUtils.isEmpty(mOrganizationId)) {
+ pw.print("mOrganizationId=");
+ pw.println(mOrganizationId);
+ }
+
+ if (!TextUtils.isEmpty(mEnrollmentSpecificId)) {
+ pw.print("mEnrollmentSpecificId=");
+ pw.println(mEnrollmentSpecificId);
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 6f1d451e7224..22e9725f49ab 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -15,6 +15,7 @@
*/
package com.android.server.devicepolicy;
+import android.annotation.NonNull;
import android.app.admin.DevicePolicySafetyChecker;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
@@ -101,4 +102,11 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
return false;
}
+
+ public String getEnrollmentSpecificId() {
+ return "";
+ }
+
+ public void setOrganizationIdForUser(
+ @NonNull String callerPackage, @NonNull String enterpriseId, int userId) {}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 3e51b7506dff..4654fca250a3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -819,6 +819,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
&& !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
+ removeCredentialManagementApp(intent.getData().getSchemeSpecificPart());
} else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)) {
clearWipeProfileNotification();
} else if (Intent.ACTION_DATE_CHANGED.equals(action)
@@ -949,6 +950,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ private void removeCredentialManagementApp(String packageName) {
+ mBackgroundHandler.post(() -> {
+ try (KeyChainConnection connection = mInjector.keyChainBind()) {
+ IKeyChainService service = connection.getService();
+ if (service.hasCredentialManagementApp()
+ && packageName.equals(service.getCredentialManagementAppPackageName())) {
+ service.removeCredentialManagementApp();
+ }
+ } catch (RemoteException | InterruptedException | IllegalStateException e) {
+ Log.e(LOG_TAG, "Unable to remove the credential management app");
+ }
+ });
+ }
+
private boolean isRemovedPackage(String changedPackage, String targetPackage, int userHandle) {
try {
return targetPackage != null
@@ -1419,6 +1434,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return SecurityLog.isLoggingEnabled();
}
+ KeyChainConnection keyChainBind() throws InterruptedException {
+ return KeyChain.bind(mContext);
+ }
+
KeyChainConnection keyChainBindAsUser(UserHandle user) throws InterruptedException {
return KeyChain.bindAsUser(mContext, user);
}
@@ -15581,4 +15600,69 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return true;
}
}
+
+ @Override
+ public String getEnrollmentSpecificId() {
+ if (!mHasFeature) {
+ return "";
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ isDeviceOwner(caller) || isProfileOwner(caller));
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
+ caller.getUserId());
+ final String esid = requiredAdmin.mEnrollmentSpecificId;
+ return esid != null ? esid : "";
+ }
+ }
+
+ @Override
+ public void setOrganizationIdForUser(
+ @NonNull String callerPackage, @NonNull String organizationId, int userId) {
+ if (!mHasFeature) {
+ return;
+ }
+ Objects.requireNonNull(callerPackage);
+
+ final CallerIdentity caller = getCallerIdentity(callerPackage);
+ // Only the DPC can set this ID.
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
+ "Only a Device Owner or Profile Owner may set the Enterprise ID.");
+ // Empty enterprise ID must not be provided in calls to this method.
+ Preconditions.checkArgument(!TextUtils.isEmpty(organizationId),
+ "Enterprise ID may not be empty.");
+
+ Log.i(LOG_TAG,
+ String.format("Setting Enterprise ID to %s for user %d", organizationId, userId));
+
+ synchronized (getLockObject()) {
+ ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
+ // As the caller is the system, it must specify the component name of the profile owner
+ // as a safety check.
+ Preconditions.checkCallAuthorization(
+ owner != null && owner.getUserHandle().getIdentifier() == userId,
+ String.format("The Profile Owner or Device Owner may only set the Enterprise ID"
+ + " on its own user, called on user %d but owner user is %d", userId,
+ owner.getUserHandle().getIdentifier()));
+ Preconditions.checkState(
+ TextUtils.isEmpty(owner.mOrganizationId) || owner.mOrganizationId.equals(
+ organizationId),
+ "The organization ID has been previously set to a different value and cannot "
+ + "be changed");
+ final String dpcPackage = owner.info.getPackageName();
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ EnterpriseSpecificIdCalculator esidCalculator =
+ new EnterpriseSpecificIdCalculator(mContext);
+
+ final String esid = esidCalculator.calculateEnterpriseId(dpcPackage,
+ organizationId);
+ owner.mOrganizationId = organizationId;
+ owner.mEnrollmentSpecificId = esid;
+ saveSettingsLocked(userId);
+ });
+ }
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
new file mode 100644
index 000000000000..df7f3084aeb3
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/EnterpriseSpecificIdCalculator.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.content.Context;
+import android.content.pm.VerifierDeviceIdentity;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.security.identity.Util;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.nio.ByteBuffer;
+
+class EnterpriseSpecificIdCalculator {
+ private static final int PADDED_HW_ID_LENGTH = 16;
+ private static final int PADDED_PROFILE_OWNER_LENGTH = 64;
+ private static final int PADDED_ENTERPRISE_ID_LENGTH = 64;
+ private static final int ESID_LENGTH = 16;
+
+ private final String mImei;
+ private final String mMeid;
+ private final String mSerialNumber;
+ private final String mMacAddress;
+
+ @VisibleForTesting
+ EnterpriseSpecificIdCalculator(String imei, String meid, String serialNumber,
+ String macAddress) {
+ mImei = imei;
+ mMeid = meid;
+ mSerialNumber = serialNumber;
+ mMacAddress = macAddress;
+ }
+
+ EnterpriseSpecificIdCalculator(Context context) {
+ TelephonyManager telephonyService = context.getSystemService(TelephonyManager.class);
+ Preconditions.checkState(telephonyService != null, "Unable to access telephony service");
+ mImei = telephonyService.getImei(0);
+ mMeid = telephonyService.getMeid(0);
+ mSerialNumber = Build.getSerial();
+ WifiManager wifiManager = context.getSystemService(WifiManager.class);
+ Preconditions.checkState(wifiManager != null, "Unable to access WiFi service");
+ final String[] macAddresses = wifiManager.getFactoryMacAddresses();
+ if (macAddresses == null || macAddresses.length == 0) {
+ mMacAddress = "";
+ } else {
+ mMacAddress = macAddresses[0];
+ }
+ }
+
+ private static String getPaddedTruncatedString(String input, int maxLength) {
+ final String paddedValue = String.format("%" + maxLength + "s", input);
+ return paddedValue.substring(0, maxLength);
+ }
+
+ private static String getPaddedHardwareIdentifier(String hardwareIdentifier) {
+ if (hardwareIdentifier == null) {
+ hardwareIdentifier = "";
+ }
+ return getPaddedTruncatedString(hardwareIdentifier, PADDED_HW_ID_LENGTH);
+ }
+
+ String getPaddedImei() {
+ return getPaddedHardwareIdentifier(mImei);
+ }
+
+ String getPaddedMeid() {
+ return getPaddedHardwareIdentifier(mMeid);
+ }
+
+ String getPaddedSerialNumber() {
+ return getPaddedHardwareIdentifier(mSerialNumber);
+ }
+
+ String getPaddedProfileOwnerName(String profileOwnerPackage) {
+ return getPaddedTruncatedString(profileOwnerPackage, PADDED_PROFILE_OWNER_LENGTH);
+ }
+
+ String getPaddedEnterpriseId(String enterpriseId) {
+ return getPaddedTruncatedString(enterpriseId, PADDED_ENTERPRISE_ID_LENGTH);
+ }
+
+ /**
+ * Calculates the ESID.
+ * @param profileOwnerPackage Package of the Device Policy Client that manages the device/
+ * profile. May not be null.
+ * @param enterpriseIdString The identifier for the enterprise in which the device/profile is
+ * being enrolled. This parameter may not be empty, but may be null.
+ * If called with {@code null}, will calculate an ESID with empty
+ * Enterprise ID.
+ */
+ public String calculateEnterpriseId(String profileOwnerPackage, String enterpriseIdString) {
+ Preconditions.checkArgument(!TextUtils.isEmpty(profileOwnerPackage),
+ "owner package must be specified.");
+
+ Preconditions.checkArgument(enterpriseIdString == null || !enterpriseIdString.isEmpty(),
+ "enterprise ID must either be null or non-empty.");
+
+ if (enterpriseIdString == null) {
+ enterpriseIdString = "";
+ }
+
+ final byte[] serialNumber = getPaddedSerialNumber().getBytes();
+ final byte[] imei = getPaddedImei().getBytes();
+ final byte[] meid = getPaddedMeid().getBytes();
+ final byte[] macAddress = mMacAddress.getBytes();
+ final int totalIdentifiersLength = serialNumber.length + imei.length + meid.length
+ + macAddress.length;
+ final ByteBuffer fixedIdentifiers = ByteBuffer.allocate(totalIdentifiersLength);
+ fixedIdentifiers.put(serialNumber);
+ fixedIdentifiers.put(imei);
+ fixedIdentifiers.put(meid);
+ fixedIdentifiers.put(macAddress);
+
+ final byte[] dpcPackage = getPaddedProfileOwnerName(profileOwnerPackage).getBytes();
+ final byte[] enterpriseId = getPaddedEnterpriseId(enterpriseIdString).getBytes();
+ final ByteBuffer info = ByteBuffer.allocate(dpcPackage.length + enterpriseId.length);
+ info.put(dpcPackage);
+ info.put(enterpriseId);
+ final byte[] esidBytes = Util.computeHkdf("HMACSHA256", fixedIdentifiers.array(), null,
+ info.array(), ESID_LENGTH);
+ ByteBuffer esidByteBuffer = ByteBuffer.wrap(esidBytes);
+
+ VerifierDeviceIdentity firstId = new VerifierDeviceIdentity(esidByteBuffer.getLong());
+ VerifierDeviceIdentity secondId = new VerifierDeviceIdentity(esidByteBuffer.getLong());
+ return firstId.toString() + secondId.toString();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index 3220dff553d3..a691a8d44e48 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -313,29 +313,30 @@ public class AppStateTrackerTest {
}
}
- private static final int NONE = 0;
- private static final int ALARMS_ONLY = 1 << 0;
- private static final int JOBS_ONLY = 1 << 1;
- private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY;
-
- private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
- int restrictionTypes, boolean exemptFromBatterySaver) {
- assertEquals(((restrictionTypes & JOBS_ONLY) != 0),
- instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver));
- assertEquals(((restrictionTypes & ALARMS_ONLY) != 0),
- instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver));
+ private void areJobsRestricted(AppStateTrackerTestable instance, int[] uids, String[] packages,
+ boolean[] restricted, boolean exemption) {
+ assertTrue(uids.length == packages.length && uids.length == restricted.length);
+ for (int i = 0; i < uids.length; i++) {
+ assertEquals(restricted[i],
+ instance.areJobsRestricted(uids[i], packages[i], exemption));
+ }
}
- private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName,
- int restrictionTypes) {
- areRestricted(instance, uid, packageName, restrictionTypes,
- /*exemptFromBatterySaver=*/ false);
+ private void areAlarmsRestrictedByFAS(AppStateTrackerTestable instance, int[] uids,
+ String[] packages, boolean[] restricted) {
+ assertTrue(uids.length == packages.length && uids.length == restricted.length);
+ for (int i = 0; i < uids.length; i++) {
+ assertEquals(restricted[i], instance.areAlarmsRestricted(uids[i], packages[i]));
+ }
}
- private void areRestrictedWithExemption(AppStateTrackerTestable instance,
- int uid, String packageName, int restrictionTypes) {
- areRestricted(instance, uid, packageName, restrictionTypes,
- /*exemptFromBatterySaver=*/ true);
+ private void areAlarmsRestrictedByBatterySaver(AppStateTrackerTestable instance, int[] uids,
+ String[] packages, boolean[] restricted) {
+ assertTrue(uids.length == packages.length && uids.length == restricted.length);
+ for (int i = 0; i < uids.length; i++) {
+ assertEquals(restricted[i],
+ instance.areAlarmsRestrictedByBatterySaver(uids[i], packages[i]));
+ }
}
@Test
@@ -344,30 +345,42 @@ public class AppStateTrackerTest {
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
-
- areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
- areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
- areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false});
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
assertTrue(instance.isForceAllAppsStandbyEnabled());
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
-
- areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
- areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
- areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false});
// Toggle the foreground state.
- mPowerSaveMode = true;
- mPowerSaveObserver.accept(getPowerSaveState());
assertFalse(instance.isUidActive(UID_1));
assertFalse(instance.isUidActive(UID_2));
@@ -376,34 +389,65 @@ public class AppStateTrackerTest {
mIUidObserver.onUidActive(UID_1);
waitUntilMainHandlerDrain();
waitUntilMainHandlerDrain();
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, true, true, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, true, true, false});
+
assertTrue(instance.isUidActive(UID_1));
assertFalse(instance.isUidActive(UID_2));
mIUidObserver.onUidGone(UID_1, /*disable=*/ false);
waitUntilMainHandlerDrain();
waitUntilMainHandlerDrain();
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false});
+
assertFalse(instance.isUidActive(UID_1));
assertFalse(instance.isUidActive(UID_2));
mIUidObserver.onUidActive(UID_1);
waitUntilMainHandlerDrain();
waitUntilMainHandlerDrain();
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, true, true, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, true, true, false});
mIUidObserver.onUidIdle(UID_1, /*disable=*/ false);
waitUntilMainHandlerDrain();
waitUntilMainHandlerDrain();
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false});
+
assertFalse(instance.isUidActive(UID_1));
assertFalse(instance.isUidActive(UID_2));
@@ -416,11 +460,19 @@ public class AppStateTrackerTest {
assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
- areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false});
setAppOps(UID_1, PACKAGE_1, true);
setAppOps(UID_10_2, PACKAGE_2, true);
@@ -429,24 +481,72 @@ public class AppStateTrackerTest {
assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2));
assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
- areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false},
+ true);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false});
// Toggle power saver, should still be the same.
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false},
+ true);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, true, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false});
+
mPowerSaveMode = false;
mPowerSaveObserver.accept(getPowerSaveState());
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
- areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false},
+ true);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, false, false, true, false});
// Clear the app ops and update the exemption list.
setAppOps(UID_1, PACKAGE_1, false);
@@ -455,24 +555,41 @@ public class AppStateTrackerTest {
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false},
+ true);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, true, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, false});
instance.setPowerSaveExemptionListAppIds(new int[] {UID_1}, new int[] {},
new int[] {UID_2});
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY);
- areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY);
- areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID},
+ new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3,
+ PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, true, true, false},
+ false);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID},
+ new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3,
+ PACKAGE_SYSTEM},
+ new boolean[] {false, false, true, true, true, true, false});
// Again, make sure toggling the global state doesn't change it.
mPowerSaveMode = false;
@@ -481,13 +598,18 @@ public class AppStateTrackerTest {
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY);
- areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY);
- areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID},
+ new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3,
+ PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false, true, true, false},
+ false);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID},
+ new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3,
+ PACKAGE_SYSTEM},
+ new boolean[] {false, false, true, true, true, true, false});
assertTrue(instance.isUidPowerSaveExempt(UID_1));
assertTrue(instance.isUidPowerSaveExempt(UID_10_1));
@@ -646,52 +768,98 @@ public class AppStateTrackerTest {
}
@Test
- public void testExempt() throws Exception {
+ public void testExemptedBucket() throws Exception {
final AppStateTrackerTestable instance = newInstance();
callStart(instance);
assertFalse(instance.isForceAllAppsStandbyEnabled());
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false},
+ false);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false});
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
assertTrue(instance.isForceAllAppsStandbyEnabled());
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {false, false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM},
+ new boolean[] {true, true, true, false});
// Exempt package 2 on user-10.
mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false,
UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT);
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
-
- areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE);
- areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
- areRestrictedWithExemption(instance, UID_10_2, PACKAGE_2, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {true, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {true, true, false});
// Exempt package 1 on user-0.
mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_1, /*user=*/ 0, false,
UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT);
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_2, PACKAGE_2, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, true, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, true, false});
// Unexempt package 2 on user-10.
mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false,
UsageStatsManager.STANDBY_BUCKET_ACTIVE, REASON_MAIN_USAGE);
- areRestricted(instance, UID_1, PACKAGE_1, NONE);
- areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS);
- areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, true, true},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, false, false},
+ true);
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, true, true});
// Check force-app-standby.
// EXEMPT doesn't exempt from force-app-standby.
@@ -703,13 +871,28 @@ public class AppStateTrackerTest {
mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 0, false,
UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT);
+ // All 3 packages (u0:p1, u0:p2, u10:p2) are now in the exempted bucket.
setAppOps(UID_1, PACKAGE_1, true);
- areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestricted(instance, UID_2, PACKAGE_2, NONE);
-
- areRestrictedWithExemption(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
- areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {true, false, false},
+ false);
+ areJobsRestricted(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {true, false, false},
+ true);
+
+ areAlarmsRestrictedByBatterySaver(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {false, false, false});
+ areAlarmsRestrictedByFAS(instance,
+ new int[] {UID_1, UID_2, UID_10_2},
+ new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2},
+ new boolean[] {true, false, false});
}
@Test
@@ -809,6 +992,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -823,7 +1008,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(1)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -853,6 +1040,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -865,6 +1054,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(1)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
@@ -876,15 +1067,16 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
- // Unrestrict while battery saver is on. Shouldn't fire.
+ // Test overlap with battery saver
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
- // Note toggling appops while BS is on will suppress unblockAlarmsForUidPackage().
setAppOps(UID_10_2, PACKAGE_2, true);
waitUntilMainHandlerDrain();
@@ -892,6 +1084,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean());
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -906,7 +1100,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(1)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -922,7 +1118,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(0)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -934,7 +1132,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(1)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -948,6 +1148,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -961,12 +1163,14 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- // Do the same thing with battery saver on. (Currently same callbacks are called.)
+ // Do the same thing with battery saver on.
mPowerSaveMode = true;
mPowerSaveObserver.accept(getPowerSaveState());
@@ -975,6 +1179,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -989,7 +1195,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(0)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(1)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -1001,7 +1209,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(1)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
+ verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -1015,6 +1225,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1028,6 +1240,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(anyInt());
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1037,9 +1251,8 @@ public class AppStateTrackerTest {
// -------------------------------------------------------------------------
// Tests with proc state changes.
- // With battery save.
- mPowerSaveMode = true;
- mPowerSaveObserver.accept(getPowerSaveState());
+ // With battery saver.
+ // Battery saver is already on.
mIUidObserver.onUidActive(UID_10_1);
@@ -1049,6 +1262,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1062,6 +1277,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1075,6 +1292,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1088,12 +1307,14 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- // Without battery save.
+ // Without battery saver.
mPowerSaveMode = false;
mPowerSaveObserver.accept(getPowerSaveState());
@@ -1102,7 +1323,9 @@ public class AppStateTrackerTest {
verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
- verify(l, times(1)).unblockAllUnrestrictedAlarms();
+ verify(l, times(1)).updateAllAlarms();
+ verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1));
+ verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
@@ -1115,6 +1338,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1128,6 +1353,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1141,6 +1368,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
@@ -1154,6 +1383,8 @@ public class AppStateTrackerTest {
verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
+ verify(l, times(0)).updateAllAlarms();
+ verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1));
verify(l, times(0)).unblockAllUnrestrictedAlarms();
verify(l, times(0)).unblockAlarmsForUid(anyInt());
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index f375421043fd..fd364ae77240 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -233,8 +233,10 @@ public class RescuePartyTest {
verifiedTimesMap);
noteBoot(4);
+ assertTrue(RescueParty.isRebootPropertySet());
- assertTrue(RescueParty.isAttemptingFactoryReset());
+ noteBoot(5);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -255,7 +257,10 @@ public class RescuePartyTest {
/*configResetVerifiedTimesMap=*/ null);
notePersistentAppCrash(4);
- assertTrue(RescueParty.isAttemptingFactoryReset());
+ assertTrue(RescueParty.isRebootPropertySet());
+
+ notePersistentAppCrash(5);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -306,7 +311,11 @@ public class RescuePartyTest {
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
- assertTrue(RescueParty.isAttemptingFactoryReset());
+ assertTrue(RescueParty.isRebootPropertySet());
+
+ observer.execute(new VersionedPackage(
+ CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -367,7 +376,11 @@ public class RescuePartyTest {
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
- assertTrue(RescueParty.isAttemptingFactoryReset());
+ assertTrue(RescueParty.isRebootPropertySet());
+
+ observer.execute(new VersionedPackage(
+ CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
+ assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -376,6 +389,7 @@ public class RescuePartyTest {
noteBoot(i + 1);
}
assertTrue(RescueParty.isAttemptingFactoryReset());
+ assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -424,7 +438,7 @@ public class RescuePartyTest {
for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
noteBoot(i + 1);
}
- assertFalse(RescueParty.isAttemptingFactoryReset());
+ assertFalse(RescueParty.isFactoryResetPropertySet());
// Restore the property value initialized in SetUp()
SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, "");
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 8edac4f8ce58..7a970a1c3d46 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -52,6 +52,7 @@ import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENE
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INTERVAL;
+import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK;
import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK;
import static com.android.server.alarm.AlarmManagerService.WORKING_INDEX;
@@ -71,6 +72,7 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -817,14 +819,14 @@ public class AlarmManagerServiceTest {
}
@Test
- public void testAlarmRestrictedInBatterySaver() throws Exception {
+ public void testAlarmRestrictedByFAS() throws Exception {
final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor =
ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class);
verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
final PendingIntent alarmPi = getNewMockPendingIntent();
- when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID, TEST_CALLING_PACKAGE,
- false)).thenReturn(true);
+ when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(true);
setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi);
assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed());
@@ -1301,7 +1303,6 @@ public class AlarmManagerServiceTest {
final long awiDelayForTest = 23;
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0);
setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
getNewMockPendingIntent());
@@ -1336,7 +1337,7 @@ public class AlarmManagerServiceTest {
}
@Test
- public void allowWhileIdleUnrestricted() throws Exception {
+ public void allowWhileIdleUnrestrictedInIdle() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong());
final long awiDelayForTest = 127;
@@ -1361,7 +1362,7 @@ public class AlarmManagerServiceTest {
}
@Test
- public void deviceIdleThrottling() throws Exception {
+ public void deviceIdleDeferralOnSet() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong());
final long deviceIdleUntil = mNowElapsedTest + 1234;
@@ -1386,6 +1387,123 @@ public class AlarmManagerServiceTest {
}
@Test
+ public void deviceIdleStateChanges() throws Exception {
+ doReturn(0).when(mService).fuzzForDuration(anyLong());
+
+ final int numAlarms = 10;
+ final PendingIntent[] pis = new PendingIntent[numAlarms];
+ for (int i = 0; i < numAlarms; i++) {
+ setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i + 1,
+ pis[i] = getNewMockPendingIntent());
+ assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
+ }
+
+ final PendingIntent idleUntil = getNewMockPendingIntent();
+ setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1234, idleUntil);
+
+ assertEquals(mNowElapsedTest + 1234, mTestTimer.getElapsed());
+
+ mNowElapsedTest += 5;
+ mTestTimer.expire();
+ // Nothing should happen.
+ verify(pis[0], never()).send(eq(mMockContext), eq(0), any(Intent.class), any(),
+ any(Handler.class), isNull(), any());
+
+ mService.removeLocked(idleUntil, null);
+ mTestTimer.expire();
+ // Now, the first 5 alarms (upto i = 4) should expire.
+ for (int i = 0; i < 5; i++) {
+ verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(),
+ any(Handler.class), isNull(), any());
+ }
+ // Rest should be restored, so the timer should reflect the next alarm.
+ assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
+ }
+
+ @Test
+ public void batterySaverThrottling() {
+ final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class);
+ verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
+ final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue();
+
+ final PendingIntent alarmPi = getNewMockPendingIntent();
+ when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(true);
+ setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi);
+ assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed());
+
+ when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(false);
+ listener.updateAllAlarms();
+ assertEquals(mNowElapsedTest + 7, mTestTimer.getElapsed());
+
+ when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(true);
+ listener.updateAlarmsForUid(TEST_CALLING_UID);
+ assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed());
+ }
+
+ @Test
+ public void allowWhileIdleAlarmsInBatterySaver() throws Exception {
+ final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class);
+ verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture());
+ final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue();
+
+ final long longDelay = 23;
+ final long shortDelay = 7;
+ setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, longDelay);
+ setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, shortDelay);
+
+ when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(true);
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
+ getNewMockPendingIntent(), false);
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2,
+ getNewMockPendingIntent(), false);
+
+ assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
+
+ mNowElapsedTest += 1;
+ mTestTimer.expire();
+
+ assertEquals(mNowElapsedTest + longDelay, mTestTimer.getElapsed());
+ listener.onUidForeground(TEST_CALLING_UID, true);
+ // The next alarm should be deferred by shortDelay.
+ assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed());
+
+ mNowElapsedTest = mTestTimer.getElapsed();
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
+ getNewMockPendingIntent(), false);
+
+ when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(true);
+ mTestTimer.expire();
+ // The next alarm should be deferred by shortDelay again.
+ assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed());
+
+ mNowElapsedTest = mTestTimer.getElapsed();
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
+ getNewMockPendingIntent(), true);
+ when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(false);
+ mTestTimer.expire();
+ final long lastAwiDispatch = mNowElapsedTest;
+ // Unrestricted, so should not be changed.
+ assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
+
+ mNowElapsedTest = mTestTimer.getElapsed();
+ // AWI_unrestricted should not affect normal AWI bookkeeping.
+ // The next alarm is after the short delay but before the long delay.
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, lastAwiDispatch + shortDelay + 1,
+ getNewMockPendingIntent(), false);
+ mTestTimer.expire();
+ assertEquals(lastAwiDispatch + longDelay, mTestTimer.getElapsed());
+
+ listener.onUidForeground(TEST_CALLING_UID, true);
+ assertEquals(lastAwiDispatch + shortDelay + 1, mTestTimer.getElapsed());
+ }
+
+ @Test
public void dispatchOrder() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong());
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
index 4f4aa3f16f09..f00edcc85404 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigBuilder.java
@@ -40,78 +40,83 @@ class CompatConfigBuilder {
}
CompatConfigBuilder addEnableAfterSdkChangeWithId(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", sdk, -1, false, false, ""));
+ mChanges.add(new CompatChange(id, "", sdk, -1, false, false, "", false));
return this;
}
CompatConfigBuilder addEnableAfterSdkChangeWithIdAndName(int sdk, long id, String name) {
- mChanges.add(new CompatChange(id, name, sdk, -1, false, false, ""));
+ mChanges.add(new CompatChange(id, name, sdk, -1, false, false, "", false));
return this;
}
CompatConfigBuilder addEnableAfterSdkChangeWithIdDefaultDisabled(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", sdk, -1, true, false, ""));
+ mChanges.add(new CompatChange(id, "", sdk, -1, true, false, "", false));
return this;
}
CompatConfigBuilder addEnableAfterSdkChangeWithIdAndDescription(int sdk, long id,
String description) {
- mChanges.add(new CompatChange(id, "", sdk, -1, false, false, description));
+ mChanges.add(new CompatChange(id, "", sdk, -1, false, false, description, false));
return this;
}
CompatConfigBuilder addEnableSinceSdkChangeWithId(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", -1, sdk, false, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, sdk, false, false, "", false));
return this;
}
CompatConfigBuilder addEnableSinceSdkChangeWithIdAndName(int sdk, long id, String name) {
- mChanges.add(new CompatChange(id, name, -1, sdk, false, false, ""));
+ mChanges.add(new CompatChange(id, name, -1, sdk, false, false, "", false));
return this;
}
CompatConfigBuilder addEnableSinceSdkChangeWithIdDefaultDisabled(int sdk, long id) {
- mChanges.add(new CompatChange(id, "", -1, sdk, true, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, sdk, true, false, "", false));
return this;
}
CompatConfigBuilder addEnableSinceSdkChangeWithIdAndDescription(int sdk, long id,
String description) {
- mChanges.add(new CompatChange(id, "", -1, sdk, false, false, description));
+ mChanges.add(new CompatChange(id, "", -1, sdk, false, false, description, false));
return this;
}
CompatConfigBuilder addEnabledChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, -1, false, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, false, "", false));
return this;
}
CompatConfigBuilder addEnabledChangeWithIdAndName(long id, String name) {
- mChanges.add(new CompatChange(id, name, -1, -1, false, false, ""));
+ mChanges.add(new CompatChange(id, name, -1, -1, false, false, "", false));
return this;
}
CompatConfigBuilder addEnabledChangeWithIdAndDescription(long id, String description) {
- mChanges.add(new CompatChange(id, "", -1, -1, false, false, description));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, false, description, false));
return this;
}
CompatConfigBuilder addDisabledChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, -1, true, false, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, true, false, "", false));
return this;
}
CompatConfigBuilder addDisabledChangeWithIdAndName(long id, String name) {
- mChanges.add(new CompatChange(id, name, -1, -1, true, false, ""));
+ mChanges.add(new CompatChange(id, name, -1, -1, true, false, "", false));
return this;
}
CompatConfigBuilder addDisabledChangeWithIdAndDescription(long id, String description) {
- mChanges.add(new CompatChange(id, "", -1, -1, true, false, description));
+ mChanges.add(new CompatChange(id, "", -1, -1, true, false, description, false));
return this;
}
CompatConfigBuilder addLoggingOnlyChangeWithId(long id) {
- mChanges.add(new CompatChange(id, "", -1, -1, false, true, ""));
+ mChanges.add(new CompatChange(id, "", -1, -1, false, true, "", false));
+ return this;
+ }
+
+ CompatConfigBuilder addOverridableChangeWithId(long id) {
+ mChanges.add(new CompatChange(id, "", -1, -1, false, true, "", true));
return this;
}
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index a70c51045340..a1b2dc8bd82d 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -97,17 +97,22 @@ public class PlatformCompatTest {
.addEnableAfterSdkChangeWithId(Build.VERSION_CODES.Q, 5L)
.addEnableAfterSdkChangeWithId(Build.VERSION_CODES.R, 6L)
.addLoggingOnlyChangeWithId(7L)
+ .addOverridableChangeWithId(8L)
.build();
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
assertThat(mPlatformCompat.listAllChanges()).asList().containsExactly(
- new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
- new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
+ new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false),
+ new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false),
new CompatibilityChangeInfo(3L, "", Build.VERSION_CODES.O, -1, false, false,
- "desc"),
- new CompatibilityChangeInfo(4L, "", Build.VERSION_CODES.P, -1, false, false, ""),
- new CompatibilityChangeInfo(5L, "", Build.VERSION_CODES.Q, -1, false, false, ""),
- new CompatibilityChangeInfo(6L, "", Build.VERSION_CODES.R, -1, false, false, ""),
- new CompatibilityChangeInfo(7L, "", -1, -1, false, true, ""));
+ "desc", false),
+ new CompatibilityChangeInfo(
+ 4L, "", Build.VERSION_CODES.P, -1, false, false, "", false),
+ new CompatibilityChangeInfo(
+ 5L, "", Build.VERSION_CODES.Q, -1, false, false, "", false),
+ new CompatibilityChangeInfo(
+ 6L, "", Build.VERSION_CODES.R, -1, false, false, "", false),
+ new CompatibilityChangeInfo(7L, "", -1, -1, false, true, "", false),
+ new CompatibilityChangeInfo(8L, "", -1, -1, false, true, "", true));
}
@Test
@@ -123,12 +128,12 @@ public class PlatformCompatTest {
.build();
mPlatformCompat = new PlatformCompat(mContext, mCompatConfig);
assertThat(mPlatformCompat.listUIChanges()).asList().containsExactly(
- new CompatibilityChangeInfo(1L, "", -1, -1, false, false, ""),
- new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, ""),
- new CompatibilityChangeInfo(5L, "", /*enableAfter*/ -1,
- /*enableSince*/ Build.VERSION_CODES.Q, false, false, ""),
- new CompatibilityChangeInfo(6L, "", /*enableAfter*/ -1,
- /*enableSince*/ Build.VERSION_CODES.R, false, false, ""));
+ new CompatibilityChangeInfo(1L, "", -1, -1, false, false, "", false),
+ new CompatibilityChangeInfo(2L, "change2", -1, -1, true, false, "", false),
+ new CompatibilityChangeInfo(
+ 5L, "", Build.VERSION_CODES.P, -1, false, false, "", false),
+ new CompatibilityChangeInfo(
+ 6L, "", Build.VERSION_CODES.Q, -1, false, false, "", false));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 17324bab70d2..9c28c99fcc07 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -460,6 +460,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
}
@Override
+ KeyChain.KeyChainConnection keyChainBind() {
+ return services.keyChainConnection;
+ }
+
+ @Override
KeyChain.KeyChainConnection keyChainBindAsUser(UserHandle user) {
return services.keyChainConnection;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index c1b1133dbb22..39fa20e4153f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1628,6 +1628,33 @@ public class DevicePolicyManagerTest extends DpmTestBase {
)), eq(user));
}
+ @Test
+ public void testRemoveCredentialManagementApp() throws Exception {
+ final String packageName = "com.test.cred.mng";
+ Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+ intent.setData(Uri.parse("package:" + packageName));
+ dpms.mReceiver.setPendingResult(
+ new BroadcastReceiver.PendingResult(Activity.RESULT_OK,
+ "resultData",
+ /* resultExtras= */ null,
+ BroadcastReceiver.PendingResult.TYPE_UNREGISTERED,
+ /* ordered= */ true,
+ /* sticky= */ false,
+ /* token= */ null,
+ CALLER_USER_HANDLE,
+ /* flags= */ 0));
+ when(getServices().keyChainConnection.getService().hasCredentialManagementApp())
+ .thenReturn(true);
+ when(getServices().keyChainConnection.getService().getCredentialManagementAppPackageName())
+ .thenReturn(packageName);
+
+ dpms.mReceiver.onReceive(mContext, intent);
+
+ flushTasks(dpms);
+ verify(getServices().keyChainConnection.getService()).hasCredentialManagementApp();
+ verify(getServices().keyChainConnection.getService()).removeCredentialManagementApp();
+ }
+
/**
* Simple test for delegate set/get and general delegation. Tests verifying that delegated
* privileges can acually be exercised by a delegate are not covered here.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/EnterpriseSpecificIdCalculatorTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/EnterpriseSpecificIdCalculatorTest.java
new file mode 100644
index 000000000000..c2c1d5b4f3be
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/EnterpriseSpecificIdCalculatorTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class EnterpriseSpecificIdCalculatorTest {
+ private static final String SOME_IMEI = "56134231542345";
+ private static final String SOME_SERIAL_NUMBER = "XZ663CCAJA7";
+ private static final String SOME_MAC_ADDRESS = "65:ca:f3:fe:9d:b1";
+ private static final String NO_MEID = null;
+ private static final String SOME_PACKAGE = "com.example.test.dpc";
+ private static final String ANOTHER_PACKAGE = "org.example.test.another.dpc";
+ private static final String SOME_ENTERPRISE_ID = "73456234";
+ private static final String ANOTHER_ENTERPRISE_ID = "243441";
+
+ private EnterpriseSpecificIdCalculator mEsidCalculator;
+
+ @Before
+ public void createDefaultEsidCalculator() {
+ mEsidCalculator = new EnterpriseSpecificIdCalculator(SOME_IMEI, NO_MEID, SOME_SERIAL_NUMBER,
+ SOME_MAC_ADDRESS);
+ }
+
+ @Test
+ public void paddingOfIdentifiers() {
+ assertThat(mEsidCalculator.getPaddedImei()).isEqualTo(" 56134231542345");
+ assertThat(mEsidCalculator.getPaddedMeid()).isEqualTo(" ");
+ assertThat(mEsidCalculator.getPaddedSerialNumber()).isEqualTo(" XZ663CCAJA7");
+ }
+
+ @Test
+ public void truncationOfLongIdentifier() {
+ EnterpriseSpecificIdCalculator esidCalculator = new EnterpriseSpecificIdCalculator(
+ SOME_IMEI, NO_MEID, "XZ663CCAJA7XZ663CCAJA7XZ663CCAJA7",
+ SOME_MAC_ADDRESS);
+ assertThat(esidCalculator.getPaddedSerialNumber()).isEqualTo("XZ663CCAJA7XZ663");
+ }
+
+ @Test
+ public void paddingOfPackageName() {
+ assertThat(mEsidCalculator.getPaddedProfileOwnerName(SOME_PACKAGE)).isEqualTo(
+ " " + SOME_PACKAGE);
+ }
+
+ @Test
+ public void paddingOfEnterpriseId() {
+ assertThat(mEsidCalculator.getPaddedEnterpriseId(SOME_ENTERPRISE_ID)).isEqualTo(
+ " " + SOME_ENTERPRISE_ID);
+ }
+
+ @Test
+ public void emptyEnterpriseIdYieldsEmptyEsid() {
+ assertThrows(IllegalArgumentException.class, () ->
+ mEsidCalculator.calculateEnterpriseId(SOME_PACKAGE, ""));
+ }
+
+ @Test
+ public void emptyDpcPackageYieldsEmptyEsid() {
+ assertThrows(IllegalArgumentException.class, () ->
+ mEsidCalculator.calculateEnterpriseId("", SOME_ENTERPRISE_ID));
+ }
+
+ // On upgrade, an ESID will be calculated with an empty Enterprise ID. This is signalled
+ // to the EnterpriseSpecificIdCalculator by passing in null.
+ @Test
+ public void nullEnterpriseIdYieldsValidEsid() {
+ assertThat(mEsidCalculator.calculateEnterpriseId(SOME_PACKAGE, null)).isEqualTo(
+ "C4W7-VUJT-PHSA-HMY53-CLHX-L4HW-L");
+ }
+
+ @Test
+ public void knownValues() {
+ assertThat(
+ mEsidCalculator.calculateEnterpriseId(SOME_PACKAGE, SOME_ENTERPRISE_ID)).isEqualTo(
+ "FP7B-RXQW-Q77F-7J6FC-5RXZ-UJI6-6");
+ assertThat(mEsidCalculator.calculateEnterpriseId(SOME_PACKAGE,
+ ANOTHER_ENTERPRISE_ID)).isEqualTo("ATAL-VPIX-GBNZ-NE3TF-TDEV-3OVO-C");
+ assertThat(mEsidCalculator.calculateEnterpriseId(ANOTHER_PACKAGE,
+ SOME_ENTERPRISE_ID)).isEqualTo("JHU3-6SHH-YLHC-ZGETD-PWNI-7NPQ-S");
+ assertThat(mEsidCalculator.calculateEnterpriseId(ANOTHER_PACKAGE,
+ ANOTHER_ENTERPRISE_ID)).isEqualTo("LEF3-QBEC-UQ6O-RIOCX-TQF6-GRLV-F");
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
index 9c8a38219a9c..ac9316e7d908 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/NetworkWatchlistServiceTests.java
@@ -24,6 +24,9 @@ import static org.junit.Assert.fail;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -106,6 +109,16 @@ public class NetworkWatchlistServiceTests {
counter--;
return true;
}
+
+ // TODO: mark @Override when aosp/1541935 automerges to master.
+ public void logDefaultNetworkValidity(boolean valid) {
+ }
+
+ // TODO: mark @Override when aosp/1541935 automerges to master.
+ public void logDefaultNetworkEvent(Network defaultNetwork, int score, boolean validated,
+ LinkProperties lp, NetworkCapabilities nc, Network previousDefaultNetwork,
+ int previousScore, LinkProperties previousLp, NetworkCapabilities previousNc) {
+ }
};
ServiceThread mHandlerThread;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
index 475e462bdd3d..009c011105de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
@@ -31,13 +31,17 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import android.app.WaitResult;
+import android.content.ComponentName;
import android.content.pm.ActivityInfo;
+import android.os.ConditionVariable;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
@@ -58,6 +62,7 @@ import java.util.concurrent.TimeUnit;
@Presubmit
@RunWith(WindowTestRunner.class)
public class ActivityTaskSupervisorTests extends WindowTestsBase {
+ private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
/**
* Ensures that an activity is removed from the stopping activities list once it is resumed.
@@ -74,30 +79,72 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase {
}
/**
- * Ensures that waiting results are notified of launches.
+ * Assume an activity has been started with result code START_SUCCESS. And before it is drawn,
+ * it launches another existing activity. This test ensures that waiting results are notified
+ * or updated while the result code of next launch is TASK_TO_FRONT or DELIVERED_TO_TOP.
*/
@Test
- public void testReportWaitingActivityLaunchedIfNeeded() {
+ public void testReportWaitingActivityLaunched() {
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
.setCreateTask(true).build();
-
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setCreateTask(true).build();
+ final ConditionVariable condition = new ConditionVariable();
final WaitResult taskToFrontWait = new WaitResult();
- mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait);
- // #notifyAll will be called on the ActivityTaskManagerService#mGlobalLock. The lock is hold
- // implicitly by WindowManagerGlobalLockRule.
- mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_TASK_TO_FRONT);
-
- assertThat(mSupervisor.mWaitingActivityLaunched).isEmpty();
+ final ComponentName[] launchedComponent = { null };
+ // Create a new thread so the waiting method in test can be notified.
+ new Thread(() -> {
+ synchronized (mAtm.mGlobalLock) {
+ // Note that TASK_TO_FRONT doesn't unblock the waiting thread.
+ mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity,
+ START_TASK_TO_FRONT);
+ launchedComponent[0] = taskToFrontWait.who;
+ // Assume that another task is brought to front because first activity launches it.
+ mSupervisor.reportActivityLaunched(false /* timeout */, secondActivity,
+ 100 /* totalTime */, WaitResult.LAUNCH_STATE_HOT);
+ }
+ condition.open();
+ }).start();
+ final ActivityMetricsLogger.LaunchingState launchingState =
+ new ActivityMetricsLogger.LaunchingState();
+ spyOn(launchingState);
+ doReturn(true).when(launchingState).contains(eq(secondActivity));
+ // The test case already runs inside global lock, so above thread can only execute after
+ // this waiting method that releases the lock.
+ mSupervisor.waitActivityVisibleOrLaunched(taskToFrontWait, firstActivity, launchingState);
+
+ // Assert that the thread is finished.
+ assertTrue(condition.block(TIMEOUT_MS));
assertEquals(taskToFrontWait.result, START_TASK_TO_FRONT);
- assertNull(taskToFrontWait.who);
+ assertEquals(taskToFrontWait.who, secondActivity.mActivityComponent);
+ assertEquals(taskToFrontWait.launchState, WaitResult.LAUNCH_STATE_HOT);
+ // START_TASK_TO_FRONT means that another component will be visible, so the component
+ // should not be assigned as the first activity.
+ assertNull(launchedComponent[0]);
+ condition.close();
final WaitResult deliverToTopWait = new WaitResult();
- mSupervisor.mWaitingActivityLaunched.add(deliverToTopWait);
- mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_DELIVERED_TO_TOP);
-
- assertThat(mSupervisor.mWaitingActivityLaunched).isEmpty();
+ new Thread(() -> {
+ synchronized (mAtm.mGlobalLock) {
+ // Put a noise which isn't tracked by the current wait result. The waiting procedure
+ // should ignore it and keep waiting for the target activity.
+ mSupervisor.reportActivityLaunched(false /* timeout */, mock(ActivityRecord.class),
+ 1000 /* totalTime */, WaitResult.LAUNCH_STATE_COLD);
+ // Assume that the first activity launches an existing top activity, so the waiting
+ // thread should be unblocked.
+ mSupervisor.reportWaitingActivityLaunchedIfNeeded(secondActivity,
+ START_DELIVERED_TO_TOP);
+ }
+ condition.open();
+ }).start();
+ mSupervisor.waitActivityVisibleOrLaunched(deliverToTopWait, firstActivity, launchingState);
+
+ assertTrue(condition.block(TIMEOUT_MS));
assertEquals(deliverToTopWait.result, START_DELIVERED_TO_TOP);
- assertEquals(deliverToTopWait.who, firstActivity.mActivityComponent);
+ assertEquals(deliverToTopWait.who, secondActivity.mActivityComponent);
+ // The result state must be unknown because DELIVERED_TO_TOP means that the target activity
+ // is already visible so there is no valid launch time.
+ assertEquals(deliverToTopWait.launchState, WaitResult.LAUNCH_STATE_UNKNOWN);
}
/**
@@ -202,7 +249,6 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase {
public void testStartHomeAfterUserUnlocked() {
mSupervisor.onUserUnlocked(0);
waitHandlerIdle(mAtm.mH);
- verify(mRootWindowContainer, timeout(TimeUnit.SECONDS.toMillis(10)))
- .startHomeOnEmptyDisplays("userUnlocked");
+ verify(mRootWindowContainer, timeout(TIMEOUT_MS)).startHomeOnEmptyDisplays("userUnlocked");
}
}
diff --git a/services/translation/Android.bp b/services/translation/Android.bp
new file mode 100644
index 000000000000..804a6177e94e
--- /dev/null
+++ b/services/translation/Android.bp
@@ -0,0 +1,13 @@
+filegroup {
+ name: "services.translation-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library_static {
+ name: "services.translation",
+ defaults: ["platform_service_defaults"],
+ srcs: [":services.translation-sources"],
+ libs: ["services.core"],
+} \ No newline at end of file
diff --git a/services/translation/OWNERS b/services/translation/OWNERS
new file mode 100644
index 000000000000..a1e663aa8ff7
--- /dev/null
+++ b/services/translation/OWNERS
@@ -0,0 +1,8 @@
+# Bug component: 994311
+
+adamhe@google.com
+augale@google.com
+joannechung@google.com
+lpeter@google.com
+svetoslavganov@google.com
+tymtsai@google.com
diff --git a/services/translation/java/com/android/server/translation/RemoteTranslationService.java b/services/translation/java/com/android/server/translation/RemoteTranslationService.java
new file mode 100644
index 000000000000..0c7e61765501
--- /dev/null
+++ b/services/translation/java/com/android/server/translation/RemoteTranslationService.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.translation;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.service.translation.ITranslationService;
+import android.service.translation.TranslationService;
+import android.util.Slog;
+import android.view.translation.TranslationSpec;
+
+import com.android.internal.infra.AbstractRemoteService;
+import com.android.internal.infra.ServiceConnector;
+import com.android.internal.os.IResultReceiver;
+
+final class RemoteTranslationService extends ServiceConnector.Impl<ITranslationService> {
+
+ private static final String TAG = RemoteTranslationService.class.getSimpleName();
+
+ // TODO(b/176590870): Make PERMANENT now.
+ private static final long TIMEOUT_IDLE_UNBIND_MS =
+ AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS;
+ private static final int TIMEOUT_REQUEST_MS = 5_000;
+
+ private final long mIdleUnbindTimeoutMs;
+ private final int mRequestTimeoutMs;
+ private final ComponentName mComponentName;
+
+ RemoteTranslationService(Context context, ComponentName serviceName,
+ int userId, boolean bindInstantServiceAllowed) {
+ super(context,
+ new Intent(TranslationService.SERVICE_INTERFACE).setComponent(serviceName),
+ bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
+ userId, ITranslationService.Stub::asInterface);
+ mIdleUnbindTimeoutMs = TIMEOUT_IDLE_UNBIND_MS;
+ mRequestTimeoutMs = TIMEOUT_REQUEST_MS;
+ mComponentName = serviceName;
+
+ // Bind right away.
+ connect();
+ }
+
+ public ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ @Override // from ServiceConnector.Impl
+ protected void onServiceConnectionStatusChanged(ITranslationService service,
+ boolean connected) {
+ try {
+ if (connected) {
+ service.onConnected();
+ } else {
+ service.onDisconnected();
+ }
+ } catch (Exception e) {
+ Slog.w(TAG,
+ "Exception calling onServiceConnectionStatusChanged(" + connected + "): ", e);
+ }
+ }
+
+ @Override // from AbstractRemoteService
+ protected long getAutoDisconnectTimeoutMs() {
+ return mIdleUnbindTimeoutMs;
+ }
+
+ public void onSessionCreated(@NonNull TranslationSpec sourceSpec,
+ @NonNull TranslationSpec destSpec, int sessionId, IResultReceiver resultReceiver) {
+ run((s) -> s.onCreateTranslationSession(sourceSpec, destSpec, sessionId, resultReceiver));
+ }
+}
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerService.java b/services/translation/java/com/android/server/translation/TranslationManagerService.java
new file mode 100644
index 000000000000..e2aabe6a89ea
--- /dev/null
+++ b/services/translation/java/com/android/server/translation/TranslationManagerService.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.translation;
+
+import static android.content.Context.TRANSLATION_MANAGER_SERVICE;
+import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_FAIL;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.translation.ITranslationManager;
+import android.view.translation.TranslationSpec;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.server.infra.AbstractMasterSystemService;
+import com.android.server.infra.FrameworkResourcesServiceNameResolver;
+
+/**
+ * Entry point service for translation management.
+ *
+ * <p>This service provides the {@link ITranslationManager} implementation and keeps a list of
+ * {@link TranslationManagerServiceImpl} per user; the real work is done by
+ * {@link TranslationManagerServiceImpl} itself.
+ */
+public final class TranslationManagerService
+ extends AbstractMasterSystemService<TranslationManagerService,
+ TranslationManagerServiceImpl> {
+
+ private static final String TAG = "TranslationManagerService";
+
+ public TranslationManagerService(Context context) {
+ // TODO: Discuss the disallow policy
+ super(context, new FrameworkResourcesServiceNameResolver(context,
+ com.android.internal.R.string.config_defaultTranslationService),
+ /* disallowProperty */ null, PACKAGE_UPDATE_POLICY_REFRESH_EAGER);
+ }
+
+ @Override
+ protected TranslationManagerServiceImpl newServiceLocked(int resolvedUserId, boolean disabled) {
+ return new TranslationManagerServiceImpl(this, mLock, resolvedUserId, disabled);
+ }
+
+ final class TranslationManagerServiceStub extends ITranslationManager.Stub {
+ @Override
+ public void getSupportedLocales(IResultReceiver receiver, int userId)
+ throws RemoteException {
+ synchronized (mLock) {
+ final TranslationManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.getSupportedLocalesLocked(receiver);
+ } else {
+ Slog.v(TAG, "getSupportedLocales(): no service for " + userId);
+ receiver.send(STATUS_SYNC_CALL_FAIL, null);
+ }
+ }
+ }
+
+ @Override
+ public void onSessionCreated(TranslationSpec sourceSpec, TranslationSpec destSpec,
+ int sessionId, IResultReceiver receiver, int userId) throws RemoteException {
+ synchronized (mLock) {
+ final TranslationManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.onSessionCreatedLocked(sourceSpec, destSpec, sessionId, receiver);
+ } else {
+ Slog.v(TAG, "onSessionCreated(): no service for " + userId);
+ receiver.send(STATUS_SYNC_CALL_FAIL, null);
+ }
+ }
+ }
+ }
+
+ @Override // from SystemService
+ public void onStart() {
+ publishBinderService(TRANSLATION_MANAGER_SERVICE,
+ new TranslationManagerService.TranslationManagerServiceStub());
+ }
+}
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
new file mode 100644
index 000000000000..b1f6f80d4158
--- /dev/null
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.translation;
+
+import static android.view.translation.TranslationManager.STATUS_SYNC_CALL_SUCCESS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.RemoteException;
+import android.service.translation.TranslationServiceInfo;
+import android.util.Slog;
+import android.view.translation.TranslationSpec;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.SyncResultReceiver;
+import com.android.server.infra.AbstractPerUserSystemService;
+
+import java.util.ArrayList;
+
+final class TranslationManagerServiceImpl extends
+ AbstractPerUserSystemService<TranslationManagerServiceImpl, TranslationManagerService> {
+
+ private static final String TAG = "TranslationManagerServiceImpl";
+
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteTranslationService mRemoteTranslationService;
+
+ @GuardedBy("mLock")
+ @Nullable
+ private ServiceInfo mRemoteTranslationServiceInfo;
+
+ protected TranslationManagerServiceImpl(
+ @NonNull TranslationManagerService master,
+ @NonNull Object lock, int userId, boolean disabled) {
+ super(master, lock, userId);
+ updateRemoteServiceLocked();
+ }
+
+ @GuardedBy("mLock")
+ @Override // from PerUserSystemService
+ protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent)
+ throws PackageManager.NameNotFoundException {
+ final TranslationServiceInfo info = new TranslationServiceInfo(getContext(),
+ serviceComponent, isTemporaryServiceSetLocked(), mUserId);
+ mRemoteTranslationServiceInfo = info.getServiceInfo();
+ return info.getServiceInfo();
+ }
+
+ @GuardedBy("mLock")
+ @Override // from PerUserSystemService
+ protected boolean updateLocked(boolean disabled) {
+ final boolean enabledChanged = super.updateLocked(disabled);
+ updateRemoteServiceLocked();
+ return enabledChanged;
+ }
+
+ /**
+ * Updates the reference to the remote service.
+ */
+ @GuardedBy("mLock")
+ private void updateRemoteServiceLocked() {
+ if (mRemoteTranslationService != null) {
+ if (mMaster.debug) Slog.d(TAG, "updateRemoteService(): destroying old remote service");
+ mRemoteTranslationService.unbind();
+ mRemoteTranslationService = null;
+ }
+ }
+
+ @GuardedBy("mLock")
+ @Nullable
+ private RemoteTranslationService ensureRemoteServiceLocked() {
+ if (mRemoteTranslationService == null) {
+ final String serviceName = getComponentNameLocked();
+ if (serviceName == null) {
+ if (mMaster.verbose) {
+ Slog.v(TAG, "ensureRemoteServiceLocked(): no service component name.");
+ }
+ return null;
+ }
+ final ComponentName serviceComponent = ComponentName.unflattenFromString(serviceName);
+ mRemoteTranslationService = new RemoteTranslationService(getContext(),
+ serviceComponent, mUserId, /* isInstantAllowed= */ false);
+ }
+ return mRemoteTranslationService;
+ }
+
+ @GuardedBy("mLock")
+ void getSupportedLocalesLocked(@NonNull IResultReceiver resultReceiver) {
+ // TODO: implement this
+ try {
+ resultReceiver.send(STATUS_SYNC_CALL_SUCCESS,
+ SyncResultReceiver.bundleFor(new ArrayList<>()));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException returning supported locales: " + e);
+ }
+ }
+
+ @GuardedBy("mLock")
+ void onSessionCreatedLocked(@NonNull TranslationSpec sourceSpec,
+ @NonNull TranslationSpec destSpec, int sessionId, IResultReceiver resultReceiver) {
+ final RemoteTranslationService remoteService = ensureRemoteServiceLocked();
+ if (remoteService != null) {
+ remoteService.onSessionCreated(sourceSpec, destSpec, sessionId, resultReceiver);
+ }
+ }
+}